-
Notifications
You must be signed in to change notification settings - Fork 78
/
Copy pathindex.js
115 lines (102 loc) · 3.39 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
const create = data => {
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const pageData = {
id: data.questionFrontendId || data.questionId,
name: data.questionTitle,
difficulty: data.difficulty,
relatedTopics: data.topicTags.map(t => t.name).join(', '),
similarQuestions: JSON.parse(data.similarQuestions).map(q => q.title).join(', '),
description: getDescription(data.content),
};
const dir = getPath(pageData.id, pageData.name.replace(/\?/g, ''));
if (fs.existsSync(dir)) {
console.log(`${chalk.red('file already exists')}: ${chalk.blue(dir)}\n`);
return;
}
let str = fs.readFileSync(path.resolve(__dirname, './template.md'), 'utf-8');
Object.keys(pageData).forEach(name => {
str = str.replace(`{{${name}}}`, pageData[name]);
});
fse.outputFileSync(dir, str);
console.log(`created at: ${chalk.blue(dir)}\n`);
};
const getDescription = (description) => {
const cheerio = require('cheerio');
const rules = [
{
regexp: /<pre>([\s\S]*?)<\/pre>/ig,
replacer: (_, $1) => `\`\`\`\n${cheerio.load($1).text().replace(/\n$/, '')}\n\`\`\``
},
{
regexp: /<code>(.*?)<\/code>/ig,
replacer: (_, $1) => `\`${$1}\``
},
{
regexp: /<i>(.*?)<\/i>/ig,
replacer: (_, $1) => `*${$1}*`
},
{
regexp: /<b>(.*?)<\/b>/ig,
replacer: (_, $1) => `**${$1}**`
},
{
regexp: /<em>(.*?)<\/em>/ig,
replacer: (_, $1) => `**${$1}**`
},
{
regexp: /<img.*src="([^"]+)".*\/?>/ig,
replacer: (_, $1) => `\n\n`
},
{
regexp: /<strong>(.*?)<\/strong>/ig,
replacer: (_, $1) => `**${$1}**`
},
{
regexp: /<\/?ul>/ig,
replacer: '',
},
{
regexp: /<li>(.*?)<\/li>/ig,
replacer: (_, $1) => `\n- ${$1}`
}
];
let html = description;
rules.forEach(rule => {
html = html.replace(rule.regexp, rule.replacer);
});
return cheerio.load(html).text();
};
const getPath = (id, name) => {
const path = require('path');
const left = Math.floor((id - 1) / 100);
const folder = `${left === 0 ? '001' : (left * 100 + 1)}-${(left + 1) * 100}`;
return path.resolve(__dirname, `../${folder}/${id}. ${name}.md`);
};
const getName = url => {
if (!url) throw new Error('need leetcode problem url');
const res = /https:\/\/leetcode.com\/problems\/([^/]+)/.exec(url);
if (!res) throw new Error('leetcode problem url not valid');
return res[1];
}
const queryAndCreate = name => {
const axios = require('axios');
const url = `https://leetcode.com/graphql?query=query%20getQuestionDetail($titleSlug:%20String!)%20%7B%0A%20%20question(titleSlug:%20$titleSlug)%20%7B%0A%20%20%20%20questionId%0A%20%20%20%20questionFrontendId%0A%20%20%20%20questionTitle%0A%20%20%20%20content%0A%20%20%20%20difficulty%0A%20%20%20%20stats%0A%20%20%20%20similarQuestions%0A%20%20%20%20topicTags%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A&operationName=getQuestionDetail&variables=%7B%22titleSlug%22:%22${name}%22%7D`;
axios.get(url).then(res => {
if (!res.data?.data?.question) {
console.error('fetch question info error, probably wrong problem url\n');
return;
}
create(res.data.data.question);
}).catch(err => {
console.error(err);
});
}
if (require.main === module) {
queryAndCreate(getName(process.argv[2]));
}
module.exports = {
queryAndCreate,
};