UNPKG

@hippy/vue-css-loader

Version:

hippy-vue style loader module for webpack

85 lines (77 loc) 2.94 kB
/* * Tencent is pleased to support the open source community by making * Hippy available. * * Copyright (C) 2017-2022 THL A29 Limited, a Tencent company. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import crypto from 'crypto'; import { getOptions } from 'loader-utils'; import { GLOBAL_STYLE_NAME, GLOBAL_DISPOSE_STYLE_NAME } from '@vue/runtime/constants'; import parseCSS from './css-parser'; import translateColor, { names as colorNames } from './color-parser'; let sourceId = 0; /** * Convert the CSS text to AST that able to parse by selector parser. */ function hippyVueCSSLoader(this: any, source: any) { const options = getOptions(this); const parsed = parseCSS(source, { source: sourceId }); const majorNodeVersion = parseInt(process.versions.node.split('.')[0], 10); const hashType = majorNodeVersion >= 17 ? 'md5' : 'md4'; const hash = crypto.createHash(hashType); const contentHash = hash.update(source).digest('hex'); sourceId += 1; const rulesAst = parsed.stylesheet.rules.filter((n: any) => n.type === 'rule').map((n: any) => ({ hash: contentHash, selectors: n.selectors, declarations: n.declarations.map((dec: any) => { let { value } = dec; const isVariableColor = dec.property?.startsWith('-') && typeof value === 'string' && ( value.includes('#') || value.includes('rgb') || value.includes('hls') || value.includes('hue') || value.trim() in colorNames ); if (dec.property && (dec.property.toLowerCase().indexOf('color') > -1 || isVariableColor)) { value = translateColor(value); } return { type: dec.type, property: dec.property, value, }; }), })); const code = `(function() { if (!global['${GLOBAL_STYLE_NAME}']) { global['${GLOBAL_STYLE_NAME}'] = []; } global['${GLOBAL_STYLE_NAME}'] = global['${GLOBAL_STYLE_NAME}'].concat(${JSON.stringify(rulesAst)}); if(module.hot) { module.hot.dispose(() => { console.log('disposeHandlers'); if(!global['${GLOBAL_DISPOSE_STYLE_NAME}']) { global['${GLOBAL_DISPOSE_STYLE_NAME}'] = []; } global['${GLOBAL_DISPOSE_STYLE_NAME}'] = global['${GLOBAL_DISPOSE_STYLE_NAME}'].concat('${contentHash}'); }) } })()`; return `module.exports=${code}`; } export default hippyVueCSSLoader;