diff --git a/docs.md b/docs.md index d75f024..92483d8 100644 --- a/docs.md +++ b/docs.md @@ -100,6 +100,7 @@ The rest: - `collect-all("Figure" 1 "." 3)` collects all the fields into a string. Useful for computing a link target because `target-context(...)` only allows 2 arguments - `if(1, true-condition, false-condition)` allows you to conditionally return something. An example would be to combine this with `is-even(...)` to remove all even answers from the back of the Book - `is-even(123)` returns `0` if the number is odd, and `111111` otherwise (truthy) +- `fetch-url('./icon.svg')` injects the contents of the file into the element - `x-tag-name()` find out current elements' tag name (ie 'div', 'pre', 'h1') - `x-throw()` throws an error (useful for unit tests) diff --git a/src/browser/functions.js b/src/browser/functions.js index d7c7414..c67c247 100644 --- a/src/browser/functions.js +++ b/src/browser/functions.js @@ -119,6 +119,12 @@ FUNCTIONS.push(new FunctionEvaluator('attr', (evaluator, astNode, $contextEl) => } return ret })) +FUNCTIONS.push(new FunctionEvaluator('fetch-url', (evaluator, astNode, $contextEl, $) => { + const url = evaluator.evaluateFirst() + const fetchNode = $(``) + fetchNode[0].__cssLocation = astNode + return fetchNode +})) let idCounter = 0 FUNCTIONS.push(new FunctionEvaluator('x-attr-ensure-id', (evaluator, astNode, $contextEl) => { const attrName = 'id' diff --git a/src/browser/main.js b/src/browser/main.js index 7e13377..b2e0482 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -136,8 +136,8 @@ module.exports = class Converter { } } - serialize (vanillaRules) { + serialize (vanillaRules, transcludedFilesMap) { vanillaRules = csstree.fromPlainObject(vanillaRules) - return serializer(this._engine, this._htmlSourceLookup, this._htmlSourcePath, this._sourceMapPath, vanillaRules, this._htmlOutputPath, this._isXml) + return serializer(this._engine, this._htmlSourceLookup, this._htmlSourcePath, this._sourceMapPath, vanillaRules, this._htmlOutputPath, this._isXml, transcludedFilesMap) } } diff --git a/src/browser/serializer.js b/src/browser/serializer.js index 550dbb8..da4e65f 100644 --- a/src/browser/serializer.js +++ b/src/browser/serializer.js @@ -21,7 +21,7 @@ const SELF_CLOSING_TAGS = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr' const XML_SKIP_TAGNAMES = ['html', 'head', 'body'] // We use a custom serializer so sourcemaps can be generated (we know the output line and columns for things) -module.exports = (engine, htmlSourceLookup, htmlSourcePath, htmlSourceMapPath, vanillaRules, htmlOutputPath, isXml) => { +module.exports = (engine, htmlSourceLookup, htmlSourcePath, htmlSourceMapPath, vanillaRules, htmlOutputPath, isXml, transcludedFilesMap) => { const coverageData = {} const documentElement = engine.getRoot() @@ -148,6 +148,17 @@ module.exports = (engine, htmlSourceLookup, htmlSourcePath, htmlSourceMapPath, v return } + // Inject any files that should be injected (SVG icons) + if (tagName === 'transcludeduringserialization') { + const url = node.getAttribute('url') + if (!transcludedFilesMap[url]) { + throwBug(`Could not find file named ${url}`) + } + pushAndMap(node, ``) + pushAndMap(node, transcludedFilesMap[url]) + return + } + pushAndMap(node, `<${tagName}`) for (let index = 0; index < node.attributes.length; index++) { @@ -186,6 +197,10 @@ module.exports = (engine, htmlSourceLookup, htmlSourcePath, htmlSourceMapPath, v if (isXml && XML_SKIP_TAGNAMES.indexOf(tagName) >= 0) { return } + // If the element is a _magic_ transclusion element then ignore it in the close as well + if (tagName === 'transcludeduringserialization') { + return + } // If we have vanilla rules then we need to inject them as a + + + + + diff --git a/test/unit/svg.out.xhtml b/test/unit/svg.out.xhtml new file mode 100644 index 0000000..fe84525 --- /dev/null +++ b/test/unit/svg.out.xhtml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/unit/svg.out.xhtml.txt b/test/unit/svg.out.xhtml.txt new file mode 100644 index 0000000..e69de29