Skip to content

Commit c141e94

Browse files
committed
Website: Add blog + change markdown engine (no more dangerousSetInnerHtml)
1 parent 10f3901 commit c141e94

26 files changed

Lines changed: 1594 additions & 418 deletions

‎website/package.json‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@
2424
},
2525
"devDependencies": {
2626
"@moox/bs-react-helmet": "^2.0.0",
27+
"@phenomic/markdown-as-json": "^1.0.0",
2728
"bs-platform": "^5.0.4",
2829
"cpy-cli": "^2.0.0",
29-
"front-matter": "^3.0.1",
3030
"glob": "^7.1.3",
31-
"highlight.js": "^9.15.6",
3231
"mkdirp": "^0.5.1",
3332
"module-alias": "^2.2.0",
3433
"opn-cli": "^4.1.0",
@@ -41,7 +40,6 @@
4140
"reason-future": "^2.4.0",
4241
"reason-highlightjs": "^0.2.0",
4342
"reason-react": "^0.7.0",
44-
"remarkable": "^1.7.1",
4543
"static-server-cli": "^1.0.2",
4644
"trash-cli": "^1.4.0"
4745
}

‎website/scripts/BuildWebsite.re‎

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ open Belt;
44
let root = Process.cwd();
55
let outputPath = Path.join([|root, "dist", Consts.baseUrl|]);
66

7-
let indexJsonString =
7+
let docsIndexJsonString =
88
Fs.readFileAsUtf8Sync(
99
Path.join([|root, "build", "docs-src", "__index__.json"|]),
1010
);
11-
let indexJson =
12-
try (indexJsonString->Js.Json.parseExn) {
11+
let docsIndexJson =
12+
try (docsIndexJsonString->Js.Json.parseExn) {
1313
| _ => failwith("Error parsing JSON modules index")
1414
};
15-
let index =
16-
indexJson
15+
let docsIndex =
16+
docsIndexJson
1717
->Js.Json.decodeArray
1818
->Option.map(a =>
1919
a->Array.reduce([||], (acc, s) =>
@@ -25,6 +25,29 @@ let index =
2525
)
2626
->Option.getWithDefault([||]);
2727

28+
let blogIndexJsonString =
29+
Fs.readFileAsUtf8Sync(
30+
Path.join([|root, "build", "blog-posts", "__index__.json"|]),
31+
);
32+
let blogIndexJson =
33+
try (blogIndexJsonString->Js.Json.parseExn) {
34+
| _ => failwith("Error parsing JSON modules index")
35+
};
36+
let blogIndex: array(PrepareMdToJson.blogIndexEntry) =
37+
blogIndexJson
38+
->Js.Json.decodeArray
39+
->Option.map(a =>
40+
a->Array.reduce([||], (acc, entry) =>
41+
entry
42+
->Js.Json.decodeObject
43+
->Option.map(decodedEntry =>
44+
acc->Array.concat([|decodedEntry->Obj.magic|])
45+
)
46+
->Option.getWithDefault(acc)
47+
)
48+
)
49+
->Option.getWithDefault([||]);
50+
2851
// build docs pages
2952
let sourcePath = Path.join([|root, "build", "docs-pages"|]);
3053
Path.join([|sourcePath, "**/!(__index__).json"|])
@@ -35,7 +58,12 @@ Path.join([|sourcePath, "**/!(__index__).json"|])
3558
|> Js.String.replace(sourcePath, "en/docs")
3659
|> Js.String.replace("/index.json", "/index.html")
3760
|> Js.String.replace(".json", "/index.html");
38-
let content = Prerender.file({name, content: file.content}, index);
61+
let content =
62+
Prerender.file(
63+
~file={name, content: file.content},
64+
~docsIndex,
65+
~blogIndex,
66+
);
3967
let f: FsUtils.t = {name: Path.join([|outputPath, name|]), content};
4068
f;
4169
})
@@ -51,18 +79,44 @@ Path.join([|sourcePath, "**/!(__index__).json"|])
5179
|> Js.String.replace(sourcePath, "en/docs")
5280
|> Js.String.replace("/index.json", "/index.html")
5381
|> Js.String.replace(".json", "/index.html");
54-
let content = Prerender.file({name, content: file.content}, index);
82+
let content =
83+
Prerender.file(
84+
~file={name, content: file.content},
85+
~docsIndex,
86+
~blogIndex,
87+
);
88+
let f: FsUtils.t = {name: Path.join([|outputPath, name|]), content};
89+
f;
90+
})
91+
);
92+
93+
// build blog posts
94+
let sourcePath = Path.join([|root, "build", "blog-posts"|]);
95+
Path.join([|sourcePath, "**/!(__index__).json"|])
96+
->FsUtils.transform(files =>
97+
files->Array.map(file => {
98+
let name =
99+
file.name
100+
|> Js.String.replace(sourcePath, "en/blog")
101+
|> Js.String.replace("/index.json", "/index.html")
102+
|> Js.String.replace(".json", "/index.html");
103+
let content =
104+
Prerender.file(
105+
~file={name, content: file.content},
106+
~docsIndex,
107+
~blogIndex,
108+
);
55109
let f: FsUtils.t = {name: Path.join([|outputPath, name|]), content};
56110
f;
57111
})
58112
);
59113

60114
// build urls
61-
[|""|]
115+
[|"", "en/blog"|]
62116
->Array.map(url => {
63117
let f: FsUtils.t = {
64118
name: Path.join([|outputPath, url ++ "/index.html"|]),
65-
content: Prerender.make(~url, ~pageData=None),
119+
content: Prerender.make(~url, ~docsIndex, ~blogIndex, ~pageData=None),
66120
};
67121
f;
68122
})

‎website/scripts/PrepareMdToJson.re‎

Lines changed: 80 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,11 @@ open Belt;
33

44
let root = Process.cwd();
55

6-
{
7-
HighlightJs.(hjs->registerLanguage("reason", reason));
8-
};
6+
Lowlight.(lowlight->registerLanguage("reason", reason));
97

10-
let remarkable =
11-
Remarkable.make(
12-
"full",
13-
{
14-
"html": true,
15-
"linkify": true,
16-
"xhtmlOut": true,
17-
"langPrefix": "hljs language-",
18-
"highlight":
19-
Some(
20-
(code, lang) =>
21-
try (
22-
{
23-
HighlightJs.highlight(~lang, code)##value;
24-
}
25-
) {
26-
| _ => ""
27-
},
28-
),
29-
},
30-
);
8+
[@bs.module] external mdToJson: string => 'a = "@phenomic/markdown-as-json";
319

32-
Js.log("Pages...");
10+
Js.log("Docs pages...");
3311
let sourcePath = Path.join([|root, "docs"|]);
3412
let outputPath = Path.join([|root, "build", "docs-pages"|]);
3513
Path.join([|sourcePath, "**/*.md"|])
@@ -41,15 +19,11 @@ Path.join([|sourcePath, "**/*.md"|])
4119
(files, file) => {
4220
let shortName =
4321
file.name
44-
|> Js.String.replace(sourcePath, "")
22+
|> Js.String.replace(sourcePath ++ "/", "")
4523
|> Js.String.replace(".md", "");
46-
let front = FrontMatter.parse(file.content);
24+
let mdJson = mdToJson(file.content);
4725
let content =
48-
{
49-
"id": front##attributes##id,
50-
"title": front##attributes##title,
51-
"body": Remarkable.render(remarkable, front##body),
52-
}
26+
{"id": mdJson##id, "title": mdJson##title, "body": mdJson##body}
5327
->Js.Json.stringifyAny;
5428
if (content->Option.isNone) {
5529
Js.log2(file.name, "can't be transformed");
@@ -83,51 +57,6 @@ Path.join([|sourcePath, "**/*.md"|])
8357
|]);
8458
});
8559

86-
Js.log("Create missing markdown files (wip)...");
87-
// create missing md for modules
88-
[@bs.module "fs"] external existsSync: string => bool = "existsSync";
89-
let createMissingMd = (sourcePath, outputPath, files) => {
90-
let newFiles: array(FsUtils.t) = [||];
91-
files->Array.reduce(
92-
newFiles,
93-
(files, file: FsUtils.t) => {
94-
let shortName =
95-
file.name
96-
|> Js.String.replace(sourcePath ++ "/", "")
97-
|> Js.String.replace(".rei", "")
98-
|> Js.String.replace(".re", "");
99-
let finalfilename = Path.join([|outputPath, shortName ++ ".md"|]);
100-
if (try (!existsSync(finalfilename)) {
101-
| _ => true
102-
}) {
103-
let name = shortName->Path.basename;
104-
let code = file.content;
105-
let content = {j|---
106-
id: $shortName
107-
title: $name
108-
wip: true
109-
---
110-
111-
```reason
112-
$code
113-
```
114-
|j};
115-
files->Array.concat([|{name: finalfilename, content}|]);
116-
} else {
117-
files;
118-
};
119-
},
120-
);
121-
};
122-
let sourcePath = Path.join([|root, "..", "reason-react-native", "src"|]);
123-
let outputPath = Path.join([|root, "..", "reason-react-native", "src"|]);
124-
// create from rei first
125-
Path.join([|sourcePath, "(apis|components)/*.rei"|])
126-
->FsUtils.transform(createMissingMd(sourcePath, outputPath));
127-
// fallback to re
128-
Path.join([|sourcePath, "(apis|components)/*.re"|])
129-
->FsUtils.transform(createMissingMd(sourcePath, outputPath));
130-
13160
Js.log("Modules...");
13261
let sourcePath = Path.join([|root, "..", "reason-react-native", "src"|]);
13362
let outputPath = Path.join([|root, "build", "docs-src"|]);
@@ -140,18 +69,17 @@ Path.join([|sourcePath, "**/*.md"|])
14069
(files, file) => {
14170
let shortName =
14271
file.name
143-
|> Js.String.replace(sourcePath, "")
72+
|> Js.String.replace(sourcePath ++ "/", "")
14473
|> Js.String.replace(".md", "");
145-
let front = FrontMatter.parse(file.content);
74+
let mdJson = mdToJson(file.content);
14675
let content =
14776
{
148-
"id": front##attributes##id,
149-
"title": front##attributes##title,
150-
"wip": front##attributes##wip,
151-
"autoLinkToOfficialDoc":
152-
front##attributes##autoLinkToOfficialDoc,
153-
"officialDoc": front##attributes##officialDoc,
154-
"body": Remarkable.render(remarkable, front##body),
77+
"id": mdJson##id,
78+
"title": mdJson##title,
79+
"wip": mdJson##wip,
80+
"autoLinkToOfficialDoc": mdJson##autoLinkToOfficialDoc,
81+
"officialDoc": mdJson##officialDoc,
82+
"body": mdJson##body,
15583
}
15684
->Js.Json.stringifyAny;
15785
if (content->Option.isNone) {
@@ -185,3 +113,69 @@ Path.join([|sourcePath, "**/*.md"|])
185113
},
186114
|]);
187115
});
116+
117+
Js.log("Blog post...");
118+
type blogIndexEntry = {
119+
.
120+
"id": string,
121+
"title": string,
122+
"author": string,
123+
"date": string,
124+
};
125+
let sourcePath = Path.join([|root, "blog"|]);
126+
let outputPath = Path.join([|root, "build", "blog-posts"|]);
127+
Path.join([|sourcePath, "**/*.md"|])
128+
->FsUtils.transform(files => {
129+
let newFiles: array(FsUtils.t) = [||];
130+
let index: ref(array(blogIndexEntry)) = ref([||]);
131+
let finalFiles =
132+
files->Array.reduce(
133+
newFiles,
134+
(files, file) => {
135+
let shortName =
136+
file.name
137+
|> Js.String.replace(sourcePath ++ "/", "")
138+
|> Js.String.replace(".md", "");
139+
let mdJson = mdToJson(file.content);
140+
let content =
141+
{
142+
"id": mdJson##id,
143+
"title": mdJson##title,
144+
"author": mdJson##author,
145+
"date": shortName->Js.String.slice(~from=0, ~to_=10),
146+
"body": mdJson##body,
147+
}
148+
->Js.Json.stringifyAny;
149+
if (content->Option.isNone) {
150+
Js.log2(file.name, "can't be transformed");
151+
};
152+
content
153+
->Option.map(content => {
154+
index :=
155+
(index^)
156+
->Array.concat([|
157+
{
158+
"id": mdJson##id,
159+
"title": mdJson##title,
160+
"author": mdJson##author,
161+
"date": shortName->Js.String.slice(~from=0, ~to_=10),
162+
},
163+
|]);
164+
files->Array.concat([|
165+
{
166+
name: Path.join([|outputPath, shortName ++ ".json"|]),
167+
content,
168+
},
169+
|]);
170+
})
171+
->Option.getWithDefault(files);
172+
},
173+
);
174+
finalFiles->Array.concat([|
175+
{
176+
name: Path.join([|outputPath, "__index__.json"|]),
177+
content:
178+
(index^ |> Js.Json.stringifyAny)->Option.getWithDefault("[]"),
179+
},
180+
|]);
181+
});

0 commit comments

Comments
 (0)