mirror of
https://gitlab.com/nightlycommit/twing.git
synced 2025-01-18 08:46:50 +02:00
Merge branch 'issue-603' into 'milestone/6.1.0'
Resolve issue #603 See merge request nightlycommit/twing!604
This commit is contained in:
commit
960ba91a95
@ -28,7 +28,9 @@ import {TwingParsingError} from "./error/parsing";
|
||||
import {createLexer, TwingLexer} from "./lexer";
|
||||
import {TwingCache} from "./cache";
|
||||
import {createCoreExtension} from "./extension/core";
|
||||
import {createAutoEscapeNode} from "../lib";
|
||||
import {createAutoEscapeNode, type TwingContext} from "../lib";
|
||||
import {iteratorToMap} from "./helpers/iterator-to-map";
|
||||
import {createContext} from "./context";
|
||||
|
||||
export type TwingNumberFormat = {
|
||||
numberOfDecimals: number;
|
||||
@ -60,6 +62,7 @@ export type TwingEnvironmentOptions = {
|
||||
charset?: string;
|
||||
dateFormat?: string;
|
||||
dateIntervalFormat?: string;
|
||||
globals?: Record<string, any>;
|
||||
numberFormat?: TwingNumberFormat;
|
||||
parserOptions?: TwingParserOptions;
|
||||
sandboxed?: boolean;
|
||||
@ -84,6 +87,7 @@ export interface TwingEnvironment {
|
||||
readonly numberFormat: TwingNumberFormat;
|
||||
readonly filters: Map<string, TwingFilter>;
|
||||
readonly functions: Map<string, TwingFunction>;
|
||||
readonly globals: TwingContext<string, any>;
|
||||
readonly isStrictVariables: boolean;
|
||||
readonly loader: TwingLoader;
|
||||
readonly sandboxPolicy: TwingSandboxSecurityPolicy;
|
||||
@ -202,6 +206,7 @@ export const createEnvironment = (
|
||||
};
|
||||
const eventEmitter = new EventEmitter();
|
||||
const sandboxPolicy = options?.sandboxPolicy || createSandboxSecurityPolicy();
|
||||
const globals = createContext(iteratorToMap(options?.globals || {}));
|
||||
|
||||
let isSandboxed = options?.sandboxed ? true : false;
|
||||
let lexer: TwingLexer;
|
||||
@ -228,6 +233,9 @@ export const createEnvironment = (
|
||||
get functions() {
|
||||
return extensionSet.functions;
|
||||
},
|
||||
get globals() {
|
||||
return globals;
|
||||
},
|
||||
get isStrictVariables() {
|
||||
return options?.strictVariables ? true : false;
|
||||
},
|
||||
|
@ -11,6 +11,7 @@ export type TwingExecutionContext = {
|
||||
context: TwingContext<any, any>;
|
||||
dateFormat: string;
|
||||
dateIntervalFormat: string;
|
||||
globals: TwingContext<string, any>;
|
||||
isStrictVariables: boolean;
|
||||
numberFormat: TwingNumberFormat;
|
||||
outputBuffer: TwingOutputBuffer;
|
||||
|
@ -2,6 +2,8 @@ import type {TwingBaseExpressionNodeAttributes} from "../expression";
|
||||
import {createBaseNode, TwingBaseNode} from "../../node";
|
||||
import {getContextValue} from "../../helpers/get-context-value";
|
||||
import {getTraceableMethod} from "../../helpers/traceable-method";
|
||||
import {mergeIterables} from "../../helpers/merge-iterables";
|
||||
import {createContext} from "../../context";
|
||||
|
||||
export type TwingNameNodeAttributes = TwingBaseExpressionNodeAttributes & {
|
||||
name: string;
|
||||
@ -29,7 +31,7 @@ export const createNameNode = (
|
||||
|
||||
const nameNode: TwingNameNode = {
|
||||
...baseNode,
|
||||
execute: async ({template, context, charset, isStrictVariables}) => {
|
||||
execute: async ({template, context, charset, isStrictVariables, globals}) => {
|
||||
const {name, isAlwaysDefined, shouldIgnoreStrictCheck, shouldTestExistence} = nameNode.attributes;
|
||||
|
||||
const traceableGetContextValue = getTraceableMethod(
|
||||
@ -43,7 +45,7 @@ export const createNameNode = (
|
||||
charset,
|
||||
template.name,
|
||||
isStrictVariables,
|
||||
context,
|
||||
createContext(mergeIterables(globals, context)),
|
||||
name,
|
||||
isAlwaysDefined,
|
||||
shouldIgnoreStrictCheck,
|
||||
|
@ -87,11 +87,7 @@ export const createForNode = (
|
||||
|
||||
let sequence = ensureTraversable(executedSequence);
|
||||
|
||||
if (sequence === context) {
|
||||
context.set('_seq', context.clone());
|
||||
} else {
|
||||
context.set('_seq', sequence);
|
||||
}
|
||||
context.set('_seq', sequence);
|
||||
|
||||
if (elseNode) {
|
||||
context.set('_iterated', false);
|
||||
|
@ -201,6 +201,7 @@ export const createTemplate = (
|
||||
context,
|
||||
dateFormat,
|
||||
dateIntervalFormat,
|
||||
globals: environment.globals,
|
||||
isStrictVariables,
|
||||
numberFormat,
|
||||
outputBuffer,
|
||||
@ -237,6 +238,7 @@ export const createTemplate = (
|
||||
context: createContext(),
|
||||
dateFormat,
|
||||
dateIntervalFormat,
|
||||
globals: environment.globals,
|
||||
isStrictVariables,
|
||||
numberFormat,
|
||||
outputBuffer,
|
||||
@ -269,6 +271,7 @@ export const createTemplate = (
|
||||
context,
|
||||
dateFormat,
|
||||
dateIntervalFormat,
|
||||
globals: environment.globals,
|
||||
isStrictVariables,
|
||||
numberFormat,
|
||||
outputBuffer,
|
||||
@ -490,6 +493,7 @@ export const createTemplate = (
|
||||
context,
|
||||
dateFormat,
|
||||
dateIntervalFormat,
|
||||
globals: environment.globals,
|
||||
isStrictVariables,
|
||||
numberFormat,
|
||||
outputBuffer,
|
||||
@ -555,6 +559,7 @@ export const createTemplate = (
|
||||
context,
|
||||
dateFormat,
|
||||
dateIntervalFormat,
|
||||
globals: environment.globals,
|
||||
isStrictVariables,
|
||||
numberFormat,
|
||||
outputBuffer,
|
||||
|
1
test/tests/integration/globals/index.ts
Normal file
1
test/tests/integration/globals/index.ts
Normal file
@ -0,0 +1 @@
|
||||
import "./with-include";
|
43
test/tests/integration/globals/with-include.ts
Normal file
43
test/tests/integration/globals/with-include.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import {runTest} from "../TestBase";
|
||||
|
||||
runTest({
|
||||
description: 'globals with include',
|
||||
templates: {
|
||||
"index.twig": `{{ include("foo") }}`,
|
||||
'foo': `{{ title }}`
|
||||
},
|
||||
environmentOptions: {
|
||||
globals: {
|
||||
title: 'foo'
|
||||
}
|
||||
},
|
||||
expectation: `foo`
|
||||
});
|
||||
|
||||
runTest({
|
||||
description: 'globals with include, when shadowed',
|
||||
templates: {
|
||||
"index.twig": `{{ include("foo", {title: "bar"}) }}`,
|
||||
'foo': `{{ title }}`
|
||||
},
|
||||
environmentOptions: {
|
||||
globals: {
|
||||
title: 'foo'
|
||||
}
|
||||
},
|
||||
expectation: `bar`
|
||||
});
|
||||
|
||||
runTest({
|
||||
description: 'globals with include and only',
|
||||
templates: {
|
||||
"index.twig": `{{ include("foo", {}, true) }}`,
|
||||
'foo': `{{ title }}`
|
||||
},
|
||||
environmentOptions: {
|
||||
globals: {
|
||||
title: 'foo'
|
||||
}
|
||||
},
|
||||
expectation: `foo`
|
||||
});
|
@ -8,6 +8,7 @@ import "./expressions";
|
||||
import "./extensions";
|
||||
import "./filters";
|
||||
import "./functions";
|
||||
import "./globals";
|
||||
import "./implicit-auto-escaping";
|
||||
import "./macros";
|
||||
import "./operators";
|
||||
|
13
test/tests/integration/tags/for/context-as-sequence.ts
Normal file
13
test/tests/integration/tags/for/context-as-sequence.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import {runTest} from "../../TestBase";
|
||||
|
||||
runTest({
|
||||
description: '"for" tag with context as sequence',
|
||||
templates: {
|
||||
"index.twig": `{% for key, value in _context %}{{ key }}{{ value }}{% endfor %}`
|
||||
},
|
||||
expectation: `foofoo valuebarbar value_parent[object Object]`,
|
||||
context: Promise.resolve({
|
||||
foo: 'foo value',
|
||||
bar: 'bar value'
|
||||
})
|
||||
});
|
@ -3,6 +3,7 @@ import "./condition.legacy";
|
||||
import "./condition_and_nested_for_loop_access";
|
||||
import "./containing_with";
|
||||
import "./context";
|
||||
import "./context-as-sequence";
|
||||
import "./hashes";
|
||||
import "./inner_variables";
|
||||
import "./inside_with";
|
||||
|
Loading…
Reference in New Issue
Block a user