Compare commits

..

1 Commits

Author SHA1 Message Date
Abdallah (ameb) 2b943e7278 Update templates.md
an => a
2025-05-13 09:43:58 +04:00
15 changed files with 80 additions and 510 deletions
-22
View File
@@ -320,28 +320,6 @@ class ComponentB extends owl.Component {
Note: the props validation code is done by using the [validate utility function](utils.md#validate). Note: the props validation code is done by using the [validate utility function](utils.md#validate).
### `slots` prop
If a component that uses [slots](slots.md) also lists or validates its props, then
you will have to explicitely allow the `slots` prop (with an `Object` type), or
allow extra props using the `*` notation mentioned above. This is because slots
are provided to a component [as props](slots.md#slots-and-props).
For example:
```js
class MyComponent extends Component {
static props = [someProp, slots?];
}
class MyComponentWithValidation extends Component {
static props = {
someProp: {type: Number, optional: true},
slots : {type: Object, optional: true},
}
}
```
## Good Practices ## Good Practices
A `props` object is a collection of values that come from the parent. As such, A `props` object is a collection of values that come from the parent. As such,
+1 -1
View File
@@ -680,7 +680,7 @@ class MyComponent extends Component {
mount(MyComponent, document.body); mount(MyComponent, document.body);
``` ```
This function simply generates an unique string id, and register the template This function simply generates a unique string id, and register the template
under that id in the internals of Owl, then return the id. under that id in the internals of Owl, then return the id.
## Rendering svg ## Rendering svg
+29 -84
View File
@@ -3850,16 +3850,7 @@ class CodeTarget {
return key; return key;
} }
} }
const TRANSLATABLE_ATTRS = [ const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
"alt",
"aria-label",
"aria-placeholder",
"aria-roledescription",
"aria-valuetext",
"label",
"placeholder",
"title",
];
const translationRE = /^(\s*)([\s\S]+?)(\s*)$/; const translationRE = /^(\s*)([\s\S]+?)(\s*)$/;
class CodeGenerator { class CodeGenerator {
constructor(ast, options) { constructor(ast, options) {
@@ -4539,7 +4530,7 @@ class CodeGenerator {
const isNewBlock = !block || forceNewBlock; const isNewBlock = !block || forceNewBlock;
let codeIdx = this.target.code.length; let codeIdx = this.target.code.length;
if (isNewBlock) { if (isNewBlock) {
const n = ast.content.filter((c) => !c.hasNoRepresentation).length; const n = ast.content.filter((c) => c.type !== 6 /* TSet */).length;
let result = null; let result = null;
if (n <= 1) { if (n <= 1) {
for (let child of ast.content) { for (let child of ast.content) {
@@ -4553,15 +4544,15 @@ class CodeGenerator {
let index = 0; let index = 0;
for (let i = 0, l = ast.content.length; i < l; i++) { for (let i = 0, l = ast.content.length; i < l; i++) {
const child = ast.content[i]; const child = ast.content[i];
const forceNewBlock = !child.hasNoRepresentation; const isTSet = child.type === 6 /* TSet */;
const subCtx = createContext(ctx, { const subCtx = createContext(ctx, {
block, block,
index, index,
forceNewBlock, forceNewBlock: !isTSet,
isLast: ctx.isLast && i === l - 1, isLast: ctx.isLast && i === l - 1,
}); });
this.compileAST(child, subCtx); this.compileAST(child, subCtx);
if (forceNewBlock) { if (!isTSet) {
index++; index++;
} }
} }
@@ -4977,11 +4968,11 @@ function parseNode(node, ctx) {
parseTPortal(node, ctx) || parseTPortal(node, ctx) ||
parseTCall(node, ctx) || parseTCall(node, ctx) ||
parseTCallBlock(node) || parseTCallBlock(node) ||
parseTTranslation(node, ctx) ||
parseTTranslationContext(node, ctx) ||
parseTKey(node, ctx) ||
parseTEscNode(node, ctx) || parseTEscNode(node, ctx) ||
parseTOutNode(node, ctx) || parseTOutNode(node, ctx) ||
parseTKey(node, ctx) ||
parseTTranslation(node, ctx) ||
parseTTranslationContext(node, ctx) ||
parseTSlot(node, ctx) || parseTSlot(node, ctx) ||
parseComponent(node, ctx) || parseComponent(node, ctx) ||
parseDOMNode(node, ctx) || parseDOMNode(node, ctx) ||
@@ -5049,29 +5040,19 @@ function parseTCustom(node, ctx) {
function parseTDebugLog(node, ctx) { function parseTDebugLog(node, ctx) {
if (node.hasAttribute("t-debug")) { if (node.hasAttribute("t-debug")) {
node.removeAttribute("t-debug"); node.removeAttribute("t-debug");
const content = parseNode(node, ctx); return {
const ast = {
type: 12 /* TDebug */, type: 12 /* TDebug */,
content, content: parseNode(node, ctx),
}; };
if (content === null || content === void 0 ? void 0 : content.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
} }
if (node.hasAttribute("t-log")) { if (node.hasAttribute("t-log")) {
const expr = node.getAttribute("t-log"); const expr = node.getAttribute("t-log");
node.removeAttribute("t-log"); node.removeAttribute("t-log");
const content = parseNode(node, ctx); return {
const ast = {
type: 13 /* TLog */, type: 13 /* TLog */,
expr, expr,
content, content: parseNode(node, ctx),
}; };
if (content === null || content === void 0 ? void 0 : content.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
} }
return null; return null;
} }
@@ -5301,19 +5282,11 @@ function parseTKey(node, ctx) {
} }
const key = node.getAttribute("t-key"); const key = node.getAttribute("t-key");
node.removeAttribute("t-key"); node.removeAttribute("t-key");
const content = parseNode(node, ctx); const body = parseNode(node, ctx);
if (!content) { if (!body) {
return null; return null;
} }
const ast = { return { type: 10 /* TKey */, expr: key, content: body };
type: 10 /* TKey */,
expr: key,
content,
};
if (content.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// t-call // t-call
@@ -5422,7 +5395,7 @@ function parseTSetNode(node, ctx) {
if (node.textContent !== node.innerHTML) { if (node.textContent !== node.innerHTML) {
body = parseChildren(node, ctx); body = parseChildren(node, ctx);
} }
return { type: 6 /* TSet */, name, value, defaultValue, body, hasNoRepresentation: true }; return { type: 6 /* TSet */, name, value, defaultValue, body };
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Components // Components
@@ -5601,51 +5574,30 @@ function parseTSlot(node, ctx) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Translation // Translation
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function wrapInTTranslationAST(r) {
const ast = { type: 16 /* TTranslation */, content: r };
if (r === null || r === void 0 ? void 0 : r.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
}
function parseTTranslation(node, ctx) { function parseTTranslation(node, ctx) {
if (node.getAttribute("t-translation") !== "off") { if (node.getAttribute("t-translation") !== "off") {
return null; return null;
} }
node.removeAttribute("t-translation"); node.removeAttribute("t-translation");
const result = parseNode(node, ctx); return {
if ((result === null || result === void 0 ? void 0 : result.type) === 3 /* Multi */) { type: 16 /* TTranslation */,
const children = result.content.map(wrapInTTranslationAST); content: parseNode(node, ctx),
return makeASTMulti(children); };
}
return wrapInTTranslationAST(result);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Translation Context // Translation Context
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function wrapInTTranslationContextAST(r, translationCtx) {
const ast = {
type: 17 /* TTranslationContext */,
content: r,
translationCtx,
};
if (r === null || r === void 0 ? void 0 : r.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
}
function parseTTranslationContext(node, ctx) { function parseTTranslationContext(node, ctx) {
const translationCtx = node.getAttribute("t-translation-context"); const translationCtx = node.getAttribute("t-translation-context");
if (!translationCtx) { if (!translationCtx) {
return null; return null;
} }
node.removeAttribute("t-translation-context"); node.removeAttribute("t-translation-context");
const result = parseNode(node, ctx); return {
if ((result === null || result === void 0 ? void 0 : result.type) === 3 /* Multi */) { type: 17 /* TTranslationContext */,
const children = result.content.map((c) => wrapInTTranslationContextAST(c, translationCtx)); content: parseNode(node, ctx),
return makeASTMulti(children); translationCtx,
} };
return wrapInTTranslationContextAST(result, translationCtx);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Portal // Portal
@@ -5690,13 +5642,6 @@ function parseChildren(node, ctx) {
} }
return children; return children;
} }
function makeASTMulti(children) {
const ast = { type: 3 /* Multi */, content: children };
if (children.every((c) => c.hasNoRepresentation)) {
ast.hasNoRepresentation = true;
}
return ast;
}
/** /**
* Parse all the child nodes of a given node and return an ast if possible. * Parse all the child nodes of a given node and return an ast if possible.
* In the case there are multiple children, they are wrapped in a astmulti. * In the case there are multiple children, they are wrapped in a astmulti.
@@ -5709,7 +5654,7 @@ function parseChildNodes(node, ctx) {
case 1: case 1:
return children[0]; return children[0];
default: default:
return makeASTMulti(children); return { type: 3 /* Multi */, content: children };
} }
} }
/** /**
@@ -5813,7 +5758,7 @@ function compile(template, options = {
} }
// do not modify manually. This file is generated by the release script. // do not modify manually. This file is generated by the release script.
const version = "2.8.1"; const version = "2.7.0";
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Scheduler // Scheduler
@@ -6284,6 +6229,6 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
export { App, Component, EventBus, OwlError, __info__, batched, blockDom, htmlEscape, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml }; export { App, Component, EventBus, OwlError, __info__, batched, blockDom, htmlEscape, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };
__info__.date = '2025-09-23T07:17:45.055Z'; __info__.date = '2025-03-26T12:58:40.935Z';
__info__.hash = '5211116'; __info__.hash = 'e788e36';
__info__.url = 'https://github.com/odoo/owl'; __info__.url = 'https://github.com/odoo/owl';
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@odoo/owl", "name": "@odoo/owl",
"version": "2.8.1", "version": "2.7.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@odoo/owl", "name": "@odoo/owl",
"version": "2.8.1", "version": "2.7.0",
"description": "Odoo Web Library (OWL)", "description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js", "main": "dist/owl.cjs.js",
"module": "dist/owl.es.js", "module": "dist/owl.es.js",
+4 -4
View File
@@ -995,7 +995,7 @@ export class CodeGenerator {
const isNewBlock = !block || forceNewBlock; const isNewBlock = !block || forceNewBlock;
let codeIdx = this.target.code.length; let codeIdx = this.target.code.length;
if (isNewBlock) { if (isNewBlock) {
const n = ast.content.filter((c) => !c.hasNoRepresentation).length; const n = ast.content.filter((c) => c.type !== ASTType.TSet).length;
let result: string | null = null; let result: string | null = null;
if (n <= 1) { if (n <= 1) {
for (let child of ast.content) { for (let child of ast.content) {
@@ -1009,15 +1009,15 @@ export class CodeGenerator {
let index = 0; let index = 0;
for (let i = 0, l = ast.content.length; i < l; i++) { for (let i = 0, l = ast.content.length; i < l; i++) {
const child = ast.content[i]; const child = ast.content[i];
const forceNewBlock = !child.hasNoRepresentation; const isTSet = child.type === ASTType.TSet;
const subCtx = createContext(ctx, { const subCtx = createContext(ctx, {
block, block,
index, index,
forceNewBlock, forceNewBlock: !isTSet,
isLast: ctx.isLast && i === l - 1, isLast: ctx.isLast && i === l - 1,
}); });
this.compileAST(child, subCtx); this.compileAST(child, subCtx);
if (forceNewBlock) { if (!isTSet) {
index++; index++;
} }
} }
+40 -95
View File
@@ -31,17 +31,12 @@ export const enum ASTType {
TPortal, TPortal,
} }
export interface BaseAST { export interface ASTText {
type: ASTType;
hasNoRepresentation?: true;
}
export interface ASTText extends BaseAST {
type: ASTType.Text; type: ASTType.Text;
value: string; value: string;
} }
export interface ASTComment extends BaseAST { export interface ASTComment {
type: ASTType.Comment; type: ASTType.Comment;
value: string; value: string;
} }
@@ -57,7 +52,7 @@ interface TModelInfo {
specialInitTargetAttr: string | null; specialInitTargetAttr: string | null;
} }
export interface ASTDomNode extends BaseAST { export interface ASTDomNode {
type: ASTType.DomNode; type: ASTType.DomNode;
tag: string; tag: string;
content: AST[]; content: AST[];
@@ -70,24 +65,24 @@ export interface ASTDomNode extends BaseAST {
ns: string | null; ns: string | null;
} }
export interface ASTMulti extends BaseAST { export interface ASTMulti {
type: ASTType.Multi; type: ASTType.Multi;
content: AST[]; content: AST[];
} }
export interface ASTTEsc extends BaseAST { export interface ASTTEsc {
type: ASTType.TEsc; type: ASTType.TEsc;
expr: string; expr: string;
defaultValue: string; defaultValue: string;
} }
export interface ASTTOut extends BaseAST { export interface ASTTOut {
type: ASTType.TOut; type: ASTType.TOut;
expr: string; expr: string;
body: AST[] | null; body: AST[] | null;
} }
export interface ASTTif extends BaseAST { export interface ASTTif {
type: ASTType.TIf; type: ASTType.TIf;
condition: string; condition: string;
content: AST; content: AST;
@@ -95,16 +90,15 @@ export interface ASTTif extends BaseAST {
tElse: AST | null; tElse: AST | null;
} }
export interface ASTTSet extends BaseAST { export interface ASTTSet {
type: ASTType.TSet; type: ASTType.TSet;
name: string; name: string;
value: string | null; // value defined in attribute value: string | null; // value defined in attribute
defaultValue: string | null; // value defined in body, if text defaultValue: string | null; // value defined in body, if text
body: AST[] | null; // content of body if not text body: AST[] | null; // content of body if not text
hasNoRepresentation: true;
} }
export interface ASTTForEach extends BaseAST { export interface ASTTForEach {
type: ASTType.TForEach; type: ASTType.TForEach;
collection: string; collection: string;
elem: string; elem: string;
@@ -117,13 +111,13 @@ export interface ASTTForEach extends BaseAST {
key: string | null; key: string | null;
} }
export interface ASTTKey extends BaseAST { export interface ASTTKey {
type: ASTType.TKey; type: ASTType.TKey;
expr: string; expr: string;
content: AST; content: AST;
} }
export interface ASTTCall extends BaseAST { export interface ASTTCall {
type: ASTType.TCall; type: ASTType.TCall;
name: string; name: string;
body: AST[] | null; body: AST[] | null;
@@ -138,7 +132,7 @@ interface SlotDefinition {
attrsTranslationCtx: Attrs | null; attrsTranslationCtx: Attrs | null;
} }
export interface ASTComponent extends BaseAST { export interface ASTComponent {
type: ASTType.TComponent; type: ASTType.TComponent;
name: string; name: string;
isDynamic: boolean; isDynamic: boolean;
@@ -149,7 +143,7 @@ export interface ASTComponent extends BaseAST {
slots: { [name: string]: SlotDefinition } | null; slots: { [name: string]: SlotDefinition } | null;
} }
export interface ASTSlot extends BaseAST { export interface ASTSlot {
type: ASTType.TSlot; type: ASTType.TSlot;
name: string; name: string;
attrs: Attrs | null; attrs: Attrs | null;
@@ -158,34 +152,34 @@ export interface ASTSlot extends BaseAST {
defaultContent: AST | null; defaultContent: AST | null;
} }
export interface ASTTCallBlock extends BaseAST { export interface ASTTCallBlock {
type: ASTType.TCallBlock; type: ASTType.TCallBlock;
name: string; name: string;
} }
export interface ASTDebug extends BaseAST { export interface ASTDebug {
type: ASTType.TDebug; type: ASTType.TDebug;
content: AST | null; content: AST | null;
} }
export interface ASTLog extends BaseAST { export interface ASTLog {
type: ASTType.TLog; type: ASTType.TLog;
expr: string; expr: string;
content: AST | null; content: AST | null;
} }
export interface ASTTranslation extends BaseAST { export interface ASTTranslation {
type: ASTType.TTranslation; type: ASTType.TTranslation;
content: AST | null; content: AST | null;
} }
export interface ASTTranslationContext extends BaseAST { export interface ASTTranslationContext {
type: ASTType.TTranslationContext; type: ASTType.TTranslationContext;
content: AST | null; content: AST | null;
translationCtx: string; translationCtx: string;
} }
export interface ASTTPortal extends BaseAST { export interface ASTTPortal {
type: ASTType.TPortal; type: ASTType.TPortal;
target: string; target: string;
content: AST; content: AST;
@@ -259,11 +253,11 @@ function parseNode(node: Node, ctx: ParsingContext): AST | null {
parseTPortal(node, ctx) || parseTPortal(node, ctx) ||
parseTCall(node, ctx) || parseTCall(node, ctx) ||
parseTCallBlock(node, ctx) || parseTCallBlock(node, ctx) ||
parseTTranslation(node, ctx) ||
parseTTranslationContext(node, ctx) ||
parseTKey(node, ctx) ||
parseTEscNode(node, ctx) || parseTEscNode(node, ctx) ||
parseTOutNode(node, ctx) || parseTOutNode(node, ctx) ||
parseTKey(node, ctx) ||
parseTTranslation(node, ctx) ||
parseTTranslationContext(node, ctx) ||
parseTSlot(node, ctx) || parseTSlot(node, ctx) ||
parseComponent(node, ctx) || parseComponent(node, ctx) ||
parseDOMNode(node, ctx) || parseDOMNode(node, ctx) ||
@@ -340,30 +334,20 @@ function parseTCustom(node: Element, ctx: ParsingContext): AST | null {
function parseTDebugLog(node: Element, ctx: ParsingContext): AST | null { function parseTDebugLog(node: Element, ctx: ParsingContext): AST | null {
if (node.hasAttribute("t-debug")) { if (node.hasAttribute("t-debug")) {
node.removeAttribute("t-debug"); node.removeAttribute("t-debug");
const content = parseNode(node, ctx); return {
const ast: ASTDebug = {
type: ASTType.TDebug, type: ASTType.TDebug,
content, content: parseNode(node, ctx),
}; };
if (content?.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
} }
if (node.hasAttribute("t-log")) { if (node.hasAttribute("t-log")) {
const expr = node.getAttribute("t-log")!; const expr = node.getAttribute("t-log")!;
node.removeAttribute("t-log"); node.removeAttribute("t-log");
const content = parseNode(node, ctx); return {
const ast: ASTLog = {
type: ASTType.TLog, type: ASTType.TLog,
expr, expr,
content, content: parseNode(node, ctx),
}; };
if (content?.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
} }
return null; return null;
} }
@@ -614,19 +598,11 @@ function parseTKey(node: Element, ctx: ParsingContext): AST | null {
} }
const key = node.getAttribute("t-key")!; const key = node.getAttribute("t-key")!;
node.removeAttribute("t-key"); node.removeAttribute("t-key");
const content = parseNode(node, ctx); const body = parseNode(node, ctx);
if (!content) { if (!body) {
return null; return null;
} }
const ast: ASTTKey = { return { type: ASTType.TKey, expr: key, content: body };
type: ASTType.TKey,
expr: key,
content,
};
if (content.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -748,7 +724,7 @@ function parseTSetNode(node: Element, ctx: ParsingContext): AST | null {
if (node.textContent !== node.innerHTML) { if (node.textContent !== node.innerHTML) {
body = parseChildren(node, ctx); body = parseChildren(node, ctx);
} }
return { type: ASTType.TSet, name, value, defaultValue, body, hasNoRepresentation: true }; return { type: ASTType.TSet, name, value, defaultValue, body };
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -940,55 +916,32 @@ function parseTSlot(node: Element, ctx: ParsingContext): AST | null {
// Translation // Translation
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function wrapInTTranslationAST(r: AST | null) {
const ast: ASTTranslation = { type: ASTType.TTranslation, content: r };
if (r?.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
}
function parseTTranslation(node: Element, ctx: ParsingContext): AST | null { function parseTTranslation(node: Element, ctx: ParsingContext): AST | null {
if (node.getAttribute("t-translation") !== "off") { if (node.getAttribute("t-translation") !== "off") {
return null; return null;
} }
node.removeAttribute("t-translation"); node.removeAttribute("t-translation");
const result = parseNode(node, ctx); return {
if (result?.type === ASTType.Multi) { type: ASTType.TTranslation,
const children = result.content.map(wrapInTTranslationAST); content: parseNode(node, ctx),
return makeASTMulti(children); };
}
return wrapInTTranslationAST(result);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Translation Context // Translation Context
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function wrapInTTranslationContextAST(r: AST | null, translationCtx: string) {
const ast: ASTTranslationContext = {
type: ASTType.TTranslationContext,
content: r,
translationCtx,
};
if (r?.hasNoRepresentation) {
ast.hasNoRepresentation = true;
}
return ast;
}
function parseTTranslationContext(node: Element, ctx: ParsingContext): AST | null { function parseTTranslationContext(node: Element, ctx: ParsingContext): AST | null {
const translationCtx = node.getAttribute("t-translation-context"); const translationCtx = node.getAttribute("t-translation-context");
if (!translationCtx) { if (!translationCtx) {
return null; return null;
} }
node.removeAttribute("t-translation-context"); node.removeAttribute("t-translation-context");
const result = parseNode(node, ctx); return {
if (result?.type === ASTType.Multi) { type: ASTType.TTranslationContext,
const children = result.content.map((c) => wrapInTTranslationContextAST(c, translationCtx)); content: parseNode(node, ctx),
return makeASTMulti(children); translationCtx,
} };
return wrapInTTranslationContextAST(result, translationCtx);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -1037,14 +990,6 @@ function parseChildren(node: Element, ctx: ParsingContext): AST[] {
return children; return children;
} }
function makeASTMulti(children: AST[]) {
const ast: ASTMulti = { type: ASTType.Multi, content: children };
if (children.every((c) => c.hasNoRepresentation)) {
ast.hasNoRepresentation = true;
}
return ast;
}
/** /**
* Parse all the child nodes of a given node and return an ast if possible. * Parse all the child nodes of a given node and return an ast if possible.
* In the case there are multiple children, they are wrapped in a astmulti. * In the case there are multiple children, they are wrapped in a astmulti.
@@ -1057,7 +1002,7 @@ function parseChildNodes(node: Element, ctx: ParsingContext): AST | null {
case 1: case 1:
return children[0]; return children[0];
default: default:
return makeASTMulti(children); return { type: ASTType.Multi, content: children };
} }
} }
+1 -1
View File
@@ -1,2 +1,2 @@
// do not modify manually. This file is generated by the release script. // do not modify manually. This file is generated by the release script.
export const version = "2.8.1"; export const version = "2.7.0";
@@ -49,27 +49,6 @@ exports[`debugging t-debug on sub template 2`] = `
}" }"
`; `;
exports[`debugging t-debug: interaction with t-set 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
debugger;
setContextValue(ctx, \\"foo\\", 42);
debugger;
setContextValue(ctx, \\"bar\\", 49);
let txt1 = ctx['foo']+ctx['bar'];
return block1([txt1]);
}
}"
`;
exports[`debugging t-log 1`] = ` exports[`debugging t-log 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -87,24 +66,3 @@ exports[`debugging t-log 1`] = `
} }
}" }"
`; `;
exports[`debugging t-log: interaction with t-set 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
console.log(ctx['foo']);
setContextValue(ctx, \\"foo\\", 42);
console.log(ctx['bar']);
setContextValue(ctx, \\"bar\\", 49);
let txt1 = ctx['foo']+ctx['bar'];
return block1([txt1]);
}
}"
`;
@@ -103,18 +103,3 @@ exports[`t-key t-key on sub dom node pushes a child block in its parent 2`] = `
} }
}" }"
`; `;
exports[`t-key t-key: interaction with t-esc 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<p><block-text-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key'];
let txt1 = ctx['text'];
return toggler(tKey_1, block1([txt1]));
}
}"
`;
@@ -10,7 +10,8 @@ exports[`translation context body of t-sets are translated in context 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"label\\", \`traduit\`); setContextValue(ctx, \\"label\\", \`traduit\`);
return text(ctx['label']); const b2 = text(ctx['label']);
return multi([b2]);
} }
}" }"
`; `;
@@ -93,23 +94,6 @@ exports[`translation context slot attrs and text contents are translated in cont
}" }"
`; `;
exports[`translation context t-translation-context with several children 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div><div/><div/><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2;
if (true) {
b2 = text(\`\`);
}
return block1([], [b2]);
}
}"
`;
exports[`translation context translation of attributes in context 1`] = ` exports[`translation context translation of attributes in context 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -169,21 +153,6 @@ exports[`translation support body of t-sets inside translation=off are not trans
}" }"
`; `;
exports[`translation support body of t-sets inside translation=off are not translated 2 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"label\\", \`untranslated\`);
return text(ctx['label']);
}
}"
`;
exports[`translation support body of t-sets with html content are translated 1`] = ` exports[`translation support body of t-sets with html content are translated 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -295,23 +264,6 @@ exports[`translation support t-set and falsy t-value: t-body are translated 1`]
}" }"
`; `;
exports[`translation support t-translation with several children 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div><div/><div/><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2;
if (true) {
b2 = text(\`\`);
}
return block1([], [b2]);
}
}"
`;
exports[`translation support translation is done on the trimmed text, with extra spaces readded after 1`] = ` exports[`translation support translation is done on the trimmed text, with extra spaces readded after 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
+1 -111
View File
@@ -692,7 +692,6 @@ describe("qweb parser", () => {
value: "value", value: "value",
defaultValue: null, defaultValue: null,
body: null, body: null,
hasNoRepresentation: true,
}); });
}); });
@@ -703,7 +702,6 @@ describe("qweb parser", () => {
defaultValue: "ok", defaultValue: "ok",
value: null, value: null,
body: null, body: null,
hasNoRepresentation: true,
}); });
expect(parse(`<t t-set="v"><div>ok</div></t>`)).toEqual({ expect(parse(`<t t-set="v"><div>ok</div></t>`)).toEqual({
@@ -725,7 +723,6 @@ describe("qweb parser", () => {
content: [{ type: ASTType.Text, value: "ok" }], content: [{ type: ASTType.Text, value: "ok" }],
}, },
], ],
hasNoRepresentation: true,
}); });
expect(parse(`<t t-set="v"><div>ok</div>abc</t>`)).toEqual({ expect(parse(`<t t-set="v"><div>ok</div>abc</t>`)).toEqual({
@@ -748,7 +745,6 @@ describe("qweb parser", () => {
}, },
{ type: ASTType.Text, value: "abc" }, { type: ASTType.Text, value: "abc" },
], ],
hasNoRepresentation: true,
}); });
}); });
@@ -762,7 +758,6 @@ describe("qweb parser", () => {
defaultValue: "ok", defaultValue: "ok",
value: null, value: null,
body: null, body: null,
hasNoRepresentation: true,
}, },
tElif: null, tElif: null,
tElse: null, tElse: null,
@@ -788,14 +783,7 @@ describe("qweb parser", () => {
condition: "flag", condition: "flag",
content: { type: ASTType.Text, value: "1" }, content: { type: ASTType.Text, value: "1" },
tElif: null, tElif: null,
tElse: { tElse: { type: ASTType.TSet, name: "ourvar", value: "0", defaultValue: null, body: null },
type: ASTType.TSet,
name: "ourvar",
value: "0",
defaultValue: null,
body: null,
hasNoRepresentation: true,
},
}, },
], ],
}); });
@@ -1983,54 +1971,6 @@ describe("qweb parser", () => {
}); });
}); });
test('t-translation="off": interaction with t-esc', async () => {
expect(parse(`<span t-esc="a" t-translation="off"/>`)).toEqual({
type: ASTType.TTranslation,
content: {
attrs: null,
attrsTranslationCtx: null,
content: [
{
defaultValue: "",
expr: "a",
type: ASTType.TEsc,
},
],
dynamicTag: null,
model: null,
ns: null,
on: null,
ref: null,
tag: "span",
type: ASTType.DomNode,
},
});
});
test('t-translation="off": interaction with t-out', async () => {
expect(parse(`<span t-out="a" t-translation="off"/>`)).toEqual({
type: ASTType.TTranslation,
content: {
attrs: null,
attrsTranslationCtx: null,
content: [
{
body: null,
expr: "a",
type: ASTType.TOut,
},
],
dynamicTag: null,
model: null,
ns: null,
on: null,
ref: null,
tag: "span",
type: ASTType.DomNode,
},
});
});
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// t-translation-context // t-translation-context
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -2068,56 +2008,6 @@ describe("qweb parser", () => {
}); });
}); });
test("t-translation-context: interaction with t-esc", async () => {
expect(parse(`<span t-esc="a" t-translation-context="fr"/>`)).toEqual({
type: ASTType.TTranslationContext,
content: {
attrs: null,
attrsTranslationCtx: null,
content: [
{
defaultValue: "",
expr: "a",
type: ASTType.TEsc,
},
],
dynamicTag: null,
model: null,
ns: null,
on: null,
ref: null,
tag: "span",
type: ASTType.DomNode,
},
translationCtx: "fr",
});
});
test("t-translation-context: interaction with t-out", async () => {
expect(parse(`<span t-out="a" t-translation-context="fr"/>`)).toEqual({
type: ASTType.TTranslationContext,
content: {
attrs: null,
attrsTranslationCtx: null,
content: [
{
body: null,
expr: "a",
type: ASTType.TOut,
},
],
dynamicTag: null,
model: null,
ns: null,
on: null,
ref: null,
tag: "span",
type: ASTType.DomNode,
},
translationCtx: "fr",
});
});
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// t-translation-context-attr // t-translation-context-attr
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
-30
View File
@@ -38,34 +38,4 @@ describe("debugging", () => {
expect(console.log).toHaveBeenCalledWith(45); expect(console.log).toHaveBeenCalledWith(45);
console.log = consoleLog; console.log = consoleLog;
}); });
test("t-log: interaction with t-set", () => {
const consoleLog = console.log;
console.log = jest.fn();
const template = `
<t>
<t t-log="foo" t-set="foo" t-value="42"/>
<t t-log="bar" t-set="bar" t-value="49"/>
<span t-esc="foo + bar"/>
</t>
`;
snapshotTemplate(template);
renderToString(template);
expect(console.log).toHaveBeenCalledWith(undefined);
expect(console.log).toHaveBeenCalledWith(undefined);
console.log = consoleLog;
});
test("t-debug: interaction with t-set", () => {
const template = `
<t>
<t t-debug="" t-set="foo" t-value="42"/>
<t t-debug="" t-set="bar" t-value="49"/>
<span t-esc="foo + bar"/>
</t>
`;
snapshotTemplate(template);
renderToString(template);
});
}); });
-6
View File
@@ -63,10 +63,4 @@ describe("t-key", () => {
expect(renderToString(template2, { key: "1" })).toBe("<div><h1></h1></div>"); expect(renderToString(template2, { key: "1" })).toBe("<div><h1></h1></div>");
}); });
test("t-key: interaction with t-esc", async () => {
const template = `<p t-key="key" t-esc="text"/>`;
expect(renderToString(template, { key: "1", text: "abc" })).toBe("<p>abc</p>");
});
}); });
-47
View File
@@ -129,21 +129,6 @@ describe("translation support", () => {
expect(fixture.innerHTML).toBe("untranslated"); expect(fixture.innerHTML).toBe("untranslated");
}); });
test("body of t-sets inside translation=off are not translated 2", async () => {
class SomeComponent extends Component {
static template = xml`
<t>
<t t-translation="off" t-set="label">untranslated</t>
<t t-esc="label"/>
</t>`;
}
const translateFn = () => "translated";
await mount(SomeComponent, fixture, { translateFn });
expect(fixture.innerHTML).toBe("untranslated");
});
test("body of t-sets with html content are translated", async () => { test("body of t-sets with html content are translated", async () => {
class SomeComponent extends Component { class SomeComponent extends Component {
static template = xml` static template = xml`
@@ -185,22 +170,6 @@ describe("translation support", () => {
await mount(SomeComponent, fixture, { translateFn }); await mount(SomeComponent, fixture, { translateFn });
expect(fixture.innerHTML).toBe("translated"); expect(fixture.innerHTML).toBe("translated");
}); });
test("t-translation with several children", async () => {
class SomeComponent extends Component {
static template = xml`
<div>
<t t-translation="off">
<div/>
<div/>
</t>
<t t-if="true"/>
</div>
`;
}
await mount(SomeComponent, fixture);
expect(fixture.outerHTML).toBe("<div><div><div></div><div></div></div></div>");
});
}); });
describe("translation context", () => { describe("translation context", () => {
@@ -324,20 +293,4 @@ describe("translation context", () => {
expect(translateFn).toHaveBeenCalledWith("param", "fr"); expect(translateFn).toHaveBeenCalledWith("param", "fr");
expect(translateFn).toHaveBeenCalledWith("title", "pt"); expect(translateFn).toHaveBeenCalledWith("title", "pt");
}); });
test("t-translation-context with several children", async () => {
class SomeComponent extends Component {
static template = xml`
<div>
<t t-translation-context="ctx">
<div/>
<div/>
</t>
<t t-if="true"/>
</div>
`;
}
await mount(SomeComponent, fixture);
expect(fixture.outerHTML).toBe("<div><div><div></div><div></div></div></div>");
});
}); });