Merge pull request #124 from sveltejs/raw-mustaches

Raw mustaches
pull/131/head
Rich Harris 9 years ago committed by GitHub
commit 4a89354409

@ -0,0 +1,47 @@
import deindent from '../utils/deindent.js';
export default {
enter ( generator, node ) {
const name = generator.current.counter( 'raw' );
generator.addSourcemapLocations( node.expression );
const { snippet } = generator.contextualise( node.expression );
// we would have used comments here, but the `insertAdjacentHTML` api only
// exists for `Element`s.
const before = `${name}_before`;
generator.addElement( before, `document.createElement( 'noscript' )`, true );
const after = `${name}_after`;
generator.addElement( after, `document.createElement( 'noscript' )`, true );
const isToplevel = generator.current.localElementDepth === 0;
const mountStatement = deindent`
${before}.insertAdjacentHTML( 'afterend', ${snippet} );
`;
const detachStatement = deindent`
while ( ${before}.nextSibling && ${before}.nextSibling !== ${after} ) {
${before}.parentNode.removeChild( ${before}.nextSibling );
}
`;
if ( isToplevel ) {
generator.current.mountStatements.push(mountStatement);
} else {
generator.current.initStatements.push(mountStatement);
}
generator.current.updateStatements.push( deindent`
${detachStatement}
${mountStatement}
` );
if ( isToplevel ) {
const { detachStatements } = generator.current;
// we need `before` and `after` to still be in the DOM when running the
// detach code, so splice in the detach code *before* detaching
// `before`/`after`.
detachStatements.splice( detachStatements.length - 2, 0, detachStatement);
}
}
};

@ -3,6 +3,7 @@ import EachBlock from './EachBlock.js';
import Element from './Element.js';
import IfBlock from './IfBlock.js';
import MustacheTag from './MustacheTag.js';
import RawMustacheTag from './RawMustacheTag.js';
import Text from './Text.js';
import YieldTag from './YieldTag.js';
@ -12,6 +13,7 @@ export default {
Element,
IfBlock,
MustacheTag,
RawMustacheTag,
Text,
YieldTag
};

@ -190,6 +190,21 @@ export default function mustache ( parser ) {
});
}
// {{{raw}}} mustache
else if ( parser.eat( '{' ) ) {
const expression = readExpression( parser );
parser.allowWhitespace();
parser.eat( '}}}', true );
parser.current().children.push({
start,
end: parser.index,
type: 'RawMustacheTag',
expression
});
}
else {
const expression = readExpression( parser );

@ -0,0 +1,16 @@
const ns = '<noscript></noscript>';
export default {
data: {
raw: '<span><em>raw html!!!\\o/</span></em>'
},
html: `before${ns}<span><em>raw html!!!\\o/</span></em>${ns}after`,
test ( assert, component, target ) {
component.set({ raw: '' });
assert.equal( target.innerHTML, `before${ns}${ns}after` );
component.set({ raw: 'how about <strong>unclosed elements?' });
assert.equal( target.innerHTML, `before${ns}how about <strong>unclosed elements?</strong>${ns}after` );
component.teardown();
assert.equal( target.innerHTML, '' );
}
};

@ -0,0 +1 @@
<p> {{{raw1}}} {{{raw2}}} </p>

@ -0,0 +1,48 @@
{
"html": {
"start": 0,
"end": 30,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 30,
"type": "Element",
"name": "p",
"attributes": [],
"children": [
{
"start": 4,
"end": 14,
"type": "RawMustacheTag",
"expression": {
"start": 7,
"end": 11,
"type": "Identifier",
"name": "raw1"
}
},
{
"start": 14,
"end": 15,
"type": "Text",
"data": " "
},
{
"start": 15,
"end": 25,
"type": "RawMustacheTag",
"expression": {
"start": 18,
"end": 22,
"type": "Identifier",
"name": "raw2"
}
}
]
}
]
},
"css": null,
"js": null
}
Loading…
Cancel
Save