From 176ee2bc9becdc7c6e6e03e9f06a826326e0952f Mon Sep 17 00:00:00 2001 From: Patrick Steele-Idem Date: Tue, 2 Feb 2016 16:01:00 -0700 Subject: [PATCH] Marko v3: Added support for node.onBeforeGenerateCode and node.onAfterGenerateCode --- compiler/CodeGenerator.js | 40 +++++++++++++++++++++++++++++++++++++-- compiler/ast/Node.js | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/compiler/CodeGenerator.js b/compiler/CodeGenerator.js index 60481b8e2..dd33b56e7 100644 --- a/compiler/CodeGenerator.js +++ b/compiler/CodeGenerator.js @@ -9,6 +9,27 @@ const Container = require('./ast/Container'); const util = require('util'); const isValidJavaScriptIdentifier = require('./util/isValidJavaScriptIdentifier'); +class GeneratorEvent { + constructor(node, codegen) { + this.node = node; + this.codegen = codegen; + + this.isBefore = true; + this.builder = codegen.builder; + this.context = codegen.context; + } + + insertCode(newCode) { + this.codegen.generateStatements(newCode); + + if (this.isBefore) { + if (!this.codegen._code.endsWith(this.codegen.currentIndent)) { + this.codegen.writeLineIndent(); + } + } + } +} + class Slot { constructor(codegen, slotNode) { this._content = null; @@ -80,7 +101,6 @@ class Generator { this._bufferedWrites = null; this.builder = context.builder; - this.walker = context.walker; this.outputType = options.output || 'html'; this.context = context; @@ -138,6 +158,17 @@ class Generator { let generateCodeFunc; var isStatement = node.statement; + var beforeAfterEvent; + + if (node.listenerCount('beforeGenerateCode') || node.listenerCount('beforeGenerateCode')) { + beforeAfterEvent = new GeneratorEvent(node, this); + } + + if (beforeAfterEvent) { + beforeAfterEvent.isBefore = true; + beforeAfterEvent.node.emit('beforeGenerateCode', beforeAfterEvent); + } + if (node.getCodeGenerator) { generateCodeFunc = node.getCodeGenerator(this.outputType); if (generateCodeFunc) { @@ -191,6 +222,11 @@ class Generator { } } + if (beforeAfterEvent) { + beforeAfterEvent.isBefore = false; + beforeAfterEvent.node.emit('afterGenerateCode', beforeAfterEvent); + } + this._currentNode = oldCurrentNode; } @@ -484,7 +520,7 @@ class Generator { this.decIndent(); this.writeLineIndent(); - this.write(']\n'); + this.write(']'); } else if (typeof value === 'number') { this.write(value.toString()); } else if (typeof value === 'object') { diff --git a/compiler/ast/Node.js b/compiler/ast/Node.js index b38857ac7..a05de4deb 100644 --- a/compiler/ast/Node.js +++ b/compiler/ast/Node.js @@ -4,6 +4,7 @@ var ArrayContainer = require('./ArrayContainer'); var ok = require('assert').ok; var extend = require('raptor-util/extend'); var inspect = require('util').inspect; +var EventEmitter = require('events').EventEmitter; class Node { constructor(type) { @@ -16,9 +17,40 @@ class Node { this._flags = {}; this._transformersApplied = {}; this._preserveWhitespace = null; + this._events = null; this.data = {}; } + on(event, listener) { + if (!this._events) { + this._events = new EventEmitter(); + } + + this._events.on(event, listener); + } + + emit(event, args) { + if (this._events) { + this._events.emit.apply(this._events, arguments); + } + } + + listenerCount(event) { + if (this._events) { + return this._events.listenerCount(event); + } else { + return 0; + } + } + + onBeforeGenerateCode(listener) { + this.on('beforeGenerateCode', listener); + } + + onAfterGenerateCode(listener) { + this.on('afterGenerateCode', listener); + } + wrap(wrapperNode) { ok(this.container, 'Node does not belong to a container: ' + this); var replaced = this.container.replaceChild(wrapperNode, this); @@ -81,6 +113,7 @@ class Node { delete result.data; delete result.tagDef; delete result._preserveWhitespace; + delete result._events; return result; }