mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
+2
-1
@@ -38,7 +38,8 @@ keyboard) the button.
|
|||||||
A more complex situation occurs when we want to transition an element in or out
|
A more complex situation occurs when we want to transition an element in or out
|
||||||
of the page. For example, we may want a fade-in and fade-out effect.
|
of the page. For example, we may want a fade-in and fade-out effect.
|
||||||
|
|
||||||
The `t-transition` directive is here to help us (see [QWeb documentation](qweb.md#t-transition-directive)).
|
The `t-transition` directive is here to help us. It works on html elements and
|
||||||
|
on components, by adding and removing some css classes.
|
||||||
|
|
||||||
To perform useful transition effects, whenever an element appears or disappears,
|
To perform useful transition effects, whenever an element appears or disappears,
|
||||||
it is necessary to add/remove some css style or class at some precise moment in
|
it is necessary to add/remove some css style or class at some precise moment in
|
||||||
|
|||||||
+7
-7
@@ -14,7 +14,7 @@
|
|||||||
- [`t-key` directive](#t-key-directive)
|
- [`t-key` directive](#t-key-directive)
|
||||||
- [`t-mounted` directive](#t-mounted-directive)
|
- [`t-mounted` directive](#t-mounted-directive)
|
||||||
- [Props Validation](#props-validation)
|
- [Props Validation](#props-validation)
|
||||||
- [Keeping References](#keeping-references])
|
- [Keeping References](#keeping-references)
|
||||||
- [Asynchronous rendering](#asynchronous-rendering)
|
- [Asynchronous rendering](#asynchronous-rendering)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
@@ -160,13 +160,13 @@ a owl component:
|
|||||||
|
|
||||||
| Method | Description |
|
| Method | Description |
|
||||||
| ------------------------------------------------ | ----------------------------------------------------- |
|
| ------------------------------------------------ | ----------------------------------------------------- |
|
||||||
| **[constructor](#constructor)** | constructor |
|
| **[constructor](#constructorparent-props)** | constructor |
|
||||||
| **[willStart](#willStart)** | async, before first rendering |
|
| **[willStart](#willstart)** | async, before first rendering |
|
||||||
| **[mounted](#mounted)** | just after component is rendered and added to the DOM |
|
| **[mounted](#mounted)** | just after component is rendered and added to the DOM |
|
||||||
| **[willUpdateProps](#willupdatepropsnextprops)** | async, before props update |
|
| **[willUpdateProps](#willupdatepropsnextprops)** | async, before props update |
|
||||||
| **[willPatch](#willpatch)** | just before the DOM is patched |
|
| **[willPatch](#willpatch)** | just before the DOM is patched |
|
||||||
| **[patched](#patchedsnapshot)** | just after the DOM is patched |
|
| **[patched](#patchedsnapshot)** | just after the DOM is patched |
|
||||||
| **[willUnmount](#willUnmount)** | just before removing component from DOM |
|
| **[willUnmount](#willunmount)** | just before removing component from DOM |
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ Note that there are some restrictions on prop names: `class`, `style` and any
|
|||||||
string which starts with `t-` are not allowed.
|
string which starts with `t-` are not allowed.
|
||||||
|
|
||||||
The `t-widget` directive also accepts dynamic values with string interpolation
|
The `t-widget` directive also accepts dynamic values with string interpolation
|
||||||
(like the [`t-attf-`](#dynamic-attributes-t-att-and-t-attf-directives) directive):
|
(like the [`t-attf-`](qweb.md#dynamic-attributes) directive):
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-name="ParentWidget">
|
<div t-name="ParentWidget">
|
||||||
@@ -736,8 +736,8 @@ Note: if used on a component, the reference will be set in the `refs`
|
|||||||
variable between `willPatch` and `patched`.
|
variable between `willPatch` and `patched`.
|
||||||
|
|
||||||
The `t-ref` directive also accepts dynamic values with string interpolation
|
The `t-ref` directive also accepts dynamic values with string interpolation
|
||||||
(like the [`t-attf-`](#dynamic-attributes-t-att-and-t-attf-directives) and
|
(like the [`t-attf-`](qweb.md#dynamic-attributes) and
|
||||||
[`t-widget-`](#component-t-widget) directives). For example, if we have
|
`t-widget` directives). For example, if we have
|
||||||
`id` set to 44 in the rendering context,
|
`id` set to 44 in the rendering context,
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@
|
|||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [Directives](#directives)
|
- [Directives](#directives)
|
||||||
- [QWeb Engine](#qweb-engine)
|
- [QWeb Engine](#qweb-engine)
|
||||||
- [Reference](#qweb-specification)
|
- [Reference](#reference)
|
||||||
- [White spaces](#white-spaces)
|
- [White spaces](#white-spaces)
|
||||||
- [Root nodes](#root-nodes)
|
- [Root nodes](#root-nodes)
|
||||||
- [Expression evaluation](#expression-evaluation)
|
- [Expression evaluation](#expression-evaluation)
|
||||||
@@ -72,7 +72,7 @@ needs. Here is a list of all Owl specific directives:
|
|||||||
| `t-key` | [Defining a key (to help virtual dom reconciliation)](component.md#t-key-directive) |
|
| `t-key` | [Defining a key (to help virtual dom reconciliation)](component.md#t-key-directive) |
|
||||||
| `t-on-*` | [Event handling](component.md#event-handling) |
|
| `t-on-*` | [Event handling](component.md#event-handling) |
|
||||||
| `t-transition` | [Defining an animation](animations.md#css-transitions) |
|
| `t-transition` | [Defining an animation](animations.md#css-transitions) |
|
||||||
| `t-mounted` | [Callback when a node or component is mounted](#component.md#t-mounted-directive) |
|
| `t-mounted` | [Callback when a node or component is mounted](component.md#t-mounted-directive) |
|
||||||
|
|
||||||
## QWeb Engine
|
## QWeb Engine
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* Doc Link Checker
|
||||||
|
*
|
||||||
|
* We define here a test to make sure that there are no dead link in the Owl
|
||||||
|
* documentation.
|
||||||
|
*/
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
const LINK_REGEXP = /\[([^\[]+)\]\(([^\)]+)\)/g;
|
||||||
|
const HEADING_REGEXP = /\n(#+\s*)(.*)/g;
|
||||||
|
|
||||||
|
test("All markdown links work", () => {
|
||||||
|
let linkNumber = 0;
|
||||||
|
let invalidLinkNumber = 0;
|
||||||
|
const data = readDocData();
|
||||||
|
for (let file of data) {
|
||||||
|
for (let link of file.links) {
|
||||||
|
// DEBUG: uncomment next line
|
||||||
|
// console.warn(`Checking "${link.name}" in "${file.name}"`);
|
||||||
|
linkNumber++;
|
||||||
|
if (!isLinkValid(link, file, data)) {
|
||||||
|
console.warn(`Invalid Link: "${link.name}" in "${file.name}"`);
|
||||||
|
invalidLinkNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(invalidLinkNumber).toBe(0);
|
||||||
|
expect(linkNumber).toBeGreaterThan(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
interface MarkDownLink {
|
||||||
|
name: string;
|
||||||
|
link: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MarkDownSection {
|
||||||
|
name: string;
|
||||||
|
slug: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FileData {
|
||||||
|
name: string;
|
||||||
|
links: MarkDownLink[];
|
||||||
|
sections: MarkDownSection[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLinkValid(
|
||||||
|
link: MarkDownLink,
|
||||||
|
current: FileData,
|
||||||
|
files: FileData[]
|
||||||
|
): boolean {
|
||||||
|
const parts = link.link.split("#");
|
||||||
|
if (parts.length === 1) {
|
||||||
|
// no # in url
|
||||||
|
if (parts[0].endsWith(".md")) {
|
||||||
|
// it is a local md file
|
||||||
|
if (!files.find(f => f.name === parts[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const file =
|
||||||
|
parts[0] === "" ? current : files.find(f => f.name === parts[0]);
|
||||||
|
if (!file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!file.sections.find(s => s.slug === parts[1])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// adapted from https://medium.com/@mhagemann/the-ultimate-way-to-slugify-a-url-string-in-javascript-b8e4a0d849e1
|
||||||
|
function slugify(str) {
|
||||||
|
const a = "àáäâãåăæçèéëêǵḧìíïîḿńǹñòóöôœøṕŕßśșțùúüûǘẃẍÿź·_,:;";
|
||||||
|
const b = "aaaaaaaaceeeeghiiiimnnnooooooprssstuuuuuwxyz-----";
|
||||||
|
const p = new RegExp(a.split("").join("|"), "g");
|
||||||
|
return str
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\//g, "") // remove /
|
||||||
|
.replace(/\s+/g, "-") // Replace spaces with -
|
||||||
|
.replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters
|
||||||
|
.replace(/&/g, "-and-") // Replace & with ‘and’
|
||||||
|
.replace(/[^\w\-]+/g, "") // Remove all non-word characters
|
||||||
|
.replace(/\-\-+/g, "-") // Replace multiple - with single -
|
||||||
|
.replace(/^-+/, "") // Trim - from start of text
|
||||||
|
.replace(/-+$/, ""); // Trim - from end of text
|
||||||
|
}
|
||||||
|
|
||||||
|
function readDocData(): FileData[] {
|
||||||
|
const result: FileData[] = [];
|
||||||
|
const FILES = fs.readdirSync("doc");
|
||||||
|
|
||||||
|
for (let file of FILES) {
|
||||||
|
const fileData: FileData = {
|
||||||
|
name: file,
|
||||||
|
links: [],
|
||||||
|
sections: []
|
||||||
|
};
|
||||||
|
const content = fs.readFileSync(`doc/${file}`, { encoding: "utf8" });
|
||||||
|
let m;
|
||||||
|
// get links info
|
||||||
|
do {
|
||||||
|
m = LINK_REGEXP.exec(content);
|
||||||
|
if (m) {
|
||||||
|
fileData.links.push({ name: m[0], link: m[2] });
|
||||||
|
}
|
||||||
|
} while (m);
|
||||||
|
// get sections info
|
||||||
|
do {
|
||||||
|
m = HEADING_REGEXP.exec(content);
|
||||||
|
if (m) {
|
||||||
|
fileData.sections.push({ name: m[0], slug: slugify(m[2]) });
|
||||||
|
}
|
||||||
|
} while (m);
|
||||||
|
|
||||||
|
result.push(fileData);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user