diff --git a/src/compile/nodes/DebugTag.ts b/src/compile/nodes/DebugTag.ts new file mode 100644 index 0000000000..7bd2742c4f --- /dev/null +++ b/src/compile/nodes/DebugTag.ts @@ -0,0 +1,44 @@ +import Node from './shared/Node'; +import Tag from './shared/Tag'; +import Block from '../dom/Block'; +import Expression from './shared/Expression'; +import deindent from '../../utils/deindent'; + +export default class DebugTag extends Node { + expression: Expression; + + constructor(compiler, parent, scope, info) { + super(compiler, parent, scope, info); + if (info.expression !== null) + // Debug when expression nodes change + this.expression = new Expression(compiler, parent, scope, info.expression); + else + // "Debug all" + this.expression = info.expression + } + + build( + block: Block, + parentNode: string, + parentNodes: string, + ) { + // Debug all + if (this.expression === null) { + block.builders.create.addLine('debugger;'); + block.builders.update.addLine('debugger;'); + } else { + const { dependencies } = this.expression; + + const condition = [...dependencies].map(d => `changed.${d}`).join(' || '); + + const identifiers = [...dependencies].join(', '); + + block.builders.update.addBlock(deindent` + if (${condition}) { + const { ${identifiers} } = ctx; + debugger; + } + `); + } + } +} \ No newline at end of file diff --git a/src/compile/nodes/Element.ts b/src/compile/nodes/Element.ts index 7ab49b9768..11eea89107 100644 --- a/src/compile/nodes/Element.ts +++ b/src/compile/nodes/Element.ts @@ -21,7 +21,45 @@ import mapChildren from './shared/mapChildren'; import { dimensions } from '../../utils/patterns'; // source: https://gist.github.com/ArjanSchouten/0b8574a6ad7f5065a5e7 -const booleanAttributes = new Set('async autocomplete autofocus autoplay border challenge checked compact contenteditable controls default defer disabled formnovalidate frameborder hidden indeterminate ismap loop multiple muted nohref noresize noshade novalidate nowrap open readonly required reversed scoped scrolling seamless selected sortable spellcheck translate'.split(' ')); +const booleanAttributes = new Set([ + 'async', + 'autocomplete', + 'autofocus', + 'autoplay', + 'border', + 'challenge', + 'checked', + 'compact', + 'contenteditable', + 'controls', + 'default', + 'defer', + 'disabled', + 'formnovalidate', + 'frameborder', + 'hidden', + 'indeterminate', + 'ismap', + 'loop', + 'multiple', + 'muted', + 'nohref', + 'noresize', + 'noshade', + 'novalidate', + 'nowrap', + 'open', + 'readonly', + 'required', + 'reversed', + 'scoped', + 'scrolling', + 'seamless', + 'selected', + 'sortable', + 'spellcheck', + 'translate' +]); export default class Element extends Node { type: 'Element'; diff --git a/src/compile/nodes/shared/mapChildren.ts b/src/compile/nodes/shared/mapChildren.ts index 0a0a111322..9cd238644c 100644 --- a/src/compile/nodes/shared/mapChildren.ts +++ b/src/compile/nodes/shared/mapChildren.ts @@ -7,6 +7,7 @@ import Head from '../Head'; import IfBlock from '../IfBlock'; import MustacheTag from '../MustacheTag'; import RawMustacheTag from '../RawMustacheTag'; +import DebugTag from '../DebugTag'; import Slot from '../Slot'; import Text from '../Text'; import Title from '../Title'; @@ -24,6 +25,7 @@ function getConstructor(type): typeof Node { case 'IfBlock': return IfBlock; case 'MustacheTag': return MustacheTag; case 'RawMustacheTag': return RawMustacheTag; + case 'DebugTag': return DebugTag; case 'Slot': return Slot; case 'Text': return Text; case 'Title': return Title; diff --git a/src/parse/state/mustache.ts b/src/parse/state/mustache.ts index cbac76e6a1..8450074c66 100644 --- a/src/parse/state/mustache.ts +++ b/src/parse/state/mustache.ts @@ -313,6 +313,24 @@ export default function mustache(parser: Parser) { type: 'RawMustacheTag', expression, }); + } else if (parser.eat('@debug')) { + let expression; + + // Implies {@debug} which indicates "debug all" + if (/\s*}/.test(parser.template[parser.index])) + expression = null; + else + expression = readExpression(parser); + + parser.allowWhitespace(); + parser.eat('}', true); + + parser.current().children.push({ + start, + end: parser.index, + type: 'DebugTag', + expression, + }); } else { const expression = readExpression(parser);