PageSourceSearch

https://www.ry-elerelay.com/src/style.js

js ry-elerelay.com collected 2026-10-04 04:34:52 UTC 10,063 bytes, 287 lines download raw bytes

1import fontConfig from '../dist/font/config.js'
2
3class StyleData {
4  /**
5   * 构造函数
6   * @param {JSON} config
7   */
8  constructor(config, ctx) {
9    this.setBackgroundGradientColor(config)
10    Object.keys(config).forEach(key => {
11      // 非装修的时候,去掉空的字段
12      if (!ctx.query.design && config[key] === '') return
13      this[key] = config[key]
14    })
15  }
16
17  setBackgroundGradientColor(screenStyle) {
18    if (screenStyle?.linear && !screenStyle['--linear']) {
19      // 兼容旧数据
20      screenStyle['--linear'] = screenStyle?.linear
21    }
22  }
23
24  /**
25   * 背景图url格式转换
26   * @param src
27   * @returns {*}
28   */
29  convertBgImageUrl(src) {
30    const convertImgSrc = (src) => {
31      return globalThis.Server.getTransferImgUrl(src, {
32        thumbnail: {type: 3, scale: 100},
33        convert: {quality: 90, dst: 'webp'}
34      }, 'webp');
35    }
36    /**
37     * css背景色格式
38     * @type {RegExp}
39     */
40    const BG_IMG_PATTERN = /(url\()([^\)]*)(\))/i
41    /**
42     * 图片url
43     * @type {RegExp}
44     */
45    const URL_PATTERN = /^(https?:)?(\/\/[a-z0-9.:_-]+)?[a-z0-9\/.#&=?%_-]*$/i
46    return BG_IMG_PATTERN.test(src) ? src.replace(BG_IMG_PATTERN, function (m0, m1, m2, m3) {
47      return m1 + convertImgSrc(m2) + m3
48    }) : URL_PATTERN.test(src) ? convertImgSrc(src) : src;
49  }
50
51  /**
52   *
53   * @param ctx
54   * @param {string[]} guardProperties 保留属性
55   * @returns {string}
56   */
57  getDataString(ctx, guardProperties) {
58    const self = this;
59    let styleString = '{'
60    const defaultKeyList = ['sign', 'screen', 'selector', 'background-image-sign', 'background-image'].filter(property => !guardProperties.includes(property))
61    ctx.state.fontFamilyList = ctx.state.fontFamilyList || []
62    // 检测可以合并的样式
63    const combine = {padding: {}, margin: {}}
64    const directionMapping = {top: 0, right: 1, bottom: 2, left: 3}
65    Object.keys(this).forEach(key => {
66      if (['margin', 'padding'].includes(key.split('-')[0]) && this[key] !== '') {
67        combine[key.split('-')[0]][directionMapping[key.split('-')[1]]] = this[key]
68      }
69    })
70
71    Object.keys(combine).forEach(key => {
72      if (Object.keys(combine[key]).length === 4) {
73        styleString += `${key}:${Object.values(combine[key]).some(value => value !== combine[key][0]) ? Object.values(combine[key]).join(' ') : combine[key][0]};`
74      }
75    })
76
77    const fontMap = {'font-family': '', 'font-weight': ''}
78    const sortKey =  Object.keys(this).sort()
79    sortKey.forEach(key => {
80      if (
81        defaultKeyList.includes(key) ||
82        (['margin', 'padding'].includes(key.split('-')[0]) && Object.keys(combine[key.split('-')[0]]).length === 4)
83      ) {
84        return
85      }
86
87      if (key === 'background-image') {
88        const bgImg = this[key].trim().replace(/^([^(\s,]+)(.*)$/, (...matches) => {
89          if (matches[0]) {
90            if (/^[a-z_-]+\s*\(/i.test(matches[0])) {
91              // url() linear-gradient()
92              return matches[0];
93            } else {
94              return `url(${matches[1]})${matches[2]}`
95            }
96          } else {
97            return ''
98          }
99        })
100        const imgUrl = self.convertBgImageUrl(bgImg);
101        styleString += `${key}:${imgUrl};`
102      } else if (key === 'font-family' || key === 'font-weight') {
103        fontMap[key] = this[key]
104      } else {
105        styleString += `${key}:${this[key]};`
106      }
107    })
108
109    // ai页面禁用网络字体
110    if (fontMap['font-family'] && ctx.state.disabled_font) {
111      fontMap['font-family'] = ''
112    }
113
114    if (fontMap['font-family'] && ['auto', 'initial'].indexOf(fontMap['font-family'].toLowerCase()) === -1) {
115      if (fontConfig[fontMap['font-family']]) {
116        if (fontMap['font-weight'] && fontConfig[fontMap['font-family']][fontMap['font-weight']]) {
117          const fontSet = fontConfig[fontMap['font-family']][fontMap['font-weight']]
118          const fontFamily = fontSet['font-family']
119          styleString += `font-family:"${fontFamily}";`
120          ctx.state.fontFamilyList.push(fontFamily)
121          if (fontSet['font-weight']) {
122            styleString += `font-weight:${fontSet['font-weight']};`
123          }
124        } else {
125          // 取默认粗细
126          let defaultFamily = ''
127          for (let f in fontConfig[fontMap['font-family']]) {
128            if (!defaultFamily || fontConfig[fontMap['font-family']][f]['default']) {
129              defaultFamily = fontConfig[fontMap['font-family']][f]['font-family']
130            }
131          }
132          if (defaultFamily) {
133            styleString += `font-family:${defaultFamily};`
134            ctx.state.fontFamilyList.push(defaultFamily)
135          }
136        }
137      } else {
138        styleString += `font-family:${fontMap['font-family']};`
139        if (fontMap['font-weight']) {
140          styleString += `font-weight:${fontMap['font-weight']};`
141        }
142        ctx.state.fontFamilyList.push(fontMap['font-family'])
143      }
144    } else if (fontMap['font-weight']) {
145      styleString += `font-weight:${fontMap['font-weight']};`
146    }
147
148    styleString += '}'
149    return styleString
150  }
151}
152
153class StyleSelector {
154  /**
155   * 构造函数
156   * @param {JSON} config
157   */
158  constructor(ctx, data) {
159    // 如果是sign,需要取template.data.style[sign]
160    data = data || {}
161    if (typeof data === 'string') {
162      data = ctx.state.template.globalData.style[data] || {}
163    }
164    // default不能为空
165    data.default = data.default || {}
166    this.sign = data.sign || globalThis.Server.getSign()
167    this.md = new StyleData(data.md || {}, ctx)
168    this.xl = new StyleData(data.xl || {}, ctx)
169    this.default = new StyleData(data.default || {}, ctx)
170    // 如果不是装修,就去掉重复的样式
171    if (!ctx.query.design) {
172      if (this.default['font-family'] && !this.md['font-family']) {
173        this.md['font-family'] = this.default['font-family']
174      }
175      if (this.md['font-family'] && !this.xl['font-family']) {
176        this.xl['font-family'] = this.md['font-family']
177      }
178
179      // 字体及加粗需要同时判断重复,用于粗体字的载入
180      let fontMap = {'font-family': '', 'font-weight': ''}
181      Object.keys(this.md).forEach(attr => {
182        if (this.md[attr] === this.xl[attr]) {
183          if (attr === 'font-family' || attr === 'font-weight') {
184            fontMap[attr] = this.xl[attr]
185          }
186          delete this.xl[attr]
187        }
188      })
189      if (!fontMap['font-family'] || !fontMap['font-weight']) {
190        if (fontMap['font-family']) {
191          this.xl['font-family'] = fontMap['font-family']
192        }
193        if (fontMap['font-weight']) {
194          this.xl['font-weight'] = fontMap['font-weight']
195        }
196      }
197      fontMap = {'font-family': '', 'font-weight': ''}
198      Object.keys(this.default).forEach(attr => {
199        if (this.default[attr] === this.md[attr]) {
200          if (attr === 'font-family' || attr === 'font-weight') {
201            fontMap[attr] = this.md[attr]
202          }
203          delete this.md[attr]
204        }
205
206        if (
207          (!(this.default['--linear'] && this.default['--linear'] !== 'unset' && this.default['--linear'] !== 'none')
208            && !this.default['background-image'] && ['background-size', 'background-attachment', 'background-position', 'background-repeat'].includes(attr)) ||
209          (this.default[attr] === 'initial' && ['background-size', 'background-attachment'].includes(attr)) ||
210          (this.default[attr] === 'normal' && ['background-blend-mode'].includes(attr))
211        ) {
212          delete this.default[attr]
213        }
214      })
215      if (!fontMap['font-family'] || !fontMap['font-weight']) {
216        if (fontMap['font-family']) {
217          this.md['font-family'] = fontMap['font-family']
218        }
219        if (fontMap['font-weight']) {
220          this.md['font-weight'] = fontMap['font-weight']
221        }
222      }
223    }
224  }
225}
226
227class Style {
228  constructor(ctx, selectorConfig, attr_id) {
229    this.getInsideData = () => { return { ctx, attr_id } }
230    this.init(selectorConfig)
231  }
232  init(selector = {}) {
233    const { ctx } = this.getInsideData()
234    // 样式选择器的前半部分
235    // 选择器一定要有default
236    selector.default = selector.default || {}
237    // 循环所有选择器
238    Object.keys(selector).forEach(selectorKey => {
239      // 创建StyleSelector实例并赋值
240      if (selectorKey === 'getInsideData') return
241      this[selectorKey] = new StyleSelector(ctx, selector[selectorKey])
242    })
243  }
244
245  append(selector = {}) {
246    const { ctx } = this.getInsideData()
247    Object.keys(selector).forEach(selectorKey => {
248      // 创建StyleSelector实例并赋值
249      if (selectorKey === 'getInsideData') return
250      this[selectorKey] = new StyleSelector(ctx, selector[selectorKey])
251    })
252  }
253
254  /**
255   *
256   * @param mapping
257   * @param screen
258   * @param {string[]} guardProperties 保留属性
259   * @returns {{}}
260   */
261  getMapping(mapping = {}, screen = 'default', guardProperties = []) {
262    let { ctx,attr_id } = this.getInsideData()
263    Object.keys(this).forEach(selectorKey => {
264      if (typeof this[selectorKey] === 'function') return
265      let cssSelector = ''
266      let cssString = this[selectorKey][screen].getDataString(ctx, guardProperties)
267      // 如果css为空,不处理
268      if (cssString === '{}') return
269      // 如果有attr_id,那就是package的样式;导航菜单用于PC端及手机端
270      if (attr_id && !['[firstMenu]', '[subMenu]'].includes(selectorKey)) cssSelector += `#${attr_id}`
271      // 如果没有,选择器又是default,就是空的全局样式,不处理
272      else if (selectorKey === 'default') return
273      // 如果选择器不是default,就需要在完整的选择器后面加上该选择器
274      if (selectorKey !== 'default') cssSelector += ` ${selectorKey}`
275      // 把完整的选择器和样式拼接起来
276      if (mapping[cssString]) {
277        mapping[cssString].push(cssSelector)
278      } else {
279        mapping[cssString] = [cssSelector]
280      }
281    })
282
283    return mapping
284  }
285}
286
287export default Style

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.