Socket
Socket
Sign inDemoInstall

edge.js

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

edge.js - npm Package Compare versions

Comparing version 2.1.0 to 2.2.0

6

build/index.d.ts

@@ -0,6 +1,6 @@

export * from './src/Contracts';
import { Edge } from './src/Edge';
export { LoaderContract, LoaderTemplate, EdgeContract, EdgeRendererContract, ContextContract, ContextConstructorContract, TagContract, CompilerContract, } from './src/Contracts';
export { disAllowExpressions, allowExpressions, extractDiskAndTemplateName, } from './src/utils';
declare const edge: Edge;
export { Edge };
declare const edge: Edge;
export default edge;
export { safeValue, withCtx } from './src/Context';

@@ -17,8 +17,7 @@ "use strict";

const globals_1 = __importDefault(require("./src/Edge/globals"));
var utils_1 = require("./src/utils");
exports.disAllowExpressions = utils_1.disAllowExpressions;
exports.allowExpressions = utils_1.allowExpressions;
exports.extractDiskAndTemplateName = utils_1.extractDiskAndTemplateName;
const edge = new Edge_1.Edge();
globals_1.default(edge);
exports.default = edge;
var Context_1 = require("./src/Context");
exports.safeValue = Context_1.safeValue;
exports.withCtx = Context_1.withCtx;

@@ -0,13 +1,15 @@

import { LoaderTemplate, CacheManagerContract } from '../Contracts';
/**
* @module edge
* In memory cache manager to cache pre-compiled templates.
*/
import { LoaderTemplate } from '../Contracts';
/**
* In memory cache manager to cache pre-compiled templates
*/
export declare class CacheManager {
private _enabled;
private _cacheStore;
constructor(_enabled: boolean);
export declare class CacheManager implements CacheManagerContract {
private enabled;
private cacheStore;
constructor(enabled: boolean);
/**
* Returns a boolean to tell if a template has already been cached
* or not.
*/
has(absPath: string): boolean;
/**
* Returns the template and the presenter class from the

@@ -14,0 +16,0 @@ * cache. If caching is disabled, then it will

"use strict";
/**
* @module edge
*/
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
/**
* In memory cache manager to cache pre-compiled templates
* In memory cache manager to cache pre-compiled templates.
*/
class CacheManager {
constructor(_enabled) {
this._enabled = _enabled;
this._cacheStore = new Map();
constructor(enabled) {
this.enabled = enabled;
this.cacheStore = new Map();
}
/**
* Returns a boolean to tell if a template has already been cached
* or not.
*/
has(absPath) {
return this.cacheStore.has(absPath);
}
/**
* Returns the template and the presenter class from the

@@ -20,6 +32,6 @@ * cache. If caching is disabled, then it will

get(absPath) {
if (!this._enabled) {
if (!this.enabled) {
return;
}
return this._cacheStore.get(absPath);
return this.cacheStore.get(absPath);
}

@@ -31,8 +43,8 @@ /**

set(absPath, payload) {
if (!this._enabled) {
if (!this.enabled) {
return;
}
this._cacheStore.set(absPath, payload);
this.cacheStore.set(absPath, payload);
}
}
exports.CacheManager = CacheManager;

@@ -1,5 +0,3 @@

/**
* @module edge
*/
import { ParserToken } from 'edge-parser';
import { Token } from 'edge-lexer';
import { CacheManager } from '../CacheManager';
import { LoaderContract, TagsContract, LoaderTemplate, CompilerContract } from '../Contracts';

@@ -15,11 +13,11 @@ /**

export declare class Compiler implements CompilerContract {
private _loader;
private _tags;
private _cache;
private _cacheManager;
constructor(_loader: LoaderContract, _tags: TagsContract, _cache?: boolean);
private loader;
private tags;
private cache;
cacheManager: CacheManager;
constructor(loader: LoaderContract, tags: TagsContract, cache?: boolean);
/**
* Merges sections of base template and parent template tokens
*/
private _mergeSections;
private mergeSections;
/**

@@ -30,13 +28,12 @@ * Generates an array of lexer tokens from the template string. Further tokens

*/
private _templateContentToTokens;
private templateContentToTokens;
/**
* Converts the template content to an [array of lexer tokens]. The method is
* same as the `parser.generateLexerTokens`, plus it will handle the layouts
* and it's sections.
* same as the `parser.tokenize`, but it also handles layouts natively.
*
* ```
* compiler.generateLexerTokens('<template-path>')
* compiler.tokenize('<template-path>')
* ```
*/
generateLexerTokens(templatePath: string): ParserToken[];
tokenize(templatePath: string): Token[];
/**

@@ -43,0 +40,0 @@ * Compiles the template contents to a function string, which can be invoked

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,6 +10,7 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_error_1 = require("edge-error");
const edge_parser_1 = require("edge-parser");
const edge_lexer_1 = require("edge-lexer");
const CacheManager_1 = require("../CacheManager");
const utils_1 = require("../utils");
/**

@@ -28,7 +25,7 @@ * Compiler compiles the template to a function, which can be invoked at a later

class Compiler {
constructor(_loader, _tags, _cache = true) {
this._loader = _loader;
this._tags = _tags;
this._cache = _cache;
this._cacheManager = new CacheManager_1.CacheManager(this._cache);
constructor(loader, tags, cache = true) {
this.loader = loader;
this.tags = tags;
this.cache = cache;
this.cacheManager = new CacheManager_1.CacheManager(this.cache);
}

@@ -38,3 +35,3 @@ /**

*/
_mergeSections(base, extended, filename, layoutPath) {
mergeSections(base, extended) {
/**

@@ -45,4 +42,4 @@ * Collection of all sections from the extended tokens

/**
* Collection of extended set calls as top level nodes. Now since they are hanging
* up in the air, they will be hoisted like `var` statements in Javascript
* Collection of extended set calls as top level nodes. The set
* calls are hoisted just like `var` statements in Javascript.
*/

@@ -56,3 +53,3 @@ const extendedSetCalls = [];

*/
if (utils_1.isBlockToken(node, 'layout') ||
if (edge_lexer_1.utils.isTag(node, 'layout') ||
node.type === 'newline' ||

@@ -65,3 +62,3 @@ (node.type === 'raw' && !node.value.trim())) {

*/
if (utils_1.isBlockToken(node, 'section')) {
if (edge_lexer_1.utils.isTag(node, 'section')) {
extendedSections[node.properties.jsArg.trim()] = node;

@@ -73,3 +70,3 @@ return;

*/
if (utils_1.isBlockToken(node, 'set')) {
if (edge_lexer_1.utils.isTag(node, 'set')) {
extendedSetCalls.push(node);

@@ -79,6 +76,6 @@ return;

/**
* Everything else if not allowed as top level nodes
* Everything else is not allowed as top level nodes
*/
const [line, col] = utils_1.getLineAndColumnForToken(node);
throw new edge_error_1.EdgeError(`Template extending the layout can only define @sections as top level nodes`, 'E_UNALLOWED_EXPRESSION', { line, col, filename });
const [line, col] = edge_lexer_1.utils.getLineAndColumn(node);
throw new edge_error_1.EdgeError('Template extending a layout can only use "@section" or "@set" tags as top level nodes', 'E_UNALLOWED_EXPRESSION', { line, col, filename: node.filename });
});

@@ -90,9 +87,8 @@ /**

.map((node) => {
if (!utils_1.isBlockToken(node, 'section')) {
node.filename = layoutPath;
if (!edge_lexer_1.utils.isTag(node, 'section')) {
return node;
}
const extendedNode = extendedSections[node.properties.jsArg.trim()];
const sectionName = node.properties.jsArg.trim();
const extendedNode = extendedSections[sectionName];
if (!extendedNode) {
node.filename = layoutPath;
return node;

@@ -103,7 +99,4 @@ }

*/
if (extendedNode.children.length && utils_1.isBlockToken(extendedNode.children[0], 'super')) {
extendedNode.children = node.children.map((child) => {
child.filename = layoutPath;
return child;
}).concat(extendedNode.children);
if (extendedNode.children.length && edge_lexer_1.utils.isTag(extendedNode.children[0], 'super')) {
extendedNode.children = node.children.concat(extendedNode.children);
}

@@ -122,4 +115,4 @@ return extendedNode;

*/
_templateContentToTokens(content, parser, filename) {
let templateTokens = parser.generateLexerTokens(content);
templateContentToTokens(content, parser) {
let templateTokens = parser.tokenize(content);
const firstToken = templateTokens[0];

@@ -130,11 +123,5 @@ /**

*/
if (utils_1.isBlockToken(firstToken, 'layout')) {
const layoutName = firstToken.properties.jsArg.replace(/'/g, '');
/**
* Making absolute path, so that lexer errors must point to the
* absolute file path
*/
const absPath = this._loader.makePath(layoutName);
const layoutTokens = this.generateLexerTokens(absPath);
templateTokens = this._mergeSections(layoutTokens, templateTokens, filename, absPath);
if (edge_lexer_1.utils.isTag(firstToken, 'layout')) {
const layoutName = firstToken.properties.jsArg.replace(/'|"/g, '');
templateTokens = this.mergeSections(this.tokenize(layoutName), templateTokens);
}

@@ -145,13 +132,13 @@ return templateTokens;

* Converts the template content to an [array of lexer tokens]. The method is
* same as the `parser.generateLexerTokens`, plus it will handle the layouts
* and it's sections.
* same as the `parser.tokenize`, but it also handles layouts natively.
*
* ```
* compiler.generateLexerTokens('<template-path>')
* compiler.tokenize('<template-path>')
* ```
*/
generateLexerTokens(templatePath) {
const { template } = this._loader.resolve(templatePath, false);
const parser = new edge_parser_1.Parser(this._tags, { filename: templatePath });
return this._templateContentToTokens(template, parser, templatePath);
tokenize(templatePath) {
const absPath = this.loader.makePath(templatePath);
const { template } = this.loader.resolve(absPath, false);
const parser = new edge_parser_1.Parser(this.tags, { filename: absPath });
return this.templateContentToTokens(template, parser);
}

@@ -180,3 +167,3 @@ /**

compile(templatePath, inline) {
const absPath = this._loader.makePath(templatePath);
const absPath = this.loader.makePath(templatePath);
/**

@@ -186,3 +173,3 @@ * If template is in the cache, then return it without

*/
const cachedResponse = this._cacheManager.get(absPath);
const cachedResponse = this.cacheManager.get(absPath);
if (cachedResponse) {

@@ -192,3 +179,3 @@ return cachedResponse;

/**
* Do not load presenter in inline mode
* Do not return presenter in inline mode
*/

@@ -204,7 +191,8 @@ const loadPresenter = !inline;

*/
const parser = new edge_parser_1.Parser(this._tags, { filename: absPath });
const parser = new edge_parser_1.Parser(this.tags, { filename: absPath });
/**
* Resolve the template and Presenter using the given loader
* Resolve the template and Presenter using the given loader. We always
* load the presenter but don't return it when `loadPresenter = false`.
*/
const { template, Presenter } = this._loader.resolve(absPath, loadPresenter);
const { template, Presenter } = this.loader.resolve(absPath, true);
/**

@@ -214,17 +202,16 @@ * Convert template to AST. The AST will have the layout actions merged (if layout)

*/
const templateTokens = this._templateContentToTokens(template, parser, absPath);
const templateTokens = this.templateContentToTokens(template, parser);
/**
* Finally process the ast
*/
const buffer = new edge_parser_1.EdgeBuffer();
buffer.writeStatement(`ctx.set('$filename', '${templatePath.replace(/\.edge$/, '')}.edge');`);
templateTokens.forEach((token) => parser.processLexerToken(token, buffer));
const buffer = new edge_parser_1.EdgeBuffer(absPath, wrapAsFunction);
templateTokens.forEach((token) => parser.processToken(token, buffer));
const payload = {
template: buffer.flush(wrapAsFunction),
template: buffer.flush(),
Presenter,
};
this._cacheManager.set(absPath, payload);
return payload;
this.cacheManager.set(absPath, payload);
return loadPresenter ? payload : { template: payload.template };
}
}
exports.Compiler = Compiler;

@@ -0,6 +1,9 @@

import { Macroable } from 'macroable';
import { Presenter } from '../Presenter';
import { ContextContract } from '../Contracts';
/**
* @module edge
* An instance of this class passed to the escape
* method ensures that underlying value is never
* escaped.
*/
import { Macroable } from 'macroable';
import { ContextContract } from '../Contracts';
declare class SafeValue {

@@ -11,2 +14,13 @@ value: any;

/**
* A class to wrap callbacks that can access the `ctx`
*/
declare class WithCtx {
private callback;
constructor(callback: (ctx: ContextContract, ...args: any[]) => any);
/**
* Invoke the callback
*/
invoke(ctx: ContextContract, bindState: any): (...args: any[]) => any;
}
/**
* Context is used at runtime to resolve values for a given

@@ -19,6 +33,3 @@ * template.

export declare class Context extends Macroable implements ContextContract {
presenter: any;
sharedState: any;
protected static macros: {};
protected static getters: {};
presenter: Presenter;
/**

@@ -30,9 +41,19 @@ * Frames are used to define a inner scope in which values will

*/
private _frames;
constructor(presenter: any, sharedState: any);
private frames;
/**
* Required by Macroable
*/
protected static macros: {};
protected static getters: {};
/**
* Added by compiler
*/
$filename: string;
$lineNumber: number;
constructor(presenter: Presenter);
/**
* Returns value for a key inside frames. Stops looking for it,
* when value is found inside any frame.
*/
private _getFromFrame;
private getFromFrame;
/**

@@ -54,3 +75,3 @@ * Returns a merged copy of the current state. The objects are merged

/**
* Set key/value pair on the frame object. The value will only be available until
* Set key/value pair on the frame object. The value will only be available til
* the `removeFrame` is not called.

@@ -74,2 +95,6 @@ *

/**
* Returns all the frames
*/
getFrames(): any[];
/**
* Mark output as safe

@@ -84,2 +109,7 @@ */

/**
* Transform the resolved value before returning it
* back
*/
private transformValue;
/**
* Resolves value for a given key. It will look for the value in different

@@ -106,5 +136,4 @@ * locations and continues till the end if `undefined` is returned at

*
* 1. If the value already exists on the presenter state, then it will be updated
* 2. If the scope is inside a frame, then will be created/updated on the frame.
* 3. At last, the value is created on the presenter state.
* 1. If the scope is inside a frame, then will be created/updated on the frame.
* 2. Otherwise, the value is created on the presenter state.
*

@@ -115,4 +144,18 @@ * ```js

*/
set(key: string, value: any): void;
set(key: string, value: any, isolated?: boolean): void;
/**
* Rethrows the runtime exception by re-constructing the error message
* to point back to the original filename
*/
reThrow(error: any): void;
}
/**
* Mark value as safe and not to be escaped
*/
export declare function safeValue(value: string): SafeValue;
/**
* Wrap a function that receives the template engine current
* ctx when invoked.
*/
export declare function withCtx(callback: (ctx: ContextContract, ...args: any[]) => any): WithCtx;
export {};
"use strict";
/**
* @module edge
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -17,5 +10,15 @@ * edge.js

*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const he_1 = __importDefault(require("he"));
const lodash_1 = require("lodash");
const macroable_1 = require("macroable");
const edge_error_1 = require("edge-error");
/**
* An instance of this class passed to the escape
* method ensures that underlying value is never
* escaped.
*/
class SafeValue {

@@ -27,2 +30,18 @@ constructor(value) {

/**
* A class to wrap callbacks that can access the `ctx`
*/
class WithCtx {
constructor(callback) {
this.callback = callback;
}
/**
* Invoke the callback
*/
invoke(ctx, bindState) {
return (...args) => {
return this.callback.bind(bindState)(ctx, ...args);
};
}
}
/**
* Context is used at runtime to resolve values for a given

@@ -35,6 +54,5 @@ * template.

class Context extends macroable_1.Macroable {
constructor(presenter, sharedState) {
constructor(presenter) {
super();
this.presenter = presenter;
this.sharedState = sharedState;
/**

@@ -46,3 +64,8 @@ * Frames are used to define a inner scope in which values will

*/
this._frames = [];
this.frames = [];
/**
* Added by compiler
*/
this.$filename = '';
this.$lineNumber = 0;
}

@@ -53,4 +76,4 @@ /**

*/
_getFromFrame(key) {
const frameWithVal = this._frames.find((frame) => frame[key] !== undefined);
getFromFrame(key) {
const frameWithVal = this.frames.find((frame) => frame[key] !== undefined);
return frameWithVal ? frameWithVal[key] : undefined;

@@ -63,3 +86,3 @@ }

getCurrentState() {
return Object.assign({}, this.sharedState, this.presenter.state, ...this._frames);
return Object.assign({}, this.presenter.sharedState, this.presenter.state, ...this.frames);
}

@@ -76,6 +99,6 @@ /**

newFrame() {
this._frames.unshift({});
this.frames.unshift({});
}
/**
* Set key/value pair on the frame object. The value will only be available until
* Set key/value pair on the frame object. The value will only be available til
* the `removeFrame` is not called.

@@ -93,5 +116,5 @@ *

setOnFrame(key, value) {
const recentFrame = this._frames[0];
const recentFrame = this.frames[0];
if (!recentFrame) {
throw new Error('Make sure to call {newFrame} before calling {setOnFrame}');
throw new Error('Make sure to call "newFrame" before calling "setOnFrame"');
}

@@ -105,5 +128,11 @@ lodash_1.set(recentFrame, key, value);

removeFrame() {
this._frames.shift();
this.frames.shift();
}
/**
* Returns all the frames
*/
getFrames() {
return this.frames;
}
/**
* Mark output as safe

@@ -124,2 +153,15 @@ */

/**
* Transform the resolved value before returning it
* back
*/
transformValue(value, bindState) {
if (value instanceof WithCtx) {
return value.invoke(this, bindState);
}
if (typeof (value) === 'function') {
return value.bind(bindState);
}
return value;
}
/**
* Resolves value for a given key. It will look for the value in different

@@ -142,5 +184,22 @@ * locations and continues till the end if `undefined` is returned at

resolve(key) {
/**
* A special key to return the template current state
*/
if (key === '$state') {
return this.getCurrentState();
}
/**
* A special key to return the filename of the current execution
* scope.
*/
if (key === '$filename') {
return this.$filename;
}
/**
* A special key to return the current execution line number pointing
* fowards the original template file.
*/
if (key === '$lineNumber') {
return this.$lineNumber;
}
let value;

@@ -150,5 +209,5 @@ /**

*/
value = this._getFromFrame(key);
value = this.getFromFrame(key);
if (value !== undefined) {
return typeof (value) === 'function' ? value.bind(this) : value;
return this.transformValue(value, this);
}

@@ -161,3 +220,3 @@ /**

if (value !== undefined) {
return typeof (value) === 'function' ? value.bind(this.presenter) : value;
return this.transformValue(value, this.presenter);
}

@@ -169,9 +228,9 @@ /**

if (value !== undefined) {
return typeof (value) === 'function' ? value.bind(this.presenter.state) : value;
return this.transformValue(value, this.presenter.state);
}
/**
* Finally fallback to defined globals
* Finally fallback to shared globals
*/
value = this.sharedState[key];
return typeof (value) === 'function' ? value.bind(this.sharedState) : value;
value = this.presenter.sharedState[key];
return this.transformValue(value, this.presenter.sharedState);
}

@@ -182,5 +241,4 @@ /**

*
* 1. If the value already exists on the presenter state, then it will be updated
* 2. If the scope is inside a frame, then will be created/updated on the frame.
* 3. At last, the value is created on the presenter state.
* 1. If the scope is inside a frame, then will be created/updated on the frame.
* 2. Otherwise, the value is created on the presenter state.
*

@@ -191,8 +249,8 @@ * ```js

*/
set(key, value) {
set(key, value, isolated = false) {
/**
* If value already exists on the presenter
* state, then mutate it first
* Set value on the presenter state if it already exists and user
* doesn't want an isolated state for the current frame scope
*/
if (this.presenter.state[key] !== undefined || !this._frames.length) {
if (lodash_1.get(this.presenter.state, key) !== undefined && !isolated) {
lodash_1.set(this.presenter.state, key, value);

@@ -202,9 +260,49 @@ return;

/**
* If frames exists, then set it on frame
* If frames exists, then set the value on the framework
*/
this.setOnFrame(key, value);
if (this.frames.length) {
this.setOnFrame(key, value);
return;
}
/**
* Otherwise set on presenter
*/
lodash_1.set(this.presenter.state, key, value);
}
/**
* Rethrows the runtime exception by re-constructing the error message
* to point back to the original filename
*/
reThrow(error) {
if (error instanceof edge_error_1.EdgeError) {
throw error;
}
// const message = error.message.replace(/ctx\.resolve\(\.\.\.\)/, this.lastResolvedKey)
throw new edge_error_1.EdgeError(error.message, 'E_RUNTIME_EXCEPTION', {
filename: this.$filename,
line: this.$lineNumber,
col: 0,
});
}
}
exports.Context = Context;
/**
* Required by Macroable
*/
Context.macros = {};
Context.getters = {};
/**
* Mark value as safe and not to be escaped
*/
function safeValue(value) {
return new SafeValue(value);
}
exports.safeValue = safeValue;
/**
* Wrap a function that receives the template engine current
* ctx when invoked.
*/
function withCtx(callback) {
return new WithCtx(callback);
}
exports.withCtx = withCtx;
/**
* @module edge
*/
/**
* edge

@@ -14,3 +11,3 @@ *

import { MacroableConstructorContract } from 'macroable';
import { ParseTagDefininationContract } from 'edge-parser';
import { ParserTagDefininationContract } from 'edge-parser';
/**

@@ -57,9 +54,13 @@ * The shape in which the loader must resolve the template

/**
* Shape of a view presenter
*/
export interface PresenterContract {
state: any;
sharedState: any;
}
/**
* Shape of runtime context
*/
export interface ContextContract {
presenter: {
state: any;
};
sharedState: any;
presenter: PresenterContract;
safe<T extends any>(value: T): {

@@ -85,3 +86,3 @@ value: T;

*/
export interface TagContract extends ParseTagDefininationContract {
export interface TagContract extends ParserTagDefininationContract {
tagName: string;

@@ -97,7 +98,16 @@ run?(context: ContextConstructorContract): void;

/**
* Shape of the cache manager
*/
export interface CacheManagerContract {
get(templatePath: string): undefined | LoaderTemplate;
set(templatePath: string, compiledOutput: LoaderTemplate): void;
has(templatePath: string): boolean;
}
/**
* Shape of the compiler
*/
export interface CompilerContract {
cacheManager: CacheManagerContract;
compile(templatePath: string, inline: boolean): LoaderTemplate;
generateLexerTokens(templatePath: string): Token[];
tokenize(templatePath: string): Token[];
}

@@ -104,0 +114,0 @@ /**

"use strict";
/**
* @module edge
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });

@@ -0,5 +1,5 @@

import { EdgeContract } from '../../Contracts';
/**
* @module edge
* A list of default globals
*/
import { EdgeContract } from '../../Contracts';
export default function globals(edge: EdgeContract): void;
"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,3 +10,6 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = require("util");
const lodash_1 = require("lodash");
const Context_1 = require("../../Context");
/**

@@ -28,3 +27,3 @@ * Inspect value.

</span>`;
return ctx.safe(`<div class="__inspect_output" style="background: #000; color: #fff; padding: 20px; position: relative;">${inspectedString}${filename}</div>`);
return Context_1.safeValue(`<div class="__inspect_output" style="background: #000; color: #fff; padding: 20px; position: relative;">${inspectedString}${filename}</div>`);
}

@@ -37,5 +36,20 @@ /**

};
/**
* A list of default globals
*/
function globals(edge) {
edge.global('inspect', inspect);
edge.global('inspect', Context_1.withCtx(inspect));
edge.global('range', (start, end, step) => lodash_1.range(start, end, step));
edge.global('first', lodash_1.first);
edge.global('last', lodash_1.last);
edge.global('groupBy', lodash_1.groupBy);
edge.global('size', lodash_1.size);
edge.global('truncate', lodash_1.truncate);
edge.global('toAnchor', (url, title = url) => {
return Context_1.safeValue(`<a href="${url}"> ${title} </a>`);
});
edge.global('style', (url, title = url) => {
return Context_1.safeValue(`<a href="${url}"> ${title} </a>`);
});
}
exports.default = globals;

@@ -1,12 +0,9 @@

/**
* @module edge
*/
import { Compiler } from '../Compiler';
import { TagContract, EdgeOptions, EdgeContract, LoaderTemplate, EdgeRendererContract } from '../Contracts';
export declare class Edge implements EdgeContract {
private _options;
private options;
/**
* Globals are shared with all rendered templates
*/
private _globals;
private globals;
/**

@@ -16,3 +13,3 @@ * List of registered tags. Adding new tags will only impact

*/
private _tags;
private tags;
/**

@@ -28,3 +25,3 @@ * The loader to load templates. A loader can read and return

compiler: Compiler;
constructor(_options?: EdgeOptions);
constructor(options?: EdgeOptions);
/**

@@ -40,13 +37,4 @@ * Mount named directory to use views. Later you can reference

*/
mount(diskName: string, dirPath: string): this;
mount(diskName: string, dirPath?: string): this;
/**
* Mount defaults views directory.
*
* ```
* edge.mount(join(__dirname, 'admin'))
* edge.render('filename')
* ```
*/
mount(dirPath: string): this;
/**
* Un Mount a disk from the loader.

@@ -53,0 +41,0 @@ *

"use strict";
/**
* @module edge
*/
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importStar = (this && this.__importStar) || function (mod) {

@@ -13,22 +18,14 @@ if (mod && mod.__esModule) return mod;

Object.defineProperty(exports, "__esModule", { value: true });
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const Tags = __importStar(require("../Tags"));
const Loader_1 = require("../Loader");
const Context_1 = require("../Context");
const Compiler_1 = require("../Compiler");
const Renderer_1 = require("../Renderer");
const Context_1 = require("../Context");
class Edge {
constructor(_options = {}) {
this._options = _options;
constructor(options = {}) {
this.options = options;
/**
* Globals are shared with all rendered templates
*/
this._globals = {};
this.globals = {};
/**

@@ -38,3 +35,3 @@ * List of registered tags. Adding new tags will only impact

*/
this._tags = {};
this.tags = {};
/**

@@ -45,9 +42,19 @@ * The loader to load templates. A loader can read and return

*/
this.loader = this._options.loader || new Loader_1.Loader();
this.loader = this.options.loader || new Loader_1.Loader();
/**
* The underlying compiler in use
*/
this.compiler = new Compiler_1.Compiler(this.loader, this._tags, !!this._options.cache);
this.compiler = new Compiler_1.Compiler(this.loader, this.tags, !!this.options.cache);
Object.keys(Tags).forEach((name) => this.registerTag(Tags[name]));
}
/**
* Mount named directory to use views. Later you can reference
* the views from a named disk as follows.
*
* ```
* edge.mount('admin', join(__dirname, 'admin'))
*
* edge.render('admin::filename')
* ```
*/
mount(diskName, dirPath) {

@@ -82,3 +89,3 @@ if (!dirPath) {

global(name, value) {
this._globals[name] = value;
this.globals[name] = value;
return this;

@@ -105,3 +112,3 @@ }

}
this._tags[tag.tagName] = tag;
this.tags[tag.tagName] = tag;
return this;

@@ -147,3 +154,3 @@ }

getRenderer() {
return new Renderer_1.EdgeRenderer(this.compiler, this._globals);
return new Renderer_1.EdgeRenderer(this.compiler, this.globals);
}

@@ -150,0 +157,0 @@ /**

/**
* @module edge
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

@@ -16,7 +21,7 @@ import { LoaderContract, LoaderTemplate } from '../Contracts';

*/
private _mountedDirs;
private mountedDirs;
/**
* List of pre-registered (in-memory) templates
*/
private _preRegistered;
private preRegistered;
/**

@@ -29,3 +34,3 @@ * Attempts to load the presenter for a given template. If presenter doesn't exists, it

*/
private _getPresenterForTemplate;
private getPresenterForTemplate;
/**

@@ -35,4 +40,19 @@ * Reads the content of a template from the disk. An exception is raised

*/
private _readTemplateContents;
private readTemplateContents;
/**
* Extracts the disk name and the template name from the template
* path expression.
*
* If `diskName` is missing, it will be set to `default`.
*
* ```
* extractDiskAndTemplateName('users::list')
* // returns ['users', 'list.edge']
*
* extractDiskAndTemplateName('list')
* // returns ['default', 'list.edge']
* ```
*/
private extractDiskAndTemplateName;
/**
* Returns an object of mounted directories with their public

@@ -39,0 +59,0 @@ * names.

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/**
* edge

@@ -14,7 +10,10 @@ *

*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const import_fresh_1 = __importDefault(require("import-fresh"));
const path_1 = require("path");
const utils_1 = require("@poppinss/utils");
const requireUncached = require("import-fresh");
const path_1 = require("path");
const utils_2 = require("../utils");
/**

@@ -32,7 +31,7 @@ * The job of a loader is to load the template and it's presenter for a given path.

*/
this._mountedDirs = new Map();
this.mountedDirs = new Map();
/**
* List of pre-registered (in-memory) templates
*/
this._preRegistered = new Map();
this.preRegistered = new Map();
}

@@ -46,3 +45,3 @@ /**

*/
_getPresenterForTemplate(templatePath) {
getPresenterForTemplate(templatePath) {
const presenterPath = templatePath

@@ -52,3 +51,3 @@ .replace(/^\w/, c => c.toUpperCase())

try {
return utils_1.esmResolver(requireUncached(presenterPath));
return utils_1.esmResolver(import_fresh_1.default(presenterPath));
}

@@ -65,3 +64,3 @@ catch (error) {

*/
_readTemplateContents(absPath) {
readTemplateContents(absPath) {
try {

@@ -72,3 +71,3 @@ return fs_1.readFileSync(absPath, 'utf-8');

if (error.code === 'ENOENT') {
throw new utils_1.Exception(`Cannot resolve ${absPath}. Make sure the file exists`, 500, 'E_MISSING_TEMPLATE_FILE');
throw new utils_1.Exception(`Cannot resolve "${absPath}". Make sure the file exists`, 500, 'E_MISSING_TEMPLATE_FILE');
}

@@ -81,2 +80,25 @@ else {

/**
* Extracts the disk name and the template name from the template
* path expression.
*
* If `diskName` is missing, it will be set to `default`.
*
* ```
* extractDiskAndTemplateName('users::list')
* // returns ['users', 'list.edge']
*
* extractDiskAndTemplateName('list')
* // returns ['default', 'list.edge']
* ```
*/
extractDiskAndTemplateName(templatePath) {
let [disk, ...rest] = templatePath.split('::');
if (!rest.length) {
rest = [disk];
disk = 'default';
}
const [template, ext] = rest.join('::').split('.edge');
return [disk, `${template.replace(/\./, path_1.sep)}.${ext || 'edge'}`];
}
/**
* Returns an object of mounted directories with their public

@@ -96,3 +118,3 @@ * names.

get mounted() {
return Array.from(this._mountedDirs).reduce((obj, [key, value]) => {
return Array.from(this.mountedDirs).reduce((obj, [key, value]) => {
obj[key] = value;

@@ -115,3 +137,3 @@ return obj;

mount(diskName, dirPath) {
this._mountedDirs.set(diskName, dirPath);
this.mountedDirs.set(diskName, dirPath);
}

@@ -126,3 +148,3 @@ /**

unmount(diskName) {
this._mountedDirs.delete(diskName);
this.mountedDirs.delete(diskName);
}

@@ -142,12 +164,25 @@ /**

makePath(templatePath) {
if (this._preRegistered.has(templatePath)) {
/**
* Return the template path as it is, when it is registered
* dynamically
*/
if (this.preRegistered.has(templatePath)) {
return templatePath;
}
const [diskName, template] = utils_2.extractDiskAndTemplateName(templatePath);
/**
* Raise exception when disk name is not defined
* Return absolute path as it is
*/
const mountedDir = this._mountedDirs.get(diskName);
if (path_1.isAbsolute(templatePath)) {
return templatePath;
}
/**
* Extract disk name and template path from the expression
*/
const [diskName, template] = this.extractDiskAndTemplateName(templatePath);
/**
* Raise exception when disk name is not registered
*/
const mountedDir = this.mountedDirs.get(diskName);
if (!mountedDir) {
throw new utils_1.Exception(`{${diskName}} namespace is not mounted`, 500, 'E_UNMOUNTED_DISK_NAME');
throw new utils_1.Exception(`"${diskName}" namespace is not mounted`, 500, 'E_UNMOUNTED_DISK_NAME');
}

@@ -179,4 +214,4 @@ return path_1.join(mountedDir, template);

*/
if (this._preRegistered.has(templatePath)) {
const contents = this._preRegistered.get(templatePath);
if (this.preRegistered.has(templatePath)) {
const contents = this.preRegistered.get(templatePath);
return withPresenter ? contents : { template: contents.template };

@@ -189,4 +224,4 @@ }

return {
template: this._readTemplateContents(templatePath),
Presenter: withPresenter ? this._getPresenterForTemplate(templatePath) : undefined,
template: this.readTemplateContents(templatePath),
Presenter: withPresenter ? this.getPresenterForTemplate(templatePath) : undefined,
};

@@ -221,8 +256,8 @@ }

*/
if (this._preRegistered.has(templatePath)) {
throw new utils_1.Exception(`Cannot override previously registered {${templatePath}} template`, 500, 'E_DUPLICATE_TEMPLATE_PATH');
if (this.preRegistered.has(templatePath)) {
throw new utils_1.Exception(`Cannot override previously registered "${templatePath}" template`, 500, 'E_DUPLICATE_TEMPLATE_PATH');
}
this._preRegistered.set(templatePath, contents);
this.preRegistered.set(templatePath, contents);
}
}
exports.Loader = Loader;

@@ -0,5 +1,3 @@

import { PresenterContract } from '../Contracts';
/**
* @module edge
*/
/**
* The Base presenter is passed to context for reading

@@ -11,5 +9,6 @@ * the state values.

*/
export declare class Presenter {
export declare class Presenter implements PresenterContract {
state: any;
constructor(state: any);
sharedState: any;
constructor(state: any, sharedState: any);
}
"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -23,6 +20,9 @@ * The Base presenter is passed to context for reading

class Presenter {
constructor(state) {
constructor(state, sharedState) {
this.state = state;
this.sharedState = sharedState;
this.state = this.state || {};
this.sharedState = this.sharedState || {};
}
}
exports.Presenter = Presenter;

@@ -6,6 +6,6 @@ import { EdgeRendererContract, CompilerContract } from '../Contracts';

export declare class EdgeRenderer implements EdgeRendererContract {
private _compiler;
private _globals;
private _locals;
constructor(_compiler: CompilerContract, _globals: any);
private compiler;
private globals;
private locals;
constructor(compiler: CompilerContract, globals: any);
/**

@@ -12,0 +12,0 @@ * Share local variables with the template. They will overwrite the

@@ -17,6 +17,6 @@ "use strict";

class EdgeRenderer {
constructor(_compiler, _globals) {
this._compiler = _compiler;
this._globals = _globals;
this._locals = {};
constructor(compiler, globals) {
this.compiler = compiler;
this.globals = globals;
this.locals = {};
}

@@ -28,3 +28,3 @@ /**

share(data) {
lodash_1.merge(this._locals, data);
lodash_1.merge(this.locals, data);
return this;

@@ -36,3 +36,3 @@ }

render(templatePath, state = {}) {
const template = new Template_1.Template(this._compiler, this._globals, this._locals);
const template = new Template_1.Template(this.compiler, this.globals, this.locals);
return template.render(templatePath, state);

@@ -39,0 +39,0 @@ }

@@ -0,5 +1,3 @@

import { Parser } from 'edge-parser';
/**
* @module edge
*/
/**
* This class generates a valid object as a string, which is written to the template

@@ -31,2 +29,18 @@ * output. The reason we need a string like object, since we don't want it's

flush(): string;
/**
* Parses an array of expressions to form an object. Each expression inside the array must
* be `ObjectExpression` or an `AssignmentExpression`, otherwise it will be ignored.
*
* ```js
* (title = 'hello')
* // returns { title: 'hello' }
*
* ({ title: 'hello' })
* // returns { title: 'hello' }
*
* ({ title: 'hello' }, username = 'virk')
* // returns { title: 'hello', username: 'virk' }
* ```
*/
static fromAcornExpressions(expressions: any[], parser: Parser): string;
}
"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -50,3 +47,37 @@ * This class generates a valid object as a string, which is written to the template

}
/**
* Parses an array of expressions to form an object. Each expression inside the array must
* be `ObjectExpression` or an `AssignmentExpression`, otherwise it will be ignored.
*
* ```js
* (title = 'hello')
* // returns { title: 'hello' }
*
* ({ title: 'hello' })
* // returns { title: 'hello' }
*
* ({ title: 'hello' }, username = 'virk')
* // returns { title: 'hello', username: 'virk' }
* ```
*/
static fromAcornExpressions(expressions, parser) {
if (!Array.isArray(expressions)) {
throw new Error('"fromAcornExpressions" expects an array of acorn ast expressions');
}
const objectifyString = new this();
expressions.forEach((arg) => {
if (arg.type === 'ObjectExpression') {
arg.properties.forEach((prop) => {
const key = parser.utils.stringify(prop.key);
const value = parser.utils.stringify(prop.value);
objectifyString.add(key, value);
});
}
if (arg.type === 'AssignmentExpression') {
objectifyString.add(arg.left.name, parser.utils.stringify(arg.right));
}
});
return objectifyString.flush();
}
}
exports.StringifiedObject = StringifiedObject;

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,3 +10,5 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_error_1 = require("edge-error");
const edge_lexer_1 = require("edge-lexer");
const edge_parser_1 = require("edge-parser");

@@ -22,3 +20,3 @@ const StringifiedObject_1 = require("../StringifiedObject");

*/
const componentNameAllowedExpressions = [
const ALLOWED_EXPRESSION_FOR_COMPONENT_NAME = [
edge_parser_1.expressions.Identifier,

@@ -35,3 +33,3 @@ edge_parser_1.expressions.Literal,

*/
function getComponentNameAndProps(expression, parser) {
function getComponentNameAndProps(expression, parser, filename) {
let name;

@@ -52,3 +50,5 @@ /**

*/
utils_1.allowExpressions(name, componentNameAllowedExpressions, parser.options.filename, `{${parser.stringifyExpression(name)}} is not a valid argument for component name`);
utils_1.isSubsetOf(name, ALLOWED_EXPRESSION_FOR_COMPONENT_NAME, () => {
utils_1.unallowedExpression(`"${parser.utils.stringify(name)}" is not a valid argument for component name`, name, filename);
});
/**

@@ -59,4 +59,4 @@ * Parse rest of sequence expressions as an objectified string.

return [
parser.stringifyExpression(name),
utils_1.expressionsToStringifyObject(expression.expressions, parser),
parser.utils.stringify(name),
StringifiedObject_1.StringifiedObject.fromAcornExpressions(expression.expressions, parser),
];

@@ -68,3 +68,3 @@ }

*/
return [parser.stringifyExpression(name), '{}'];
return [parser.utils.stringify(name), '{}'];
}

@@ -74,3 +74,3 @@ /**

*/
function getSlotNameAndProps(expression, parser) {
function getSlotNameAndProps(token, parser) {
/**

@@ -80,4 +80,6 @@ * We just generate the acorn AST only, since we don't want parser to transform

*/
const parsed = parser.generateAcornExpression(expression.properties.jsArg, expression.loc).expression;
utils_1.allowExpressions(parsed, [edge_parser_1.expressions.Literal, edge_parser_1.expressions.SequenceExpression], parser.options.filename, `{${expression.properties.jsArg}} is not a valid argument type for the @slot tag`);
const parsed = parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename).expression;
utils_1.isSubsetOf(parsed, [edge_parser_1.expressions.Literal, edge_parser_1.expressions.SequenceExpression], () => {
utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid argument type for the @slot tag`, parsed, token.filename);
});
/**

@@ -96,3 +98,5 @@ * Fetch the slot name

*/
utils_1.allowExpressions(name, [edge_parser_1.expressions.Literal], parser.options.filename, 'slot name must be a valid string literal');
utils_1.isSubsetOf(name, [edge_parser_1.expressions.Literal], () => {
utils_1.unallowedExpression('slot name must be a valid string literal', name, token.filename);
});
/**

@@ -113,6 +117,8 @@ * Return the slot name with empty props, when the expression is a literal

col: parsed.loc.start.column,
filename: parser.options.filename,
filename: token.filename,
});
}
utils_1.allowExpressions(parsed.expressions[1], [edge_parser_1.expressions.Identifier], parser.options.filename, `{${parser.stringifyExpression(parsed.expressions[1])}} is not valid prop identifier for @slot tag`);
utils_1.isSubsetOf(parsed.expressions[1], [edge_parser_1.expressions.Identifier], () => {
utils_1.unallowedExpression(`"${parser.utils.stringify(parsed.expressions[1])}" is not valid prop identifier for @slot tag`, parsed.expressions[1], token.filename);
});
/**

@@ -132,7 +138,9 @@ * Returning the slot name and slot props name

compile(parser, buffer, token) {
const parsed = parser.generateEdgeExpression(token.properties.jsArg, token.loc);
const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename);
/**
* Check component js props for allowed expressions
* Check component jsProps for allowed expressions
*/
utils_1.allowExpressions(parsed, componentNameAllowedExpressions.concat(edge_parser_1.expressions.SequenceExpression), parser.options.filename, `{${token.properties.jsArg}} is not a valid argument type for the @component tag`);
utils_1.isSubsetOf(parsed, ALLOWED_EXPRESSION_FOR_COMPONENT_NAME.concat(edge_parser_1.expressions.SequenceExpression), () => {
utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid argument type for the @component tag`, parsed, token.filename);
});
/**

@@ -142,3 +150,3 @@ * Pulling the name and props for the component. The underlying method will

*/
const [name, props] = getComponentNameAndProps(parsed, parser);
const [name, props] = getComponentNameAndProps(parsed, parser, token.filename);
/**

@@ -149,36 +157,74 @@ * Loop over all the children and set them as part of slots. If no slot

const slots = {};
/**
* Main slot collects everything that is out of the named slots
* inside a component
*/
const mainSlot = {
props: {},
buffer: new edge_parser_1.EdgeBuffer(token.filename, false, { outputVar: 'slot_main' }),
line: -1,
filename: token.filename,
};
/**
* Loop over all the component children
*/
token.children.forEach((child, index) => {
let slotName = `'main'`;
let slotProps = null;
/**
* Update the slot name and props when a new slot is detected
* If children is not a slot, then add it to the main slot
*/
if (utils_1.isBlockToken(child, 'slot')) {
[slotName, slotProps] = getSlotNameAndProps(child, parser);
if (!edge_lexer_1.utils.isTag(child, 'slot')) {
parser.processToken(child, mainSlot.buffer);
return;
}
/**
* Fetch slot and props
*/
const [slotName, slotProps] = getSlotNameAndProps(child, parser);
/**
* Create a new slot with buffer to process the childs
*/
if (!slots[slotName]) {
slots[slotName] = { buffer: new edge_parser_1.EdgeBuffer(`slot_${index}`), props: slotProps };
/**
* Slot buffer points to the component file name, since slots doesn't
* have their own file names.
*/
slots[slotName] = {
buffer: new edge_parser_1.EdgeBuffer(token.filename, false, { outputVar: `slot_${index}` }),
props: slotProps,
line: -1,
filename: token.filename,
};
/**
* Only start the frame, when there are props in use for a given slot.
*/
if (slotProps) {
slots[slotName].buffer.writeStatement('ctx.newFrame();');
slots[slotName].buffer.writeStatement(`ctx.setOnFrame('${slotProps}', ${slotProps});`);
slots[slotName].buffer.writeExpression('ctx.newFrame()', slots[slotName].filename, slots[slotName].line);
slots[slotName].buffer.writeExpression(`ctx.setOnFrame('${slotProps}', ${slotProps})`, slots[slotName].filename, slots[slotName].line);
}
}
/**
* We must process slot of a component by ourselves (instead of making slot tag)
* process it. This way, we can disallow slots appearing outside the component
* tag
* Self process the slot children.
*/
if (utils_1.isBlockToken(child, 'slot')) {
child.children.forEach((token) => parser.processLexerToken(token, slots[slotName].buffer));
child.children.forEach((grandChildren) => parser.processToken(grandChildren, slots[slotName].buffer));
/**
* Close the frame after process the slot children
*/
if (slotProps) {
slots[slotName].buffer.writeExpression('ctx.removeFrame()', slots[slotName].filename, slots[slotName].line);
}
});
const obj = new StringifiedObject_1.StringifiedObject();
/**
* Add main slot to the stringified object, when main slot
* is not defined otherwise.
*/
if (!slots['main']) {
if (mainSlot.buffer.size) {
mainSlot.buffer.wrap('function () {', '}');
obj.add('main', mainSlot.buffer.flush());
}
else {
parser.processLexerToken(child, slots[slotName].buffer);
obj.add('main', 'function () { return "" }');
}
});
}
/**

@@ -188,13 +234,11 @@ * We convert the slots to an objectified string, that is passed to `template.renderWithState`,

*/
const obj = new StringifiedObject_1.StringifiedObject();
Object.keys(slots).forEach((slot) => {
/**
* Cleanup the previously started frame scope
*/
if (slots[slot].props) {
slots[slot].buffer.writeStatement('ctx.removeFrame();');
Object.keys(slots).forEach((slotName) => {
if (slots[slotName].buffer.size) {
const fnCall = slots[slotName].props ? `function (${slots[slotName].props}) {` : 'function () {';
slots[slotName].buffer.wrap(fnCall, '}');
obj.add(slotName, slots[slotName].buffer.flush());
}
const fnCall = slots[slot].props ? `return function (${slots[slot].props}) {` : 'return function () {';
slots[slot].buffer.wrap(fnCall, '};');
obj.add(slot, slots[slot].buffer.flush(true));
else {
obj.add(slotName, 'function () { return "" }');
}
});

@@ -204,4 +248,4 @@ /**

*/
buffer.writeLine(`template.renderWithState(${name}, ${props}, ${obj.flush()})`);
buffer.outputExpression(`template.renderWithState(${name}, ${props}, ${obj.flush()})`, token.filename, token.loc.start.line, false);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });

@@ -20,5 +25,5 @@ /**

*/
compile(_parser, buffer) {
buffer.writeStatement('debugger;');
compile(_, buffer, token) {
buffer.writeExpression('debugger', token.filename, token.loc.start.line);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,4 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_lexer_1 = require("edge-lexer");
const edge_parser_1 = require("edge-parser");

@@ -21,4 +19,4 @@ const lodash_1 = require("lodash");

*/
function getLoopList(expression, parser) {
return parser.stringifyExpression(parser.acornToEdgeExpression(expression));
function getLoopList(expression, parser, filename) {
return parser.utils.stringify(parser.utils.transformAst(expression, filename));
}

@@ -29,3 +27,5 @@ /**

function getLoopItemAndIndex(expression, filename) {
utils_1.allowExpressions(expression, [edge_parser_1.expressions.SequenceExpression, edge_parser_1.expressions.Identifier], filename, `invalid left hand side expression for the @each tag`);
utils_1.isSubsetOf(expression, [edge_parser_1.expressions.SequenceExpression, edge_parser_1.expressions.Identifier], () => {
utils_1.unallowedExpression(`invalid left hand side "${expression.type}" for the @each tag`, expression, filename);
});
/**

@@ -35,4 +35,8 @@ * Return list index from the sequence expression

if (expression.type === 'SequenceExpression') {
utils_1.allowExpressions(expression.expressions[0], [edge_parser_1.expressions.Identifier], filename, `invalid expression for {value} identifier for the @each tag`);
utils_1.allowExpressions(expression.expressions[1], [edge_parser_1.expressions.SequenceExpression, edge_parser_1.expressions.Identifier], filename, `invalid expression for {key} identifier for the @each tag`);
utils_1.isSubsetOf(expression.expressions[0], [edge_parser_1.expressions.Identifier], () => {
utils_1.unallowedExpression(`"${expression.expressions[0]}.type" is not allowed as value identifier for @each tag`, expression.expressions[0], filename);
});
utils_1.isSubsetOf(expression.expressions[1], [edge_parser_1.expressions.Identifier], () => {
utils_1.unallowedExpression(`"${expression.expressions[1]}.type" is not allowed as key identifier for @each tag`, expression.expressions[1], filename);
});
return [expression.expressions[0].name, expression.expressions[1].name];

@@ -60,13 +64,13 @@ }

/**
* Instead of using `parser.generateEdgeExpression`, we make use of
* `generateAcornExpression`, since we do not want to process
* `Indentifer` expressions as per the normal parsing logic
* and just want to extract it's name.
* We just generate the AST and do not transform it, since the transform
* function attempts to resolve identifiers
*/
const parsed = parser.generateAcornExpression(token.properties.jsArg, token.loc).expression;
utils_1.allowExpressions(parsed, [edge_parser_1.expressions.BinaryExpression], parser.options.filename, `{${token.properties.jsArg}} is not a valid binary expression for the @each tag`);
const parsed = parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename).expression;
utils_1.isSubsetOf(parsed, [edge_parser_1.expressions.BinaryExpression], () => {
utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid binary expression for the @each tag`, parsed, token.filename);
});
/**
* Finding if an else child exists inside the each tag
*/
const elseIndex = token.children.findIndex((child) => utils_1.isBlockToken(child, 'else'));
const elseIndex = token.children.findIndex((child) => edge_lexer_1.utils.isTag(child, 'else'));
const elseChild = elseIndex > -1 ? token.children.splice(elseIndex) : [];

@@ -76,4 +80,4 @@ /**

*/
const [item, index] = getLoopItemAndIndex(parsed.left, parser.options.filename);
const list = getLoopList(parsed.right, parser);
const [item, index] = getLoopItemAndIndex(parsed.left, token.filename);
const list = getLoopList(parsed.right, parser, token.filename);
/**

@@ -84,4 +88,3 @@ * If there is an else statement, then wrap the loop

if (elseIndex > -1) {
buffer.writeStatement(`if(ctx.size(${list})) {`);
buffer.indent();
buffer.writeStatement(`if(ctx.size(${list})) {`, token.filename, token.loc.start.line);
}

@@ -91,8 +94,4 @@ /**

*/
buffer.writeStatement(`ctx.loop(${list}, function (${item}, loop) {`);
buffer.writeStatement(`ctx.loop(${list}, function (${item}, loop) {`, token.filename, token.loc.start.line);
/**
* Indent block
*/
buffer.indent();
/**
* Start a new context frame. Frame ensures the value inside

@@ -102,27 +101,21 @@ * the loop is given priority over top level values. Think

*/
buffer.writeStatement('ctx.newFrame();');
buffer.writeExpression('ctx.newFrame()', token.filename, -1);
/**
* Set key and value pair on the context
*/
buffer.writeStatement(`ctx.setOnFrame('${item}', ${item});`);
buffer.writeStatement(`ctx.setOnFrame('$loop', loop);`);
buffer.writeStatement(`ctx.setOnFrame('${index}', loop.key);`);
buffer.writeExpression(`ctx.setOnFrame('${item}', ${item})`, token.filename, -1);
buffer.writeExpression('ctx.setOnFrame(\'$loop\', loop)', token.filename, -1);
buffer.writeExpression(`ctx.setOnFrame('${index}', loop.key)`, token.filename, -1);
/**
* Process all kids
*/
token.children.forEach((child) => {
parser.processLexerToken(child, buffer);
});
token.children.forEach((child) => parser.processToken(child, buffer));
/**
* Remove the frame
*/
buffer.writeStatement('ctx.removeFrame();');
buffer.writeExpression('ctx.removeFrame()', token.filename, -1);
/**
* Dedent block
*/
buffer.dedent();
/**
* Close each loop
*/
buffer.writeStatement('});');
buffer.writeExpression('})', token.filename, -1);
/**

@@ -133,5 +126,4 @@ * If there is an else statement, then process

if (elseIndex > -1) {
elseChild.forEach((child) => parser.processLexerToken(child, buffer));
buffer.dedent();
buffer.writeStatement(`}`);
elseChild.forEach((child) => parser.processToken(child, buffer));
buffer.writeStatement('}', token.filename, -1);
}

@@ -138,0 +130,0 @@ },

@@ -1,5 +0,2 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';
export declare const elseTag: TagContract;
"use strict";
/**
* @module edge
*/
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });

@@ -13,7 +18,5 @@ exports.elseTag = {

*/
compile(_parser, buffer) {
buffer.dedent();
buffer.writeStatement(`} else {`);
buffer.indent();
compile(_, buffer, token) {
buffer.writeStatement('} else {', token.filename, -1);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_parser_1 = require("edge-parser");

@@ -36,17 +33,11 @@ const utils_1 = require("../utils");

compile(parser, buffer, token) {
const parsed = parser.generateEdgeExpression(token.properties.jsArg, token.loc);
utils_1.disAllowExpressions(parsed, [edge_parser_1.expressions.SequenceExpression], parser.options.filename, `{${token.properties.jsArg}} is not a valid argument type for the @elseif tag`);
const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename);
utils_1.isNotSubsetOf(parsed, [edge_parser_1.expressions.SequenceExpression], () => {
utils_1.unallowedExpression(`{${token.properties.jsArg}} is not a valid argument type for the @elseif tag`, parsed, token.filename);
});
/**
* Dedent block
*/
buffer.dedent();
/**
* Start else block
*/
buffer.writeStatement(`} else if(${parser.stringifyExpression(parsed)}) {`);
/**
* Indent block again
*/
buffer.indent();
buffer.writeStatement(`} else if (${parser.utils.stringify(parsed)}) {`, token.filename, token.loc.start.line);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_parser_1 = require("edge-parser");

@@ -33,25 +30,19 @@ const utils_1 = require("../utils");

compile(parser, buffer, token) {
const parsed = parser.generateEdgeExpression(token.properties.jsArg, token.loc);
utils_1.disAllowExpressions(parsed, [edge_parser_1.expressions.SequenceExpression], parser.options.filename, `{${token.properties.jsArg}} is not a valid argument type for the @if tag`);
const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename);
utils_1.isNotSubsetOf(parsed, [edge_parser_1.expressions.SequenceExpression], () => {
utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid argument type for the @if tag`, parsed, token.filename);
});
/**
* Start if block
*/
buffer.writeStatement(`if(${parser.stringifyExpression(parsed)}) {`);
buffer.writeStatement(`if (${parser.utils.stringify(parsed)}) {`, token.filename, token.loc.start.line);
/**
* Indent upcoming code
*/
buffer.indent();
/**
* Process of all kids recursively
*/
token.children.forEach((child) => parser.processLexerToken(child, buffer));
token.children.forEach((child) => parser.processToken(child, buffer));
/**
* Remove identation
*/
buffer.dedent();
/**
* Close if block
*/
buffer.writeStatement('}');
buffer.writeStatement('}', token.filename, -1);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_parser_1 = require("edge-parser");

@@ -33,4 +30,4 @@ const utils_1 = require("../utils");

compile(parser, buffer, token) {
const parsed = parser.generateEdgeExpression(token.properties.jsArg, token.loc);
utils_1.allowExpressions(parsed, [
const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename);
utils_1.isSubsetOf(parsed, [
edge_parser_1.expressions.Identifier,

@@ -43,3 +40,5 @@ edge_parser_1.expressions.Literal,

edge_parser_1.expressions.TemplateLiteral,
], parser.options.filename, `{${token.properties.jsArg}} is not a valid argument type for the @include tag`);
], () => {
utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid argument type for the @include tag`, parsed, token.filename);
});
/**

@@ -50,4 +49,4 @@ * Include template. Since the partials can be a runtime value, we cannot inline

*/
buffer.writeLine(`template.renderInline(${parser.stringifyExpression(parsed)})(template, ctx)`);
buffer.outputExpression(`template.renderInline(${parser.utils.stringify(parsed)})(template, ctx)`, token.filename, token.loc.start.line, true);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
export { ifTag as if } from './If';

@@ -5,0 +2,0 @@ export { elseTag as else } from './Else';

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
var If_1 = require("./If");

@@ -16,0 +13,0 @@ exports.if = If_1.ifTag;

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });

@@ -6,0 +11,0 @@ /**

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });

@@ -15,4 +20,4 @@ /**

compile(parser, buffer, token) {
token.children.forEach((token) => parser.processLexerToken(token, buffer));
token.children.forEach((child) => parser.processToken(child, buffer));
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,4 +10,5 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_error_1 = require("edge-error");
const edge_parser_1 = require("edge-parser");
const edge_error_1 = require("edge-error");
const utils_1 = require("../utils");

@@ -44,27 +41,31 @@ /**

compile(parser, buffer, token) {
const parsed = parser.generateEdgeExpression(token.properties.jsArg, token.loc);
const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename);
/**
* The set tag only accepts a sequence expression.
*/
utils_1.allowExpressions(parsed, [edge_parser_1.expressions.SequenceExpression], parser.options.filename, `{${token.properties.jsArg}} is not a valid key-value pair for the @slot tag`);
utils_1.isSubsetOf(parsed, [edge_parser_1.expressions.SequenceExpression], () => {
throw utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid key-value pair for the @slot tag`, parsed, token.filename);
});
/**
* Disallow more than 2 values for the sequence expression
*/
if (parsed.expressions.length > 2) {
throw new edge_error_1.EdgeError(`maximum of 2 arguments are allowed for the @set tag`, 'E_MAX_ARGUMENTS', {
if (parsed.expressions.length > 3) {
throw new edge_error_1.EdgeError('maximum of 3 arguments are allowed for the @set tag', 'E_MAX_ARGUMENTS', {
line: parsed.loc.start.line,
col: parsed.loc.start.column,
filename: parser.options.filename,
filename: token.filename,
});
}
const [key, value] = parsed.expressions;
const [key, value, isolated] = parsed.expressions;
/**
* The key has to be a literal value
*/
utils_1.allowExpressions(key, [edge_parser_1.expressions.Literal], parser.options.filename, 'The first argument for @set tag must be a string literal');
utils_1.isSubsetOf(key, [edge_parser_1.expressions.Literal], () => {
throw utils_1.unallowedExpression('The first argument for @set tag must be a string literal', parsed, token.filename);
});
/**
* Write statement to mutate the key
*/
buffer.writeStatement(`ctx.set(${key.raw}, ${parser.stringifyExpression(value)});`);
buffer.writeExpression(`ctx.set(${key.raw}, ${parser.utils.stringify(value)}, ${!!isolated})`, token.filename, token.loc.start.line);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_error_1 = require("edge-error");

@@ -24,9 +21,9 @@ /**

tagName: 'slot',
compile(parser, _buffer, token) {
throw new edge_error_1.EdgeError(`@slot tag must appear as top level tag inside the @component tag`, 'E_ORPHAN_SLOT_TAG', {
compile(_, __, token) {
throw new edge_error_1.EdgeError('@slot tag must appear as top level tag inside the @component tag', 'E_ORPHAN_SLOT_TAG', {
line: token.loc.start.line,
col: token.loc.start.col,
filename: parser.options.filename,
filename: token.filename,
});
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
/*
* edge
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });

@@ -6,0 +11,0 @@ /**

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_parser_1 = require("edge-parser");

@@ -35,27 +32,19 @@ const utils_1 = require("../utils");

compile(parser, buffer, token) {
const parsed = parser.generateEdgeExpression(token.properties.jsArg, token.loc);
utils_1.disAllowExpressions(parsed, [edge_parser_1.expressions.SequenceExpression], parser.options.filename, `{${token.properties.jsArg}} is not a valid argument type for the @unless tag`);
const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename);
utils_1.isNotSubsetOf(parsed, [edge_parser_1.expressions.SequenceExpression], () => {
utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid argument type for the @unless tag`, parsed, token.filename);
});
/**
* Start if block
*/
buffer.writeStatement(`if(!${parser.stringifyExpression(parsed)}) {`);
buffer.writeStatement(`if (!${parser.utils.stringify(parsed)}) {`, token.filename, token.loc.start.line);
/**
* Indent upcoming code
*/
buffer.indent();
/**
* Process of all kids recursively
*/
token.children.forEach((child) => {
parser.processLexerToken(child, buffer);
});
token.children.forEach((child) => parser.processToken(child, buffer));
/**
* Remove identation
*/
buffer.dedent();
/**
* Close if block
*/
buffer.writeStatement('}');
buffer.writeStatement('}', token.filename, -1);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { TagContract } from '../Contracts';

@@ -5,0 +2,0 @@ /**

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const edge_parser_1 = require("edge-parser");

@@ -44,12 +41,15 @@ const utils_1 = require("../utils");

compile(parser, buffer, token) {
const parsed = parser.generateEdgeExpression(token.properties.jsArg, token.loc);
utils_1.disAllowExpressions(parsed, [edge_parser_1.expressions.SequenceExpression], parser.options.filename, `{${token.properties.jsArg}} is not a valid argument type for the @yield tag`);
const parsedString = parser.stringifyExpression(parsed);
let yieldCounter = buffer['yieldCounter'] || 0;
buffer['yieldCounter'] = yieldCounter++;
const parsed = parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename);
utils_1.isNotSubsetOf(parsed, [edge_parser_1.expressions.SequenceExpression], () => {
utils_1.unallowedExpression(`"${token.properties.jsArg}" is not a valid argument type for the @yield tag`, parsed, token.filename);
});
const parsedString = parser.utils.stringify(parsed);
/**
* Write main content when it's truthy
*/
buffer.writeStatement(`if(${parsedString}) {`);
buffer.indent();
buffer.writeLine(parsedString);
buffer.dedent();
buffer.writeExpression(`let yield_${yieldCounter} = ${parsedString}`, token.filename, token.loc.start.line);
buffer.writeStatement(`if (yield_${yieldCounter}) {`, token.filename, -1);
buffer.outputExpression(`yield_${yieldCounter}`, token.filename, -1, true);
/**

@@ -59,9 +59,7 @@ * Else write fallback

if (!token.properties.selfclosed) {
buffer.writeStatement('} else {');
buffer.indent();
token.children.forEach((child) => (parser.processLexerToken(child, buffer)));
buffer.dedent();
buffer.writeStatement('} else {', token.filename, -1);
token.children.forEach((child) => (parser.processToken(child, buffer)));
}
buffer.writeStatement('}');
buffer.writeStatement('}', token.filename, -1);
},
};

@@ -1,4 +0,1 @@

/**
* @module edge
*/
import { CompilerContract } from '../Contracts';

@@ -11,3 +8,3 @@ /**

export declare class Template {
private _compiler;
private compiler;
/**

@@ -17,4 +14,4 @@ * The shared state is used to hold the globals and locals,

*/
private _sharedState;
constructor(_compiler: CompilerContract, globals: any, locals: any);
private sharedState;
constructor(compiler: CompilerContract, globals: any, locals: any);
/**

@@ -21,0 +18,0 @@ * Render the template inline by sharing the state of the current template.

"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,2 +10,3 @@ * edge

*/
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");

@@ -24,5 +21,5 @@ const Context_1 = require("../Context");

class Template {
constructor(_compiler, globals, locals) {
this._compiler = _compiler;
this._sharedState = lodash_1.merge({}, globals, locals);
constructor(compiler, globals, locals) {
this.compiler = compiler;
this.sharedState = lodash_1.merge({}, globals, locals);
}

@@ -40,3 +37,3 @@ /**

renderInline(templatePath) {
return new Function('template', 'ctx', this._compiler.compile(templatePath, true).template);
return new Function('template', 'ctx', this.compiler.compile(templatePath, true).template);
}

@@ -55,6 +52,6 @@ /**

renderWithState(template, state, slots) {
const { template: compiledTemplate, Presenter } = this._compiler.compile(template, false);
const presenter = new (Presenter || Presenter_1.Presenter)(lodash_1.merge(state, { $slots: slots }));
const ctx = new Context_1.Context(presenter, this._sharedState);
return new Function('template', 'ctx', `return ${compiledTemplate}`)(this, ctx);
const { template: compiledTemplate, Presenter } = this.compiler.compile(template, false);
const presenter = new (Presenter || Presenter_1.Presenter)(lodash_1.merge(state, { $slots: slots }), this.sharedState);
const ctx = new Context_1.Context(presenter);
return new Function('template', 'ctx', compiledTemplate)(this, ctx);
}

@@ -69,8 +66,8 @@ /**

render(template, state) {
const { template: compiledTemplate, Presenter } = this._compiler.compile(template, false);
const presenter = new (Presenter || Presenter_1.Presenter)(state);
const ctx = new Context_1.Context(presenter, this._sharedState);
return new Function('template', 'ctx', `return ${compiledTemplate}`)(this, ctx);
const { template: compiledTemplate, Presenter } = this.compiler.compile(template, false);
const presenter = new (Presenter || Presenter_1.Presenter)(state, this.sharedState);
const ctx = new Context_1.Context(presenter);
return new Function('template', 'ctx', compiledTemplate)(this, ctx);
}
}
exports.Template = Template;

@@ -0,5 +1,8 @@

import { expressions as expressionsList } from 'edge-parser';
declare type ExpressionList = readonly (keyof typeof expressionsList)[];
/**
* @module edge
* Raise an `E_UNALLOWED_EXPRESSION` exception. Filename and expression is
* required to point the error stack to the correct file
*/
import { Parser, expressions as expressionsList, ParserToken, ParserTagToken } from 'edge-parser';
export declare function unallowedExpression(message: string, expression: any, filename: string): void;
/**

@@ -12,6 +15,6 @@ * Validates the expression type to be part of the allowed

* ```js
* allowExpressions('include', 'SequenceExpression', ['Literal', 'Identifier'], 'foo.edge')
* isNotSubsetOf(expression, ['Literal', 'Identifier'], () => {})
* ```
*/
export declare function allowExpressions(expression: any, expressions: (keyof typeof expressionsList)[], filename: string, message: string): void;
export declare function isSubsetOf(expression: any, expressions: ExpressionList, errorCallback: () => void): void;
/**

@@ -24,45 +27,6 @@ * Validates the expression type not to be part of the disallowed

* ```js
* disAllowExpressions('include', 'SequenceExpression', ['Literal', 'Identifier'], 'foo.edge')
* isNotSubsetOf(expression, 'SequenceExpression', () => {})
* ```
*/
export declare function disAllowExpressions(expression: any, expressions: (keyof typeof expressionsList)[], filename: string, message: string): void;
/**
* Parses an array of expressions to form an object. Each expression inside the array must
* be `ObjectExpression` or an `AssignmentExpression`, otherwise it will be ignored.
*
* ```js
* (title = 'hello')
* // returns { title: 'hello' }
*
* ({ title: 'hello' })
* // returns { title: 'hello' }
*
* ({ title: 'hello' }, username = 'virk')
* // returns { title: 'hello', username: 'virk' }
* ```
*/
export declare function expressionsToStringifyObject(expressions: any[], parser: Parser): string;
/**
* Extracts the disk name and the template name from the template
* path expression.
*
* If `diskName` is missing, it will be set to `default`.
*
* ```
* extractDiskAndTemplateName('users::list')
* // returns ['users', 'list.edge']
*
* extractDiskAndTemplateName('list')
* // returns ['default', 'list.edge']
* ```
*/
export declare function extractDiskAndTemplateName(templatePath: string): [string, string];
/**
* Returns a boolean, telling whether the lexer node is a block node
* or not.
*/
export declare function isBlockToken(token: ParserToken, name: string): token is ParserTagToken;
/**
* Returns line and number for a given AST token
*/
export declare function getLineAndColumnForToken(token: ParserToken): [number, number];
export declare function isNotSubsetOf(expression: any, expressions: ExpressionList, errorCallback: () => void): void;
export {};
"use strict";
/**
* @module edge
*/
Object.defineProperty(exports, "__esModule", { value: true });
/*

@@ -14,7 +10,17 @@ * edge

*/
const path_1 = require("path");
Object.defineProperty(exports, "__esModule", { value: true });
const edge_error_1 = require("edge-error");
const edge_lexer_1 = require("edge-lexer");
const StringifiedObject_1 = require("../StringifiedObject");
/**
* Raise an `E_UNALLOWED_EXPRESSION` exception. Filename and expression is
* required to point the error stack to the correct file
*/
function unallowedExpression(message, expression, filename) {
throw new edge_error_1.EdgeError(message, 'E_UNALLOWED_EXPRESSION', {
line: expression.loc.start.line,
col: expression.loc.start.column,
filename: filename,
});
}
exports.unallowedExpression = unallowedExpression;
/**
* Validates the expression type to be part of the allowed

@@ -26,15 +32,11 @@ * expressions only.

* ```js
* allowExpressions('include', 'SequenceExpression', ['Literal', 'Identifier'], 'foo.edge')
* isNotSubsetOf(expression, ['Literal', 'Identifier'], () => {})
* ```
*/
function allowExpressions(expression, expressions, filename, message) {
function isSubsetOf(expression, expressions, errorCallback) {
if (!expressions.includes(expression.type)) {
throw new edge_error_1.EdgeError(message, 'E_UNALLOWED_EXPRESSION', {
line: expression.loc.start.line,
col: expression.loc.start.column,
filename: filename,
});
errorCallback();
}
}
exports.allowExpressions = allowExpressions;
exports.isSubsetOf = isSubsetOf;
/**

@@ -47,91 +49,10 @@ * Validates the expression type not to be part of the disallowed

* ```js
* disAllowExpressions('include', 'SequenceExpression', ['Literal', 'Identifier'], 'foo.edge')
* isNotSubsetOf(expression, 'SequenceExpression', () => {})
* ```
*/
function disAllowExpressions(expression, expressions, filename, message) {
function isNotSubsetOf(expression, expressions, errorCallback) {
if (expressions.includes(expression.type)) {
throw new edge_error_1.EdgeError(message, 'E_UNALLOWED_EXPRESSION', {
line: expression.loc.start.line,
col: expression.loc.start.column,
filename: filename,
});
errorCallback();
}
}
exports.disAllowExpressions = disAllowExpressions;
/**
* Parses an array of expressions to form an object. Each expression inside the array must
* be `ObjectExpression` or an `AssignmentExpression`, otherwise it will be ignored.
*
* ```js
* (title = 'hello')
* // returns { title: 'hello' }
*
* ({ title: 'hello' })
* // returns { title: 'hello' }
*
* ({ title: 'hello' }, username = 'virk')
* // returns { title: 'hello', username: 'virk' }
* ```
*/
function expressionsToStringifyObject(expressions, parser) {
const objectifyString = new StringifiedObject_1.StringifiedObject();
expressions.forEach((arg) => {
if (arg.type === 'ObjectExpression') {
arg.properties.forEach((prop) => {
const key = parser.stringifyExpression(prop.key);
const value = parser.stringifyExpression(prop.value);
objectifyString.add(key, value);
});
}
if (arg.type === 'AssignmentExpression') {
objectifyString.add(arg.left.name, parser.stringifyExpression(arg.right));
}
});
return objectifyString.flush();
}
exports.expressionsToStringifyObject = expressionsToStringifyObject;
/**
* Extracts the disk name and the template name from the template
* path expression.
*
* If `diskName` is missing, it will be set to `default`.
*
* ```
* extractDiskAndTemplateName('users::list')
* // returns ['users', 'list.edge']
*
* extractDiskAndTemplateName('list')
* // returns ['default', 'list.edge']
* ```
*/
function extractDiskAndTemplateName(templatePath) {
let [disk, ...rest] = templatePath.split('::');
if (!rest.length) {
rest = [disk];
disk = 'default';
}
const [template, ext] = rest.join('::').split('.edge');
return [disk, `${template.replace(/\./, path_1.sep)}.${ext || 'edge'}`];
}
exports.extractDiskAndTemplateName = extractDiskAndTemplateName;
/**
* Returns a boolean, telling whether the lexer node is a block node
* or not.
*/
function isBlockToken(token, name) {
if (token.type === edge_lexer_1.TagTypes.TAG || token.type === edge_lexer_1.TagTypes.ETAG) {
return token.properties.name === name;
}
return false;
}
exports.isBlockToken = isBlockToken;
/**
* Returns line and number for a given AST token
*/
function getLineAndColumnForToken(token) {
if (token.type === 'newline' || token.type === 'raw') {
return [token.line, 0];
}
return [token.loc.start.line, token.loc.start.col];
}
exports.getLineAndColumnForToken = getLineAndColumnForToken;
exports.isNotSubsetOf = isNotSubsetOf;
{
"name": "edge.js",
"version": "2.1.0",
"version": "2.2.0",
"description": "Template engine",

@@ -20,3 +20,3 @@ "main": "build/index.js",

"build": "npm run compile",
"lint": "tslint --project tsconfig.json",
"lint": "eslint . --ext=.ts",
"release": "np",

@@ -38,8 +38,11 @@ "version": "npm run build"

"@poppinss/dev-utils": "^1.0.4",
"@types/node": "^13.7.6",
"@types/lodash": "^4.14.149",
"@types/node": "^13.9.0",
"commitizen": "^4.0.3",
"cz-conventional-changelog": "^3.1.0",
"dedent": "^0.7.0",
"dedent-js": "^1.0.1",
"del-cli": "^3.0.0",
"doctoc": "^1.4.0",
"eslint": "^6.8.0",
"eslint-plugin-adonis": "^1.0.8",
"fs-extra": "^8.1.0",

@@ -51,8 +54,6 @@ "husky": "^4.2.3",

"ts-node": "^8.6.2",
"tslint": "^6.0.0",
"tslint-eslint-rules": "^5.4.0",
"typedoc": "^0.16.10",
"typedoc": "^0.16.11",
"typedoc-clarity-theme": "^1.1.0",
"typedoc-plugin-external-module-name": "^3.0.0",
"typescript": "^3.8.2",
"typescript": "^3.8.3",
"yorkie": "^2.0.0",

@@ -77,3 +78,4 @@ "youch": "^2.0.10"

"edge-error": "^1.0.4",
"edge-parser": "^2.1.2",
"edge-lexer": "^2.1.0",
"edge-parser": "^3.0.8",
"he": "^1.2.0",

@@ -80,0 +82,0 @@ "import-fresh": "^3.2.1",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc