mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] *: run prettier
This commit is contained in:
@@ -13,7 +13,6 @@ A rendering occurs in two phases:
|
|||||||
- virtual rendering: this generates the virtual dom in memory, asynchronously
|
- virtual rendering: this generates the virtual dom in memory, asynchronously
|
||||||
- patch: applies a virtual tree to the screen (synchronously)
|
- patch: applies a virtual tree to the screen (synchronously)
|
||||||
|
|
||||||
|
|
||||||
There are several classes involved in a rendering:
|
There are several classes involved in a rendering:
|
||||||
|
|
||||||
- components
|
- components
|
||||||
@@ -21,9 +20,9 @@ There are several classes involved in a rendering:
|
|||||||
- fibers: small objects containing some metadata, associated with a rendering of
|
- fibers: small objects containing some metadata, associated with a rendering of
|
||||||
a specific component
|
a specific component
|
||||||
|
|
||||||
|
|
||||||
Components are organized in a dynamic component tree, visible in the user
|
Components are organized in a dynamic component tree, visible in the user
|
||||||
interface. Whenever a rendering is initiated in a component `C`:
|
interface. Whenever a rendering is initiated in a component `C`:
|
||||||
|
|
||||||
- a fiber is created on `C` with the rendering props information
|
- a fiber is created on `C` with the rendering props information
|
||||||
- the virtual rendering phase starts on C (will asynchronously render all the
|
- the virtual rendering phase starts on C (will asynchronously render all the
|
||||||
child components)
|
child components)
|
||||||
@@ -31,4 +30,3 @@ interface. Whenever a rendering is initiated in a component `C`:
|
|||||||
animation frame, if the fiber is done
|
animation frame, if the fiber is done
|
||||||
- once it is done, the scheduler will call the task callback, which will apply
|
- once it is done, the scheduler will call the task callback, which will apply
|
||||||
the patch (if it was not cancelled in the meantime).
|
the patch (if it was not cancelled in the meantime).
|
||||||
|
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ will perform a strict equality check and will update the component every time th
|
|||||||
check fails.
|
check fails.
|
||||||
|
|
||||||
Also, it may not be obvious, but it is crucial to remember that the selector
|
Also, it may not be obvious, but it is crucial to remember that the selector
|
||||||
function should return an object or an array. The reason is that it needs to be
|
function should return an object or an array. The reason is that it needs to be
|
||||||
observed, otherwise the component would not be able to react to changes.
|
observed, otherwise the component would not be able to react to changes.
|
||||||
|
|
||||||
### `useDispatch`
|
### `useDispatch`
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ describe("props validation", () => {
|
|||||||
async __updateProps() {
|
async __updateProps() {
|
||||||
try {
|
try {
|
||||||
await Component.prototype.__updateProps.apply(this, arguments);
|
await Component.prototype.__updateProps.apply(this, arguments);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ interface MarkDownSection {
|
|||||||
interface FileData {
|
interface FileData {
|
||||||
name: string;
|
name: string;
|
||||||
path: string[];
|
path: string[];
|
||||||
fullName: string
|
fullName: string;
|
||||||
links: MarkDownLink[];
|
links: MarkDownLink[];
|
||||||
sections: MarkDownSection[];
|
sections: MarkDownSection[];
|
||||||
}
|
}
|
||||||
@@ -31,30 +31,27 @@ interface FileData {
|
|||||||
const LINK_REGEXP = /\[([^\[]+)\]\(([^\)]+)\)/g;
|
const LINK_REGEXP = /\[([^\[]+)\]\(([^\)]+)\)/g;
|
||||||
const HEADING_REGEXP = /\n(#+\s*)(.*)/g;
|
const HEADING_REGEXP = /\n(#+\s*)(.*)/g;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function addMardownData(fileData): void {
|
export function addMardownData(fileData): void {
|
||||||
const sep = fileData.path.length > 0 ? '/' : '';
|
const sep = fileData.path.length > 0 ? "/" : "";
|
||||||
const fullName = fileData.path.join('/') + sep + fileData.name;
|
const fullName = fileData.path.join("/") + sep + fileData.name;
|
||||||
const content = fs.readFileSync(fullName, { encoding: "utf8" });
|
const content = fs.readFileSync(fullName, { encoding: "utf8" });
|
||||||
let m;
|
let m;
|
||||||
// get links info
|
// get links info
|
||||||
do {
|
do {
|
||||||
m = LINK_REGEXP.exec(content);
|
m = LINK_REGEXP.exec(content);
|
||||||
if (m) {
|
if (m) {
|
||||||
fileData.links.push({ name: m[0], link: m[2] });
|
fileData.links.push({ name: m[0], link: m[2] });
|
||||||
}
|
}
|
||||||
} while (m);
|
} while (m);
|
||||||
// get sections info
|
// get sections info
|
||||||
do {
|
do {
|
||||||
m = HEADING_REGEXP.exec(content);
|
m = HEADING_REGEXP.exec(content);
|
||||||
if (m) {
|
if (m) {
|
||||||
fileData.sections.push({ name: m[0], slug: slugify(m[2]) });
|
fileData.sections.push({ name: m[0], slug: slugify(m[2]) });
|
||||||
}
|
}
|
||||||
} while (m);
|
} while (m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of FileData corresponding to all files that need to be
|
* Returns a list of FileData corresponding to all files that need to be
|
||||||
* validated.
|
* validated.
|
||||||
@@ -74,7 +71,7 @@ function getFiles(path: string[] = []): FileData[] {
|
|||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
return getFiles(path.concat(f.name));
|
return getFiles(path.concat(f.name));
|
||||||
}
|
}
|
||||||
const fullName = path.join('/') + (path.length > 0 ? '/' : '') + f.name;
|
const fullName = path.join("/") + (path.length > 0 ? "/" : "") + f.name;
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: f.name,
|
name: f.name,
|
||||||
@@ -88,62 +85,62 @@ function getFiles(path: string[] = []): FileData[] {
|
|||||||
return Array.prototype.concat(...files);
|
return Array.prototype.concat(...files);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOCAL_FILES = ['LICENSE'];
|
const LOCAL_FILES = ["LICENSE"];
|
||||||
export function isLinkValid(link: MarkDownLink, current: FileData, files: FileData[]): boolean {
|
export function isLinkValid(link: MarkDownLink, current: FileData, files: FileData[]): boolean {
|
||||||
if (link.link.startsWith("http")) {
|
if (link.link.startsWith("http")) {
|
||||||
// no check on external links
|
// no check on external links
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Step 1: extract path, name, hash
|
// Step 1: extract path, name, hash
|
||||||
// path = ['doc', 'architecture]
|
// path = ['doc', 'architecture]
|
||||||
// name = 'rendering.md'
|
// name = 'rendering.md'
|
||||||
// hash = 'blabla' (or '' if no hash)
|
// hash = 'blabla' (or '' if no hash)
|
||||||
|
|
||||||
const parts = link.link.split('#');
|
const parts = link.link.split("#");
|
||||||
const hash = parts[1] || '';
|
const hash = parts[1] || "";
|
||||||
let name;
|
let name;
|
||||||
let path;
|
let path;
|
||||||
if (parts[0]) {
|
if (parts[0]) {
|
||||||
let temp = parts[0].split('/');
|
let temp = parts[0].split("/");
|
||||||
name = temp[temp.length - 1];
|
name = temp[temp.length - 1];
|
||||||
temp.splice(-1);
|
temp.splice(-1);
|
||||||
path = current.path.slice();
|
path = current.path.slice();
|
||||||
for (let elem of temp) {
|
for (let elem of temp) {
|
||||||
if (elem === '..') {
|
if (elem === "..") {
|
||||||
path.splice(-1);
|
path.splice(-1);
|
||||||
} else if (elem !== '.') {
|
} else if (elem !== ".") {
|
||||||
path.push(elem);
|
path.push(elem);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// there are no file name, so this is a relative link to the current file
|
|
||||||
name = current.name;
|
|
||||||
path = current.path;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// there are no file name, so this is a relative link to the current file
|
||||||
|
name = current.name;
|
||||||
|
path = current.path;
|
||||||
|
}
|
||||||
|
|
||||||
// Step 2: build normalized link file name
|
// Step 2: build normalized link file name
|
||||||
const linkFullName = path.join('/') + (path.length > 0 ? '/' : '') + name;
|
const linkFullName = path.join("/") + (path.length > 0 ? "/" : "") + name;
|
||||||
|
|
||||||
// Step 3: check link name against white list of local files
|
|
||||||
if (LOCAL_FILES.includes(linkFullName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 4: check if there is a matching file
|
|
||||||
let target: FileData | undefined = files.find(f => f.fullName === linkFullName);
|
|
||||||
if (!target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5: if necessary, check if there is a corresponding link inside the target
|
|
||||||
// link name
|
|
||||||
if (hash) {
|
|
||||||
if (!target.sections.find(s => s.slug === hash)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Step 3: check link name against white list of local files
|
||||||
|
if (LOCAL_FILES.includes(linkFullName)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4: check if there is a matching file
|
||||||
|
let target: FileData | undefined = files.find(f => f.fullName === linkFullName);
|
||||||
|
if (!target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5: if necessary, check if there is a corresponding link inside the target
|
||||||
|
// link name
|
||||||
|
if (hash) {
|
||||||
|
if (!target.sections.find(s => s.slug === hash)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adapted from https://medium.com/@mhagemann/the-ultimate-way-to-slugify-a-url-string-in-javascript-b8e4a0d849e1
|
// adapted from https://medium.com/@mhagemann/the-ultimate-way-to-slugify-a-url-string-in-javascript-b8e4a0d849e1
|
||||||
@@ -164,25 +161,23 @@ function slugify(str) {
|
|||||||
.replace(/-+$/, ""); // Trim - from end of text
|
.replace(/-+$/, ""); // Trim - from end of text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Test
|
// Test
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
test("All markdown links work", () => {
|
test("All markdown links work", () => {
|
||||||
let linkNumber = 0;
|
let linkNumber = 0;
|
||||||
let invalidLinkNumber = 0;
|
let invalidLinkNumber = 0;
|
||||||
const data = getFiles();
|
const data = getFiles();
|
||||||
for (let file of data) {
|
for (let file of data) {
|
||||||
for (let link of file.links) {
|
for (let link of file.links) {
|
||||||
linkNumber++;
|
linkNumber++;
|
||||||
if (!isLinkValid(link, file, data)) {
|
if (!isLinkValid(link, file, data)) {
|
||||||
console.warn(`Invalid Link: "${link.name}" in "${file.name}"`);
|
console.warn(`Invalid Link: "${link.name}" in "${file.name}"`);
|
||||||
invalidLinkNumber++;
|
invalidLinkNumber++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(invalidLinkNumber).toBe(0);
|
expect(invalidLinkNumber).toBe(0);
|
||||||
expect(linkNumber).toBeGreaterThan(10);
|
expect(linkNumber).toBeGreaterThan(10);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -54,13 +54,12 @@ describe("router miscellaneous", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("navigate in hash mode preserve location", async () => {
|
test("navigate in hash mode preserve location", async () => {
|
||||||
router = new TestRouter(env, [{ name: "users", path: "/users/{{id}}" }], {mode: "hash"});
|
router = new TestRouter(env, [{ name: "users", path: "/users/{{id}}" }], { mode: "hash" });
|
||||||
window.history.pushState({}, "title", window.location.origin + '/test.html');
|
window.history.pushState({}, "title", window.location.origin + "/test.html");
|
||||||
expect(window.location.href).toBe("http://localhost/test.html");
|
expect(window.location.href).toBe("http://localhost/test.html");
|
||||||
await router.navigate({ to: "users", params: { id: 3 } });
|
await router.navigate({ to: "users", params: { id: 3 } });
|
||||||
expect(window.location.href).toBe("http://localhost/test.html#/users/3");
|
expect(window.location.href).toBe("http://localhost/test.html#/users/3");
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("routeToPath", () => {
|
describe("routeToPath", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user