Skip to content

Commit 9f568b6

Browse files
author
Gianluca Beil
committed
Move to different approach
1 parent ee8583f commit 9f568b6

File tree

17 files changed

+510
-379
lines changed

17 files changed

+510
-379
lines changed

CONTRIBUTING.md

Lines changed: 0 additions & 137 deletions
This file was deleted.

ToDo

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ Compare random files manually
33

44
Find issues in layouting also find the reason
55

6-
- Messed up table columns
6+
- [?] Link js files to GitHub (Local Development = main, Else = tmp/pacakges/@ui5)
7+
- [ ] Internal linking to methods is still borked
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/* eslint-disable indent */
2+
import {unified} from "unified";
3+
import rehypeParse from "rehype-parse";
4+
import rehypeRemark from "rehype-remark";
5+
import remarkStringify from "remark-stringify";
6+
import rehypeIgnore from "rehype-ignore";
7+
import rehypeFormat from "rehype-format";
8+
import remarkGfm from "remark-gfm";
9+
import rehypeVideo from "rehype-video";
10+
import fs from "node:fs";
11+
import path from "node:path";
12+
import {toHtml} from "hast-util-to-html";
13+
import {JSDOM} from "jsdom";
14+
15+
const aElementRegex = /<a.*?href="(.*?)".*?>([^<]*)<\/a>/;
16+
17+
function escapeMarkdown(input) {
18+
const map = {
19+
"|": "&#124;"
20+
};
21+
22+
const escapeLine = (line) => {
23+
let out = line;
24+
for (const key of Object.keys(map)) {
25+
out = out.replaceAll(key, map[key]);
26+
}
27+
return out;
28+
};
29+
30+
return input
31+
.split("\n")
32+
.map((line) => {
33+
const trimmed = line.trimStart();
34+
35+
if (trimmed.startsWith("|")) {
36+
return line;
37+
}
38+
39+
return escapeLine(line);
40+
})
41+
.join("\n");
42+
}
43+
44+
function fixMarkdown(input) {
45+
return input.replaceAll("\\<optional>", "Optional").replaceAll("<optional>", "Optional");
46+
}
47+
48+
async function htmlToMarkdown(options = {}) {
49+
const file = await unified()
50+
.use(rehypeParse, {fragment: true})
51+
.use(rehypeIgnore)
52+
.use(remarkGfm)
53+
.use(rehypeVideo)
54+
.use(rehypeFormat)
55+
.use(rehypeRemark, {
56+
document: false,
57+
handlers: {
58+
table(state, node) {
59+
// This fixes nested tables that happen in the conversion from html to markdown
60+
let html = toHtml(node);
61+
const parsedHTML = new JSDOM(html).window.document.getElementsByClassName("params")[1];
62+
if (parsedHTML !== undefined) {
63+
html = parsedHTML.outerHTML;
64+
}
65+
const result = {type: "html", value: html};
66+
state.patch(node, result);
67+
return result;
68+
},
69+
a(state, node) {
70+
// This fixes internal linking e.g. from #~myawesomemethod to #myawesomemethod
71+
const result = {type: "html", value: toHtml(node).replaceAll("~", "")};
72+
let href = result.value.match(aElementRegex);
73+
// Filters for a tags that need fixing
74+
// href !== null - Checks if href is null (A element has no href)
75+
// href[1].split("#")[1] != null - Checks if the a element is an internal link
76+
// !href[2].includes("line") - Checks for links to GitHub source code
77+
if (href !== null && href[1].split("#")[1] != null && !href[2].includes("line")) {
78+
const text = href[2];
79+
href = href[1];
80+
result.value =
81+
result.value.replace(href, href.split("#")[0] + "#" + href.split("#")[1].toLowerCase())
82+
.replace(text, text.replace(href.split("#")[1], "") + "#" + href.split("#")[1])
83+
.replace("##", "#");
84+
}
85+
state.patch(node, result);
86+
return result;
87+
}
88+
}
89+
})
90+
.use(remarkStringify, {
91+
commonmark: true,
92+
entities: true
93+
})
94+
.processSync(options.html);
95+
return String(file);
96+
}
97+
98+
const deadLinks = [];
99+
const deadLinksCheckPromises = [];
100+
const excludedFiles = {"index.html": "", "global.html": "", "custom.css": ""};
101+
const inputDirectory = path.join("dist", "api");
102+
const outputDirectory = path.join("docs", "api");
103+
let packageTagName = "https://github.com/UI5/cli/blob/main/packages/";
104+
105+
// 1. Find tag name
106+
if (process.argv[2] == "gh-pages") {
107+
// Read package.json of packages/builder
108+
const builderJson = JSON.parse(fs.readFileSync("tmp/packages/@ui5/builder/package.json"));
109+
packageTagName = `https://github.com/UI5/cli/blob/cli-v${builderJson["version"]}/packages/`;
110+
}
111+
112+
// 2. Check and create api directory, also remove all existing files if it exists
113+
if (!fs.existsSync(outputDirectory)) {
114+
fs.mkdirSync(outputDirectory);
115+
} else {
116+
for (const file of fs.readdirSync(outputDirectory)) {
117+
fs.rmSync(path.join(outputDirectory, file));
118+
}
119+
}
120+
121+
// 3. Iterate through every .html generated by jsdoc
122+
for (const file of fs.readdirSync(path.join("dist", "api"))) {
123+
// Skip some files
124+
if (excludedFiles[file] !== undefined) continue;
125+
126+
// Skip js files
127+
if (file.endsWith(".js.html")) continue;
128+
129+
const filePath = path.join(inputDirectory, file);
130+
// Skip directories
131+
if (fs.statSync(filePath).isDirectory()) continue;
132+
133+
const mardownPath = path.join(outputDirectory, file.replace(".html", ".md"));
134+
console.log("HTML -> Markdown", "|", filePath, "->", mardownPath);
135+
136+
// Read the html file
137+
const htmlString = fs.readFileSync(filePath);
138+
139+
// Convert html to markdown
140+
let markdown = await htmlToMarkdown({
141+
html: htmlString
142+
});
143+
144+
// Escape characters in markdown
145+
markdown = escapeMarkdown(markdown);
146+
147+
// Fix some markdown syntax e.g. <optional> -> Optional
148+
markdown = fixMarkdown(markdown);
149+
150+
// Point all js links to GitHub
151+
const linkMatches = markdown.matchAll(/"[^"]*\.[A-Za-z0-9]+\.[A-Za-z0-9]+[^"]*"/g);
152+
for (const linkMatch of linkMatches) {
153+
if (!linkMatch[0].endsWith(".js.html\"")) continue;
154+
const githubUrl = packageTagName +
155+
linkMatch[0].replaceAll("\"", "").replace(".js.html", "").replaceAll("_", "/") +
156+
".js";
157+
markdown = markdown
158+
.replaceAll(linkMatch[0].replaceAll("\"", "") + "#line", githubUrl + "#L")
159+
.replaceAll(linkMatch[0].replaceAll("\"", ""), githubUrl);
160+
}
161+
162+
// Add target="_blank" to the a element (Must link to external site) for a better user experience
163+
markdown = markdown.replaceAll("<a href=\"http", "<a target=\"_blank\" href=\"http");
164+
165+
markdown = stripHtmlComments(markdown);
166+
167+
for (const aElement of markdown.matchAll(aElementRegex + "g")) {
168+
deadLinksCheckPromises.push(checkDeadlinks(aElement[1], filePath));
169+
}
170+
171+
// Save markdown file
172+
fs.writeFileSync(
173+
mardownPath,
174+
markdown
175+
);
176+
177+
Promise.all(deadLinksCheckPromises);
178+
}
179+
180+
async function checkDeadlinks(link, sourcePath) {
181+
if ((await fetch(link)).status != 200) {
182+
deadLinks.push({
183+
link: link,
184+
sourcePath: sourcePath
185+
});
186+
}
187+
}
188+
189+
function stripHtmlComments(str) {
190+
return str.replace(/<!--[\s\S]*?-->/g, "");
191+
}
192+
193+
console.log("Conversion done");
194+
console.log("Found", deadLinks.length, "dead links");
195+
if (deadLinks.length != 0) {
196+
console.log(deadLinks);
197+
}

0 commit comments

Comments
 (0)