diff --git a/src/__tests__/test-process-tpl.js b/src/__tests__/test-process-tpl.js index 2e09da7..8fa26f8 100644 --- a/src/__tests__/test-process-tpl.js +++ b/src/__tests__/test-process-tpl.js @@ -4,6 +4,7 @@ import processTpl, { genLinkReplaceSymbol, genModuleScriptReplaceSymbol, genScriptReplaceSymbol, + processCssContent, } from '../process-tpl'; test('test process-tpl', () => { @@ -318,3 +319,26 @@ test('should work with huge html content', () => { const during = Date.now() - start; expect(during < 1000).toBeTruthy(); }); + +test('test process url in external css resources', () => { + const transformedStyleText = processCssContent('//cdntest.com/css/ui.css', ` + @import 'component1.css' + @import url('component2.less') + .test-notice { + background: #ffffff url(../images/bg1.jpg) no-repeat center left; + background-image: url( '../images/bg2.jpg' ); + background-image: url("../images/bg3.jpg"); + background-image: url("//test.com/images/bg4.jpg"); + background-image: url("http://test.com/images/bg5.jpg"); + }; + /*# sourceMappingURL=test-notice.css.map */ + `); + expect(transformedStyleText.indexOf('//cdntest.com/css/component1.css') !== -1).toBeTruthy(); + expect(transformedStyleText.indexOf('//cdntest.com/css/component2.less') !== -1).toBeTruthy(); + expect(transformedStyleText.indexOf('//cdntest.com/images/bg1.jpg') !== -1).toBeTruthy(); + expect(transformedStyleText.indexOf('//cdntest.com/images/bg2.jpg') !== -1).toBeTruthy(); + expect(transformedStyleText.indexOf('//cdntest.com/images/bg3.jpg') !== -1).toBeTruthy(); + expect(transformedStyleText.indexOf('//test.com/images/bg4.jpg') !== -1).toBeTruthy(); + expect(transformedStyleText.indexOf('http://test.com/images/bg5.jpg') !== -1).toBeTruthy(); + expect(transformedStyleText.indexOf('//cdntest.com/css/test-notice.css.map') !== -1).toBeTruthy(); +}); \ No newline at end of file diff --git a/src/index.js b/src/index.js index 28fd294..a096a68 100644 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,7 @@ * @since 2018-08-15 11:37 */ -import processTpl, { genLinkReplaceSymbol, genScriptReplaceSymbol } from './process-tpl'; +import processTpl, { genLinkReplaceSymbol, genScriptReplaceSymbol, processCssContent } from './process-tpl'; import { defaultGetPublicPath, getGlobalProp, @@ -40,7 +40,8 @@ function getEmbedHTML(template, styles, opts = {}) { return getExternalStyleSheets(styles, fetch) .then(styleSheets => { embedHTML = styles.reduce((html, styleSrc, i) => { - html = html.replace(genLinkReplaceSymbol(styleSrc), ``); + const styleText = processCssContent(styleSrc, styleSheets[i]); + html = html.replace(genLinkReplaceSymbol(styleSrc), ``); return html; }, embedHTML); return embedHTML; diff --git a/src/process-tpl.js b/src/process-tpl.js index bdd1b2e..19c55d3 100644 --- a/src/process-tpl.js +++ b/src/process-tpl.js @@ -30,7 +30,13 @@ function hasProtocol(url) { } function getEntirePath(path, baseURI) { - return new URL(path, baseURI).toString(); + // 防止new URL(path, '//xxx...')这种形式报错: Invalid base URL + // by daniel@2021-06-22 + let newBaseURI = baseURI; + if (baseURI.indexOf('//') === 0) { + newBaseURI = 'http:' + baseURI; + } + return new URL(path, newBaseURI).toString(); } function isValidJavaScriptType(type) { @@ -43,7 +49,32 @@ export const genScriptReplaceSymbol = (scriptSrc, async = false) => ``; export const genIgnoreAssetReplaceSymbol = url => ``; export const genModuleScriptReplaceSymbol = (scriptSrc, moduleSupport) => ``; +/** + * process the css content, transform the relative url in external css to absolute path. + * + * @author Daniel + * @since 2021-06-22 + * @param {string} styleSrc the external css link + * @param {string} styleText the fetched css content + * @returns + */ + export const processCssContent = (styleSrc, styleText) => { + const replacement = function (match, prefix, path, suffix) { + if (hasProtocol(path)) { + return match; + } + const newHref = getEntirePath(path, styleSrc); + return prefix + newHref + suffix; + }; + + const transformedStyleText = styleText + .replace(/(@import\s*['"])([^'"]+)(['"])/g, replacement) // transform leading `@import 'xxx.css'` + .replace(/(url\(\s*['"]?)([^'"\s\(\)]+)(['"]?\s*\))/g, replacement) // transform `url(xxx.jpg)` + .replace(/(\/[*\/][@#] sourceMappingURL=)(\S+)(( \*\/)?[\r\n]*)$/mg, replacement); // transform trailing `sourceMappingURL=xxx.map` + + return transformedStyleText; +}; /** * parse the script link from the template * 1. collect stylesheets