Skip to content

Commit

Permalink
Transform xml-stylesheet processing instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
thewilkybarkid committed Aug 19, 2021
1 parent cef40c4 commit c56c775
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 14 deletions.
5 changes: 5 additions & 0 deletions flow-libs/posthtml.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ declare module 'posthtml' {
messages: Array<PostHTMLMessage>,
...
}>;
declare var match: (
expression: string | RegExp | Object | Array,
cb: (node: PostHTMLNode) => PostHTMLNode | PostHTMLNode[],
) => void;

declare class Api {
static walk: typeof walk;
walk: typeof walk;
process: typeof process;
match: typeof match;
}

declare class PostHTML extends Api {
Expand Down
22 changes: 12 additions & 10 deletions packages/core/integration-tests/test/svg.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ describe('svg', function() {
assert(file.includes('comment'));
});

it('should detect xml-stylesheet processing instructions', async function() {
let b = await bundle(
it('should turn xml-stylesheet processing instructions into styles', async function() {
const b = await bundle(
path.join(__dirname, '/integration/svg-xml-stylesheet/img.svg'),
);

Expand All @@ -70,21 +70,23 @@ describe('svg', function() {
},
{
type: 'css',
assets: ['style1.css'],
},
{
type: 'css',
assets: ['style3.css'],
assets: ['img.svg', 'style1.css', 'style3.css'],
},
]);

let file = await outputFS.readFile(
const svg = await outputFS.readFile(
b.getBundles().find(b => b.type === 'svg').filePath,
'utf-8',
);

assert(file.includes('<?xml-stylesheet'));
assert(file.includes('<?xml-not-a-stylesheet'));
assert(!svg.includes('style1.css'));
assert(!svg.includes('style3.css'));
assert(svg.includes('style2.css'));
assert(svg.includes('<?xml-not-a-stylesheet'));
assert(svg.includes('<style>'));
assert(!svg.includes('@import'));
assert(svg.includes(':root {\n fill: red;\n font-family: serif;\n}'));
assert(svg.includes(':root {\n font-family: monospace;\n}\n'));
});

it('should handle CSS with @imports', async function() {
Expand Down
31 changes: 27 additions & 4 deletions packages/transformers/svg/src/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@ const OPTIONS = {

export default function collectDependencies(asset: MutableAsset, ast: AST) {
let isDirty = false;
const stylesheets = [];
PostHTML().walk.call(ast.program, node => {
if (typeof node === 'string' && node.startsWith('<?xml-stylesheet')) {
return node.replace(/(?<=(?:^|\s)href\s*=\s*")(.+?)(?=")/i, href => {
isDirty = true;
const [, href] = node.match(/(?<=(?:^|\s)href\s*=\s*")(.+?)(?=")/i) ?? [];

return asset.addURLDependency(href, {priority: 'parallel'});
});
if (!href) {
return node;
}
stylesheets.push(href);

return [];
}

const {tag, attrs} = node;
Expand All @@ -50,6 +54,25 @@ export default function collectDependencies(asset: MutableAsset, ast: AST) {
return node;
});

if (stylesheets.length) {
PostHTML().match.call(ast.program, {tag: 'svg'}, node => {
if (!node.content) {
node.content = [];
}

const imports = stylesheets.map(href => `@import '${href}';`);

// $FlowFixMe
node.content.unshift({
tag: 'style',
content: imports,
});
isDirty = true;

return node;
});
}

if (isDirty) {
asset.setAST(ast);
}
Expand Down

0 comments on commit c56c775

Please sign in to comment.