mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] app, compiler: introduce t-out
t-out automatically escaped content when it is a string not marked with the `markup` function t-out renders the raw content if it is a Block, or if it has been marked with the `markup` funtion. t-esc has been kept since it is safe and is optimized to render text nodes. all t-raw calls are in fact the same as t-out.
This commit is contained in:
committed by
Aaron Bohy
parent
1761af9c24
commit
b902edc1be
@@ -15,7 +15,7 @@ import {
|
||||
ASTTForEach,
|
||||
ASTTif,
|
||||
ASTTKey,
|
||||
ASTTRaw,
|
||||
ASTTOut,
|
||||
ASTTSet,
|
||||
ASTTranslation,
|
||||
ASTType,
|
||||
@@ -208,7 +208,7 @@ export class CodeGenerator {
|
||||
// define blocks and utility functions
|
||||
this.addLine(`let { text, createBlock, list, multi, html, toggler, component } = bdom;`);
|
||||
this.addLine(
|
||||
`let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;`
|
||||
`let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;`
|
||||
);
|
||||
if (this.shouldDefineAssign) {
|
||||
this.addLine(`let assign = Object.assign;`);
|
||||
@@ -377,8 +377,8 @@ export class CodeGenerator {
|
||||
case ASTType.TEsc:
|
||||
this.compileTEsc(ast, ctx);
|
||||
break;
|
||||
case ASTType.TRaw:
|
||||
this.compileTRaw(ast, ctx);
|
||||
case ASTType.TOut:
|
||||
this.compileTOut(ast, ctx);
|
||||
break;
|
||||
case ASTType.TIf:
|
||||
this.compileTIf(ast, ctx);
|
||||
@@ -640,20 +640,20 @@ export class CodeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
compileTRaw(ast: ASTTRaw, ctx: Context) {
|
||||
compileTOut(ast: ASTTOut, ctx: Context) {
|
||||
let { block } = ctx;
|
||||
if (block) {
|
||||
this.insertAnchor(block);
|
||||
}
|
||||
block = this.createBlock(block, "html", ctx);
|
||||
let expr = ast.expr === "0" ? "ctx[zero]" : compileExpr(ast.expr);
|
||||
let expr = ast.expr === "0" ? "ctx[zero]" : `safeOutput(${compileExpr(ast.expr)})`;
|
||||
if (ast.body) {
|
||||
const nextId = BlockDescription.nextBlockId;
|
||||
const subCtx: Context = createContext(ctx);
|
||||
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||
expr = `withDefault(${expr}, b${nextId})`;
|
||||
}
|
||||
this.insertBlock(`html(${expr})`, block, ctx);
|
||||
this.insertBlock(`${expr}`, block, ctx);
|
||||
}
|
||||
|
||||
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode) {
|
||||
|
||||
+22
-16
@@ -11,7 +11,7 @@ export const enum ASTType {
|
||||
TIf,
|
||||
TSet,
|
||||
TCall,
|
||||
TRaw,
|
||||
TOut,
|
||||
TForEach,
|
||||
TKey,
|
||||
TComponent,
|
||||
@@ -62,8 +62,8 @@ export interface ASTTEsc {
|
||||
defaultValue: string;
|
||||
}
|
||||
|
||||
export interface ASTTRaw {
|
||||
type: ASTType.TRaw;
|
||||
export interface ASTTOut {
|
||||
type: ASTType.TOut;
|
||||
expr: string;
|
||||
body: AST[] | null;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ export type AST =
|
||||
| ASTTif
|
||||
| ASTTSet
|
||||
| ASTTCall
|
||||
| ASTTRaw
|
||||
| ASTTOut
|
||||
| ASTTForEach
|
||||
| ASTTKey
|
||||
| ASTComponent
|
||||
@@ -197,7 +197,7 @@ function parseNode(node: ChildNode, ctx: ParsingContext): AST | null {
|
||||
parseTKey(node, ctx) ||
|
||||
parseTTranslation(node, ctx) ||
|
||||
parseTSlot(node, ctx) ||
|
||||
parseTRawNode(node, ctx) ||
|
||||
parseTOutNode(node, ctx) ||
|
||||
parseComponent(node, ctx) ||
|
||||
parseDOMNode(node, ctx) ||
|
||||
parseTSetNode(node, ctx) ||
|
||||
@@ -419,33 +419,39 @@ function parseTEscNode(node: Element, ctx: ParsingContext): AST | null {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// t-raw
|
||||
// t-out
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
function parseTRawNode(node: Element, ctx: ParsingContext): AST | null {
|
||||
if (!node.hasAttribute("t-raw")) {
|
||||
function parseTOutNode(node: Element, ctx: ParsingContext): AST | null {
|
||||
if (!node.hasAttribute("t-out") && !node.hasAttribute("t-raw")) {
|
||||
return null;
|
||||
}
|
||||
const expr = node.getAttribute("t-raw")!;
|
||||
if (node.hasAttribute("t-raw")) {
|
||||
console.warn(
|
||||
`t-raw has been deprecated in favor of t-out. If the value to render is not wrapped by the "markup" function, it will be escaped`
|
||||
);
|
||||
}
|
||||
const expr = (node.getAttribute("t-out") || node.getAttribute("t-raw"))!;
|
||||
node.removeAttribute("t-out");
|
||||
node.removeAttribute("t-raw");
|
||||
|
||||
const tRaw: AST = { type: ASTType.TRaw, expr, body: null };
|
||||
const tOut: AST = { type: ASTType.TOut, expr, body: null };
|
||||
const ref = node.getAttribute("t-ref");
|
||||
node.removeAttribute("t-ref");
|
||||
const ast = parseNode(node, ctx);
|
||||
if (!ast) {
|
||||
return tRaw;
|
||||
return tOut;
|
||||
}
|
||||
if (ast && ast.type === ASTType.DomNode) {
|
||||
tRaw.body = ast.content.length ? ast.content : null;
|
||||
if (ast.type === ASTType.DomNode) {
|
||||
tOut.body = ast.content.length ? ast.content : null;
|
||||
return {
|
||||
...ast,
|
||||
ref,
|
||||
content: [tRaw],
|
||||
content: [tOut],
|
||||
};
|
||||
}
|
||||
|
||||
return tRaw;
|
||||
return tOut;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -504,7 +510,7 @@ function parseTForEach(node: Element, ctx: ParsingContext): AST | null {
|
||||
function hasNoComponent(ast: AST): boolean {
|
||||
switch (ast.type) {
|
||||
case ASTType.TComponent:
|
||||
case ASTType.TRaw:
|
||||
case ASTType.TOut:
|
||||
case ASTType.TCall:
|
||||
case ASTType.TCallBlock:
|
||||
case ASTType.TSlot:
|
||||
|
||||
Reference in New Issue
Block a user