[FIX] doc: fix all dead links

closes #149
This commit is contained in:
Géry Debongnie
2019-06-07 14:31:22 +02:00
parent 7b887447da
commit 54c3dd76e4
4 changed files with 132 additions and 10 deletions
+2 -1
View File
@@ -38,7 +38,8 @@ keyboard) the button.
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.
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,
it is necessary to add/remove some css style or class at some precise moment in
+7 -7
View File
@@ -14,7 +14,7 @@
- [`t-key` directive](#t-key-directive)
- [`t-mounted` directive](#t-mounted-directive)
- [Props Validation](#props-validation)
- [Keeping References](#keeping-references])
- [Keeping References](#keeping-references)
- [Asynchronous rendering](#asynchronous-rendering)
## Overview
@@ -160,13 +160,13 @@ a owl component:
| Method | Description |
| ------------------------------------------------ | ----------------------------------------------------- |
| **[constructor](#constructor)** | constructor |
| **[willStart](#willStart)** | async, before first rendering |
| **[constructor](#constructorparent-props)** | constructor |
| **[willStart](#willstart)** | async, before first rendering |
| **[mounted](#mounted)** | just after component is rendered and added to the DOM |
| **[willUpdateProps](#willupdatepropsnextprops)** | async, before props update |
| **[willPatch](#willpatch)** | just before 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:
@@ -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.
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
<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`.
The `t-ref` directive also accepts dynamic values with string interpolation
(like the [`t-attf-`](#dynamic-attributes-t-att-and-t-attf-directives) and
[`t-widget-`](#component-t-widget) directives). For example, if we have
(like the [`t-attf-`](qweb.md#dynamic-attributes) and
`t-widget` directives). For example, if we have
`id` set to 44 in the rendering context,
```xml
+2 -2
View File
@@ -5,7 +5,7 @@
- [Overview](#overview)
- [Directives](#directives)
- [QWeb Engine](#qweb-engine)
- [Reference](#qweb-specification)
- [Reference](#reference)
- [White spaces](#white-spaces)
- [Root nodes](#root-nodes)
- [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-on-*` | [Event handling](component.md#event-handling) |
| `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
+121
View File
@@ -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;
}