Skip to content

Commit

Permalink
fix(sourcemap): more reliable detection
Browse files Browse the repository at this point in the history
  • Loading branch information
Anidetrix committed May 7, 2020
1 parent 969697d commit a419361
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 47 deletions.
21 changes: 12 additions & 9 deletions __tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import loadModule from "../src/utils/load-module";
import { fixture } from "./helpers";
import { mm, getExtractedMap, getInlineMap, stripMap } from "../src/utils/sourcemap";
import { mm, getMap, stripMap } from "../src/utils/sourcemap";

describe("load-module", () => {
test("wrong path", async () => {
Expand All @@ -20,21 +20,24 @@ describe("load-module", () => {
});

describe("sourcemap-utils", () => {
test("inline map", () => {
let code = ".foo {color: red;}";
const wrongMap = getInlineMap(code);
expect(wrongMap).toBeUndefined();
test("inline map", async () => {
let code =
'.foo {color: red;background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAG1BMVEXMzMyWlpacnJy+vr6jo6PFxcW3t7eqqqqxsbHbm8QuAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAiklEQVRYhe3QMQ6EIBAF0C+GSInF9mYTs+1ewRsQbmBlayysKefYO2asXbbYxvxHQj6ECQMAEREREf2NQ/fCtp5Zky6vtRMkSJEzhyISynWJnzH6Z8oQlzS7lEc/fLmmQUSvc16OrCPqRl1JePxQYo1ZSWVj9nxrrOb5esw+eXdvzTWfTERERHRXH4tWFZGswQ2yAAAAAElFTkSuQmCC");}';
const noMap = await getMap(code);
expect(noMap).toBeUndefined();
code +=
"/*# sourceMappingURL=data:application/json;base64,e1RISVM6SVNBU09VUkNFTUFQU0lNVUxBVElPTn0= */";
const correctMap = getInlineMap(code);
const correctMap = await getMap(code);
expect(correctMap).toBe("{THIS:ISASOURCEMAPSIMULATION}");
});

test("file map", async () => {
const code = ".foo {color: red;}/*# sourceMappingURL=fixture.css.map */";
const wrongMap = await getExtractedMap(code, "this/is/nonexistant/path.css");
expect(wrongMap).toBeUndefined();
const correctMap = await getExtractedMap(code, fixture("utils/pointless.css"));
const noPathMap = await getMap(code);
expect(noPathMap).toBeUndefined();
const wrongPathMap = await getMap(code, "this/is/nonexistant/path.css");
expect(wrongPathMap).toBeUndefined();
const correctMap = await getMap(code, fixture("utils/pointless.css"));
expect(correctMap).toBe("{THIS:ISASOURCEMAPSIMULATION}");
});

Expand Down
18 changes: 9 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 2 additions & 10 deletions src/loaders/postcss/url/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,9 @@ import valueParser, { Node, ParsedValue } from "postcss-value-parser";

const urlFuncRe = /^url$/i;
const imageSetFuncRe = /^(?:-webkit-)?image-set$/i;
const declWithUrlRe = new RegExp(
[
"(?:",
[urlFuncRe, imageSetFuncRe].map(re => re.source.replace("$", "")).join("|"),
")",
"\\(",
].join(""),
"i",
);

export const isDeclWithUrl = (decl: postcss.Declaration): boolean => declWithUrlRe.test(decl.value);
export const isDeclWithUrl = (decl: postcss.Declaration): boolean =>
/^(?:url|(?:-webkit-)?image-set)\(/i.test(decl.value);

export const walkUrls = (
parsed: ParsedValue,
Expand Down
28 changes: 9 additions & 19 deletions src/utils/sourcemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,24 @@ const mapBlockRe = /\/\*[#*@]+?\s*?sourceMappingURL\s*?=\s*?(\S+)\s*?\*+?\//;
const mapInlineRe = /\/\/[#@]+?\s*?sourceMappingURL\s*?=\s*?(\S+)\s*?(?:$|\n|\r\n)/;
const mapRe = new RegExp([mapBlockRe, mapInlineRe].map(re => re.source).join("|"));

export function getInlineMap(code: string): string | undefined {
if (!mapRe.test(code)) return;
const matches = dataURIRe.exec(code);
if (!matches || matches.length < 2) return;
return Buffer.from(matches[1], "base64").toString("utf8");
}
export async function getMap(code: string, id?: string): Promise<string | undefined> {
const [, data] = mapRe.exec(code) ?? [];
if (!data) return;

const [, inlineMap] = dataURIRe.exec(data) ?? [];
if (inlineMap) return Buffer.from(inlineMap, "base64").toString();

export async function getExtractedMap(code: string, id: string): Promise<string | undefined> {
if (dataURIRe.test(code)) return;
const matches = mapBlockRe.exec(code) ?? mapInlineRe.exec(code);
if (!matches || matches.length < 2) return;
const mapFileName = path.resolve(path.dirname(id), matches[1]);
if (!id) return;
const mapFileName = path.resolve(path.dirname(id), data);
try {
return await fs.readFile(mapFileName, "utf8");
} catch (error) {
return;
}
}

export async function getMap(code: string, id: string): Promise<string | undefined> {
let map = getInlineMap(code);
if (!map) map = await getExtractedMap(code, id);
return map;
}

export function stripMap(code: string): string {
if (!mapRe.test(code)) return code;
return code.replace(mapRe, "").replace(/\s+$/, "");
return code.replace(mapRe, "");
}

class MapModifier {
Expand Down

0 comments on commit a419361

Please sign in to comment.