-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
154 lines (147 loc) · 5.04 KB
/
index.js
File metadata and controls
154 lines (147 loc) · 5.04 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Script that take a JSON list of OpenSearch and generate :
// - XML files
// - an HTML file that references all the OpenSearch
const fs = require("fs");
let args = process.argv.slice(2);
// Poor's man arg parser
let appArgs = {};
for (const key in args) {
if (["--file", "-f", "--image", "-i", "--help", "-h"].includes(args[key])) {
let option = "";
switch (args[key]) {
case "--file":
case "-f":
option = "file";
break;
case "--image":
case "-i":
option = "image";
break;
case "--help":
case "-h":
console.log(`Usage:\n`);
console.log(` $ node index.js -f data.json --image data\n`);
console.log(`--help | -h\n\t prints this help`);
console.log(
`--file | -f\n\t specify another data file (default to list.json)`
);
console.log(
`--image | -i ["data"|url]\n\t define if image use data URLs (embeded) or are linked (default data URLs)`
);
process.exit(1);
break;
default:
break;
}
appArgs[option] = args[parseInt(key) + 1];
}
}
// console.debug(appArgs);
let dataFile = appArgs.file;
if (!fs.existsSync(dataFile)) {
dataFile = "list.json";
}
const data = JSON.parse(
fs.readFileSync(dataFile, { encoding: "utf8", flag: "r" })
);
if (!fs.existsSync("opensearch")) {
fs.mkdirSync("opensearch");
}
let HTMLTemplate = fs.readFileSync("index-template.html", {
encoding: "utf8",
flag: "r",
});
let updatedTemplate = "";
let opensearch_data = "\n";
let opensearch_info = "\n <ul>\n";
let iterations = data.length;
for (const element of data) {
let opensearchDir = "opensearch/";
let opensearchFile = element.shortName.replace(/[^A-Z0-9]+/gi, "-");
let opensearchPath = opensearchDir + opensearchFile + ".xml";
try {
fs.writeFileSync(opensearchPath, generateOpenSearchXML(element));
console.log(`${opensearchPath} file has been saved.`);
} catch (err) {
console.error(err);
}
opensearch_data += ` <link rel="search" type="application/opensearchdescription+xml" href="${opensearchPath}" title="${element.shortName}">\n`;
updatedTemplate = HTMLTemplate.replace(
/{{ OPENSEARCH_DATA }}/g,
opensearch_data
);
if (appArgs.image !== undefined && appArgs.image.startsWith("http")) {
opensearch_info += ` <li><a href="${element.searchURL}" target="_blank"><img src="${appArgs.image}${element.image["16"]}" /></a> <b>${element.shortName}</b> (${element.description})</li>\n`;
} else {
opensearch_info += ` <li><a href="${
element.searchURL
}" target="_blank"><img src="${generateDataImage(
element.image["16"]
)}" /></a> <b>${element.shortName}</b> (${element.description})</li>\n`;
}
if (!--iterations) {
opensearch_info += ` </ul>`;
}
updatedTemplate = updatedTemplate.replace(
/{{ OPENSEARCH_INFO }}/g,
opensearch_info
);
}
fs.writeFile("index.html", updatedTemplate, "utf8", function (err) {
if (err) return console.log(err);
});
function generateOpenSearchXML(data) {
let date = new Date();
//let url = new URL(data.searchQueryURL);
//console.debug(url.pathname);
let images = "";
let iterations = data.image.length;
for (const img in data.image) {
const file_ext = data.image[img].split(".").pop();
const file_type_str = (file_ext === "png") ? `type="image/png"` : ((file_ext === "ico") ? `type="image/x-icon"` : '');
if (appArgs.image !== undefined && appArgs.image.startsWith("http")) {
images += ` <Image height="${img}" width="${img}" ${file_type_str}>${appArgs.image}${data.image[img]}</Image>`;
} else {
images += ` <Image height="${img}" width="${img}" ${file_type_str}>${generateDataImage(
data.image[img]
)}</Image>`;
}
if (!--iterations) {
images += `\n`;
}
}
return `<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<!-- Last generated on ${date.toISOString()} -->
<ShortName>${data.shortName}</ShortName>
<Description>${data.shortName}</Description>
<InputEncoding>UTF-8</InputEncoding>
${images}
<Url type="text/html" method="get" template="${data.searchQueryURL}"/>
<moz:SearchForm>${data.searchURL}</moz:SearchForm>
<Contact>${data.contact}</Contact>
<Developer>${data.contact}</Developer>
</OpenSearchDescription>`;
}
function generateDataImage(img) {
/* When possible, search engines should offer a 16x16 image of type "image/x-icon" or "image/vnd.microsoft.icon" (the Microsoft ICO format) and a 64x64 image of type "image/jpeg" or "image/png". */
const contents = fs.readFileSync(img);
const b64 = contents.toString("base64");
const file_ext = img.split(".").pop();
let mime = "";
switch (file_ext) {
case "png":
mime = "image/png";
break;
case "ico":
mime = "image/x-icon";
break;
case "svg":
mime = "image/svg";
break;
default:
mime = "image/unknown";
}
return `data:${mime};base64,${b64}`;
}