Skip to content

Commit d369822

Browse files
author
huangchenbj
committed
fix: unescaped quote marks in style strings. Also add option to remove starting slash from path
1 parent 6c1ac56 commit d369822

File tree

4 files changed

+35
-20
lines changed

4 files changed

+35
-20
lines changed

src/core/transform.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {replace, replaceImport, replaceInStringLiteral, replaceInTemplateElement
44
import {StringAsBytes, collectMatchingStrings, parseCode} from "./ast";
55

66
export async function transformChunk(codeStr: string, options: TransformOptions): Promise<string> {
7-
const { base, publicPath } = options
7+
const { base, publicPath, removeStartingSlash } = options
88
const [spanOffset, ast] = await parseCode(codeStr);
99

1010
const strings = collectMatchingStrings(base, ast);
@@ -23,9 +23,9 @@ export async function transformChunk(codeStr: string, options: TransformOptions)
2323

2424
let transformed: string;
2525
if (str.type === 'TemplateElement') {
26-
transformed = replaceInTemplateElement(str, base, publicPath);
26+
transformed = replaceInTemplateElement(str, base, publicPath, removeStartingSlash);
2727
} else if (str.type === 'StringLiteral') {
28-
transformed = replaceInStringLiteral(str, base, publicPath);
28+
transformed = replaceInStringLiteral(str, base, publicPath, removeStartingSlash);
2929
}
3030

3131
lastIdx = str.span.end - spanOffset;
@@ -44,16 +44,20 @@ export function transformAsset(code: string, options: TransformOptions) {
4444
}
4545

4646
export function transformLegacyHtml(code: string, options: TransformOptions) {
47-
const { base, publicPath } = options
47+
const { base, publicPath, removeStartingSlash } = options
4848
let content = replaceSrc(publicPath, code)
4949
content = replace(base, '/', content)
5050
content = replaceImport(publicPath, content)
5151
const document = parse(content, { comment: true })
5252
const legacyPolyfill = document.getElementById('vite-legacy-polyfill')
53-
const legacyPolyfillSrc = legacyPolyfill?.getAttribute('src')
53+
let legacyPolyfillSrc = legacyPolyfill?.getAttribute('src')
5454

5555
const legacyEntry = document.getElementById('vite-legacy-entry')
56-
const legacyEntrySrc = legacyEntry?.getAttribute('data-src')
56+
let legacyEntrySrc = legacyEntry?.getAttribute('data-src')
57+
if (removeStartingSlash) {
58+
legacyPolyfillSrc = legacyPolyfillSrc?.replace(/^\//, '')
59+
legacyEntrySrc = legacyEntrySrc?.replace(/^\//, '')
60+
}
5761

5862
if (legacyPolyfill) {
5963
legacyPolyfill.setAttribute('data-src', legacyPolyfillSrc)

src/core/utils.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,39 @@ export function replaceImport(placeholder: string, code: string) {
1515
return code.replace(/(System.import\()/g, `$1${placeholder}+`)
1616
}
1717

18-
export function replaceInStringLiteral(literal: StringLiteral, base: string, placeholder: string): string {
18+
export function replaceInStringLiteral(literal: StringLiteral, base: string, placeholder: string, removeStartingSlash: boolean): string {
1919
const quoteMark = literal.raw.charAt(0);
2020
const regex = new RegExp(base, 'g');
2121
// Keep track of whether we need to add quotation marks at the beginning of the
2222
// final output
23-
let withStartQuote = true;
2423

25-
const transformedStr = literal.value.replace(regex, (match, index) => {
24+
const resourceStartingSlash = removeStartingSlash ? '' : '/';
25+
26+
/**
27+
* original StringLiteral may have escaped quote marks, so we need to use raw instead of value
28+
* otherwise, will fail on style strings such as
29+
* "@charset \"UTF-8\";cursor: url(/__vite_dynamic_public_path__/assets/cursor.svg);"
30+
*
31+
* since the value is
32+
* @charset "UTF-8";cursor: url(/__vite_dynamic_public_path__/assets/cursor.svg);
33+
*
34+
* and does not reflect the escaped quote marks
35+
*/
36+
const transformedStr = literal.raw.replace(regex, (match, index) => {
2637
let prefix = `${quoteMark}+`;
2738

2839
if (index === 0) {
2940
prefix = '';
30-
withStartQuote = false;
3141
}
3242

33-
return `${prefix}${placeholder}+${quoteMark}/`;
43+
return `${prefix}${placeholder}+${quoteMark}${resourceStartingSlash}`;
3444
});
3545

36-
const prefix = withStartQuote ? quoteMark : '';
37-
38-
return `${prefix}${transformedStr}${quoteMark}`;
46+
return `${transformedStr}`;
3947
}
4048

41-
export function replaceInTemplateElement(element: TemplateElement, base: string, placeholder: string): string {
49+
export function replaceInTemplateElement(element: TemplateElement, base: string, placeholder: string, removeStartingSlash: boolean): string {
50+
const resourceStartingSlash = removeStartingSlash ? '' : '/';
4251
const regex = new RegExp(base, 'g');
43-
return element.raw.replace(regex, () => '/${' + placeholder + '}/');
52+
return element.raw.replace(regex, () => '/${' + placeholder + '}' + resourceStartingSlash);
4453
}

src/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ export function dynamicBase(options?: Options): Plugin {
66
const defaultOptions: Options = {
77
publicPath: 'window.__dynamic_base__',
88
transformIndexHtml: false, // maybe default true
9-
transformIndexHtmlConfig: {}
9+
transformIndexHtmlConfig: {},
10+
removeStartingSlash: false
1011
}
1112

12-
const { publicPath, transformIndexHtml, transformIndexHtmlConfig } = { ...defaultOptions, ...(options || {}) }
13+
const { publicPath, transformIndexHtml, transformIndexHtmlConfig, removeStartingSlash } = { ...defaultOptions, ...(options || {}) }
1314

1415
// const preloadHelperId = 'vite/preload-helper'
1516
let assetsDir = 'assets'
1617
let base = '/'
1718
let legacy = false
18-
let baseOptions: TransformOptions = { assetsDir, base, legacy, publicPath: ` ${publicPath}`, transformIndexHtml }
19-
19+
let baseOptions: TransformOptions = { assetsDir, base, legacy, publicPath: ` ${publicPath}`, transformIndexHtml, removeStartingSlash }
20+
2021
return {
2122
name: 'vite-plugin-dynamic-base',
2223
enforce: 'post',

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export interface Options {
22
publicPath?: string,
3+
removeStartingSlash?: boolean,
34
transformIndexHtml?: boolean
45
transformIndexHtmlConfig?: TransformIndexHtmlConfig
56
}

0 commit comments

Comments
 (0)