Skip to content

Commit 40380b8

Browse files
committed
🎉 init: Init
0 parents commit 40380b8

File tree

12 files changed

+4101
-0
lines changed

12 files changed

+4101
-0
lines changed

.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.DS_Store
2+
node_modules/
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
7+
# Editor directories and files
8+
.idea
9+
.vscode
10+
*.suo
11+
*.ntvs*
12+
*.njsproj
13+
*.sln
14+
.history
15+
/dist/*
16+
!/dist/.gitignore
17+
/docs/*
18+
!/docs/.gitignore
19+
/icons/*
20+
!/icons/.gitignore

DocSet.js

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
const fs = require("fs");
2+
const path = require("path");
3+
const exec = require("sync-exec");
4+
const db = require("sqlite-sync");
5+
const cheerio = require("cheerio");
6+
7+
module.exports = class DocSet {
8+
constructor(options) {
9+
this.docset = {
10+
...options,
11+
...this.getPaths(options),
12+
infoPlist: this.getInfoPlist(options),
13+
};
14+
this.timer = null;
15+
}
16+
17+
build() {
18+
this.createBaseIndex();
19+
this.createSqliteIndex();
20+
this.readDirSync(this.docset.docPath);
21+
}
22+
23+
getPaths(options) {
24+
const basePath = path.join(
25+
__dirname,
26+
"dist",
27+
`${options.displayName}.docset`
28+
);
29+
const resPath = path.join(basePath, `/Contents/Resources`);
30+
const docPath = path.join(resPath, `/Documents/${options.domain}`);
31+
return {
32+
basePath,
33+
resPath,
34+
docPath,
35+
};
36+
}
37+
38+
getInfoPlist(options) {
39+
return `<?xml version="1.0" encoding="UTF-8"?>
40+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
41+
<plist version="1.0">
42+
<dict>
43+
<key>CFBundleIdentifier</key>
44+
<string>${options.name}</string>
45+
<key>CFBundleName</key>
46+
<string>${options.displayName}</string>
47+
<key>DocSetPlatformFamily</key>
48+
<string>${options.platformFamily}</string>
49+
<key>isDashDocset</key>
50+
<true/>
51+
<key>DashDocSetFamily</key>
52+
<string>dashtoc3</string>
53+
<key>dashIndexFilePath</key>
54+
<string>${options.entry}</string>
55+
</dict>
56+
</plist>`;
57+
}
58+
59+
createBaseIndex() {
60+
exec(`rm -rf ${this.docset.resPath}`);
61+
exec(`mkdir ${this.docset.resPath}`);
62+
exec(
63+
`cp ${__dirname}/icons/${this.docset.name}.png ${this.docset.basePath}/icon.png`
64+
);
65+
exec(
66+
`cp -r ${__dirname}/docs/${this.docset.name} ${this.docset.resPath}/Documents`
67+
);
68+
exec(`find ${path.join(__dirname)} -name '*.DS_Store' -type f -delete;`); // 删除当前目录下的 .DS_Store 文件
69+
70+
fs.writeFileSync(
71+
`${this.docset.basePath}/Contents/Info.plist`,
72+
this.docset.infoPlist
73+
);
74+
}
75+
76+
createSqliteIndex() {
77+
exec(`rm -rf ${this.docset.resPath}/docSet.dsidx`);
78+
79+
db.connect(`${this.docset.resPath}/docSet.dsidx`);
80+
db.run(
81+
`CREATE TABLE searchIndex (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, type TEXT, path TEXT);`,
82+
undefined,
83+
undefined
84+
);
85+
db.run(
86+
`CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);`,
87+
undefined,
88+
undefined
89+
);
90+
}
91+
92+
readDirSync(_path) {
93+
let _this = this;
94+
let paths = fs.readdirSync(_path);
95+
for (const item of paths) {
96+
const itemPath = path.join(_path, item).replace(/\\/g, "/");
97+
// 排除
98+
if (
99+
this.docset.exclude &&
100+
this.docset.exclude.find((regex) => new RegExp(regex).test(itemPath))
101+
) {
102+
return;
103+
}
104+
// 包含
105+
if (
106+
this.docset.include &&
107+
this.docset.include.length > 0 &&
108+
!this.docset.include.find((regex) => new RegExp(regex).test(itemPath))
109+
) {
110+
return;
111+
}
112+
// 目录
113+
if (fs.statSync(itemPath).isDirectory()) {
114+
_this.readDirSync(itemPath);
115+
continue;
116+
}
117+
118+
if (![".html", ".htm"].includes(path.extname(itemPath))) {
119+
return;
120+
}
121+
122+
let relativePath = itemPath.split("Documents/")[1];
123+
124+
let html = fs.readFileSync(itemPath, {
125+
encoding: "utf-8",
126+
});
127+
if (_this.docset.beforeParse) {
128+
html = _this.docset.beforeParse({ path: itemPath, html: html });
129+
}
130+
let $ = cheerio.load(html);
131+
let params = {
132+
$,
133+
relativePath,
134+
addDashAnchor: _this.addDashAnchor.bind({ $ }),
135+
docset: _this.docset,
136+
};
137+
if (_this.docset.beforeGenerateToc) {
138+
_this.docset.beforeGenerateToc(params);
139+
}
140+
_this.docset.generateToc({
141+
insertToDb: _this.insertToDb,
142+
...params,
143+
});
144+
if (_this.docset.beforeFilter) {
145+
_this.docset.beforeFilter(params);
146+
}
147+
if (_this.docset.filter) {
148+
_this.docset.filter(params);
149+
}
150+
if (_this.docset.afterFilter) {
151+
_this.docset.afterFilter(params);
152+
}
153+
html = $.html();
154+
if (_this.docset.beforeWrite) {
155+
html = _this.docset.beforeWrite({ path: itemPath, html: html });
156+
}
157+
_this.writeFile({
158+
path: itemPath,
159+
content: html,
160+
});
161+
}
162+
}
163+
164+
insertToDb({ name, type, path }) {
165+
try {
166+
db.run(
167+
"INSERT INTO searchIndex (name, type, path) VALUES (?, ?, ?);",
168+
[name, type, path],
169+
function (res) {
170+
if (res.error) throw res.error;
171+
console.log(res);
172+
}
173+
);
174+
} catch (e) {
175+
console.log({ name, type, path });
176+
}
177+
}
178+
179+
addDashAnchor({ element, title, type, num }) {
180+
let titleStr = `//dash_ref_${title}/${type}/${encodeURIComponent(
181+
title
182+
)}/${num}`;
183+
let dashAnchor = `<a class="dashAnchor" name="${titleStr}"/>`;
184+
this.$(element).before(dashAnchor).html();
185+
}
186+
187+
writeFile({ path, content }) {
188+
fs.writeFileSync(path, content, "utf-8");
189+
console.info("文件已经成功生成.");
190+
}
191+
};

build.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const DocSet = require("./DocSet");
2+
const config = require("./config/" + process.argv[2]);
3+
4+
let docSet = new DocSet(config);
5+
docSet.build();

config/php.js

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
const types = require("../types");
2+
3+
const generateToc = function ({
4+
$,
5+
relativePath,
6+
addDashAnchor,
7+
insertToDb,
8+
docset,
9+
}) {
10+
let h1 = $("h1");
11+
let title = h1.text();
12+
if (
13+
title === "" ||
14+
(h1.prev().length > 0 && h1.prev()[0].tagName === "strong")
15+
) {
16+
title = $("h2").text();
17+
}
18+
let type = undefined;
19+
let classSyn = $(".classsynopsis");
20+
if (classSyn.length > 0) {
21+
if (!/|interface/g.test(title)) {
22+
title = title.replace(/|The|class|\([^)]*\)|[^]*/g, "");
23+
type = types.Class;
24+
} else {
25+
title = title.replace(/|The|interface|\([^)]*\)|[^]*/g, "");
26+
type = types.Interface;
27+
}
28+
} else if (title.indexOf("::") !== -1) {
29+
type = types.Method;
30+
} else if (relativePath.startsWith("function.")) {
31+
type = types.Function;
32+
} else if (
33+
relativePath.startsWith("control-structures.") &&
34+
relativePath !== "control-structures.intro.html"
35+
) {
36+
type = types.Keyword;
37+
} else if (
38+
relativePath.startsWith("language.types.") &&
39+
relativePath !== "language.types.html" &&
40+
relativePath !== "language.types.intro.html"
41+
) {
42+
type = types.Type;
43+
} else if (relativePath.startsWith("language.operators.")) {
44+
type = types.Operator;
45+
} else if (
46+
relativePath.startsWith("reserved.variables.") &&
47+
relativePath !== "reserved.variables.html"
48+
) {
49+
type = types.Variable;
50+
} else if (relativePath.startsWith("wrappers.")) {
51+
type = types.Protocol;
52+
} else if (
53+
relativePath.endsWith("constants.html") &&
54+
relativePath !== "internals2.pdo.constants.html"
55+
) {
56+
type = types.Constant;
57+
} else if (
58+
relativePath.startsWith("language.") ||
59+
relativePath.startsWith("install.") ||
60+
relativePath.startsWith("security.") ||
61+
relativePath.startsWith("features.") ||
62+
relativePath.startsWith("faq.")
63+
) {
64+
type = types.Guide;
65+
}
66+
if (type === undefined) {
67+
return;
68+
}
69+
title = title.trim();
70+
if (type === types.Class || type === types.Interface) {
71+
insertToDb({
72+
name: title,
73+
type: type,
74+
path: `${relativePath}`,
75+
});
76+
77+
$('[id$="props"] dt').each((index, element) => {
78+
let propName = `${title}::${$(element).text().trim()}`;
79+
addDashAnchor({
80+
element,
81+
title: element.attribs.id,
82+
type: types.Property,
83+
num: 0,
84+
});
85+
86+
insertToDb({
87+
name: propName,
88+
type: types.Property,
89+
path: `${relativePath}#${encodeURIComponent(element.attribs.id)}`,
90+
});
91+
});
92+
$('[id$="constants"] dt').each((index, element) => {
93+
if (!element.attribs.id) {
94+
return;
95+
}
96+
let constName = `${$(element).text().trim()}`;
97+
addDashAnchor({
98+
element,
99+
title: element.attribs.id,
100+
type: types.Constant,
101+
num: 0,
102+
});
103+
104+
insertToDb({
105+
name: constName,
106+
type: types.Constant,
107+
path: `${relativePath}#${encodeURIComponent(element.attribs.id)}`,
108+
});
109+
});
110+
} else if (type === types.Constant) {
111+
$("dt").each((index, element) => {
112+
if (!element.attribs.id) {
113+
return;
114+
}
115+
let constName = $(element).children("strong").text().trim();
116+
addDashAnchor({
117+
element,
118+
title: element.attribs.id,
119+
type: types.Constant,
120+
num: 0,
121+
});
122+
123+
insertToDb({
124+
name: constName,
125+
type: types.Constant,
126+
path: `${relativePath}#${encodeURIComponent(element.attribs.id)}`,
127+
});
128+
});
129+
} else {
130+
insertToDb({
131+
name: title,
132+
type: type,
133+
path: `${relativePath}`,
134+
});
135+
}
136+
};
137+
138+
const beforeFilter = function ({ $, relativePath, addDashAnchor, docset }) {
139+
$(".navbar").remove();
140+
};
141+
142+
const filter = function ({ $, relativePath, addDashAnchor, docset }) {};
143+
144+
const afterFilter = function ({ $, relativePath, addDashAnchor, docset }) {};
145+
146+
module.exports = {
147+
name: "php",
148+
displayName: "PHP",
149+
platformFamily: "PHP",
150+
entry: "index.html",
151+
domain: "",
152+
include: [],
153+
exclude: [],
154+
replace: {},
155+
generateToc,
156+
filter,
157+
beforeFilter,
158+
afterFilter,
159+
};

0 commit comments

Comments
 (0)