mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fe176f13a5 |
@@ -107,7 +107,7 @@ is necessary, since Owl needs to react to a change in state.
|
|||||||
### `useRef`
|
### `useRef`
|
||||||
|
|
||||||
The `useRef` hook is useful when we need a way to interact with some inside part
|
The `useRef` hook is useful when we need a way to interact with some inside part
|
||||||
of a component, rendered by Owl. It only work on a html element tagged by the
|
of a component, rendered by Owl. It only work on a HTML element tagged by the
|
||||||
`t-ref` directive:
|
`t-ref` directive:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
@@ -227,12 +227,12 @@ function useSomething() {
|
|||||||
|
|
||||||
This hook will run a callback when a component is mounted and patched, and
|
This hook will run a callback when a component is mounted and patched, and
|
||||||
will run a cleanup function before patching and before unmounting the
|
will run a cleanup function before patching and before unmounting the
|
||||||
the component (only if some dependencies have changed).
|
component (only if some dependencies have changed).
|
||||||
|
|
||||||
It has almost the same API as the React `useEffect` hook, except that the dependencies
|
It has almost the same API as the React `useEffect` hook, except that the dependencies
|
||||||
are defined by a function instead of just the dependencies.
|
are defined by a function instead of just the dependencies.
|
||||||
|
|
||||||
The `useEffect` hook takes two function: the effect function and the dependency
|
The `useEffect` hook takes two functions: the effect function and the dependency
|
||||||
function. The effect function perform some task and return (optionally) a cleanup
|
function. The effect function perform some task and return (optionally) a cleanup
|
||||||
function. The dependency function returns a list of dependencies, these dependencies
|
function. The dependency function returns a list of dependencies, these dependencies
|
||||||
are passed as parameters in the effect function . If any of these
|
are passed as parameters in the effect function . If any of these
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
+26
-72
@@ -4539,7 +4539,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 +4553,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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4979,9 +4979,9 @@ function parseNode(node, ctx) {
|
|||||||
parseTCallBlock(node) ||
|
parseTCallBlock(node) ||
|
||||||
parseTTranslation(node, ctx) ||
|
parseTTranslation(node, ctx) ||
|
||||||
parseTTranslationContext(node, ctx) ||
|
parseTTranslationContext(node, ctx) ||
|
||||||
parseTKey(node, ctx) ||
|
|
||||||
parseTEscNode(node, ctx) ||
|
parseTEscNode(node, ctx) ||
|
||||||
parseTOutNode(node, ctx) ||
|
parseTOutNode(node, ctx) ||
|
||||||
|
parseTKey(node, ctx) ||
|
||||||
parseTSlot(node, ctx) ||
|
parseTSlot(node, ctx) ||
|
||||||
parseComponent(node, ctx) ||
|
parseComponent(node, ctx) ||
|
||||||
parseDOMNode(node, ctx) ||
|
parseDOMNode(node, ctx) ||
|
||||||
@@ -5049,29 +5049,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 +5291,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 +5404,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 +5583,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 +5651,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 +5663,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 +5767,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.8.0";
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Scheduler
|
// Scheduler
|
||||||
@@ -6284,6 +6238,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-06-30T12:46:06.424Z';
|
||||||
__info__.hash = '5211116';
|
__info__.hash = 'b620502';
|
||||||
__info__.url = 'https://github.com/odoo/owl';
|
__info__.url = 'https://github.com/odoo/owl';
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odoo/owl",
|
"name": "@odoo/owl",
|
||||||
"version": "2.8.1",
|
"version": "2.8.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odoo/owl",
|
"name": "@odoo/owl",
|
||||||
"version": "2.8.1",
|
"version": "2.8.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",
|
||||||
|
|||||||
@@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-93
@@ -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;
|
||||||
@@ -261,9 +255,9 @@ function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
|||||||
parseTCallBlock(node, ctx) ||
|
parseTCallBlock(node, ctx) ||
|
||||||
parseTTranslation(node, ctx) ||
|
parseTTranslation(node, ctx) ||
|
||||||
parseTTranslationContext(node, ctx) ||
|
parseTTranslationContext(node, ctx) ||
|
||||||
parseTKey(node, ctx) ||
|
|
||||||
parseTEscNode(node, ctx) ||
|
parseTEscNode(node, ctx) ||
|
||||||
parseTOutNode(node, ctx) ||
|
parseTOutNode(node, ctx) ||
|
||||||
|
parseTKey(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 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ export function handleError(params: ErrorParams) {
|
|||||||
let current: Fiber | null = fiber;
|
let current: Fiber | null = fiber;
|
||||||
do {
|
do {
|
||||||
current.node.fiber = current;
|
current.node.fiber = current;
|
||||||
fibersInError.set(current, error);
|
|
||||||
current = current.parent;
|
current = current.parent;
|
||||||
} while (current);
|
} while (current);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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.8.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
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -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,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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>");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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>");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -94,52 +94,6 @@ exports[`basics no component catching error lead to full app destruction 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`basics render from above on error -- handler is not a Root or MountFiber 1`] = `
|
|
||||||
"function anonymous(app, bdom, helpers
|
|
||||||
) {
|
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
|
||||||
const comp1 = app.createComponent(\`Parent\`, true, false, false, []);
|
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
|
||||||
return comp1({}, key + \`__1\`, node, this, null);
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`basics render from above on error -- handler is not a Root or MountFiber 2`] = `
|
|
||||||
"function anonymous(app, bdom, helpers
|
|
||||||
) {
|
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
|
||||||
const comp1 = app.createComponent(\`Boom\`, true, false, false, []);
|
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
|
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
|
||||||
let b2, b3;
|
|
||||||
if (ctx['error']) {
|
|
||||||
b2 = text(\`Error\`);
|
|
||||||
} else {
|
|
||||||
b3 = comp1({onError: (ctx['handleError']).bind(this)}, key + \`__1\`, node, this, null);
|
|
||||||
}
|
|
||||||
return block1([], [b2, b3]);
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`basics render from above on error -- handler is not a Root or MountFiber 3`] = `
|
|
||||||
"function anonymous(app, bdom, helpers
|
|
||||||
) {
|
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-text-0/></div>\`);
|
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
|
||||||
let txt1 = ctx['a'].b.c;
|
|
||||||
return block1([txt1]);
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`basics simple catchError 1`] = `
|
exports[`basics simple catchError 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -233,44 +233,6 @@ function(app, bdom, helpers) {
|
|||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
expect(mockConsoleError).toBeCalledTimes(0);
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(0);
|
expect(mockConsoleWarn).toBeCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("render from above on error -- handler is not a Root or MountFiber", async () => {
|
|
||||||
class Boom extends Component {
|
|
||||||
static template = xml`<div t-esc="a.b.c"/>`;
|
|
||||||
setup() {
|
|
||||||
onError((err) => {
|
|
||||||
this.props.onError(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Parent extends Component {
|
|
||||||
static template = xml`
|
|
||||||
<div>
|
|
||||||
<t t-if="error">Error</t>
|
|
||||||
<t t-else="">
|
|
||||||
<Boom onError.bind="handleError"/>
|
|
||||||
</t>
|
|
||||||
</div>`;
|
|
||||||
static components = { Boom };
|
|
||||||
|
|
||||||
error: any = false;
|
|
||||||
|
|
||||||
handleError(err: Error) {
|
|
||||||
this.error = err;
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GrandParent extends Component {
|
|
||||||
static template: string = xml`<Parent />`;
|
|
||||||
static components = { Parent };
|
|
||||||
}
|
|
||||||
await mount(GrandParent, fixture);
|
|
||||||
expect(fixture.innerHTML).toBe("<div>Error</div>");
|
|
||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(0);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("errors and promises", () => {
|
describe("errors and promises", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user