wikity 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/index.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/cli.js');
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -1,47 +1,58 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const index_1 = __importDefault(require("./index"));
8
- const common_1 = require("./common");
9
- const indent = (n) => ' '.repeat(n * 4);
10
- const usage = (command, ...desc) => {
11
- console.log('\n' + indent(2) + command);
12
- desc.forEach((msg) => console.log(indent(2.5) + msg));
13
- };
14
- const arg = (n) => process.argv[n + 1] || '';
15
- const args = process.argv.slice(1);
16
- if (!arg(1)) {
17
- console.log('Type `wikity help` for a list of commands.');
18
- }
19
- else if (arg(1).includes('h')) {
20
- console.log(`\n${indent(1)}Wikity CLI commands:`);
21
- usage(`wikity (help|-h)`, `Display this help message.`);
22
- usage(`wikity compile [<folder>] [-o <folder>] [-t <folder>] -i <folder>] [-e] [-d]`, `Compile wikitext files from a given folder.`, ` [<folder>]\n${indent(3.5)}Input folder ('.' (current folder) if unset).`, ` (-o|--outputFolder) <folder>\n${indent(3.5)}Folder that compiled HTML files are placed in ('wikity-out' if unset).`, ` (-t|--templatesFolder) <folder>\n${indent(3.5)}Where to place wiki templates ('templates' if unset).`, ` (-i|--imagesFolder) <folder>\n${indent(3.5)}Where to place wiki images ('images' if unset).`, ` (-e|--eleventy)\n${indent(3.5)}Compiles files with Eleventy front matter (false if unset).`, ` (-d|--defaultStyles)\n${indent(3.5)}Add default wiki styling to all pages (true if unset).`);
23
- usage(`wikity (parse|-p) "<input>"`, `Parse raw wikitext from the command line.`);
24
- usage(`wikity (version|-v)`, `Display the current version of Wikity.`);
25
- }
26
- else if (arg(1).includes('c')) {
27
- const configArgs = args.slice(2);
28
- const argsList = configArgs.join(' ');
29
- const getArgContent = (arg) => arg.test(argsList) && configArgs.filter((_, i) => arg.test(configArgs[i - 1])).join(' ') || '';
30
- const folder = arg(2) || '.';
31
- const outputFolder = getArgContent(/^-+o/);
32
- const templatesFolder = getArgContent(/^-+t/);
33
- const imagesFolder = getArgContent(/^-+i/);
34
- const eleventy = /^-+e/.test(argsList);
35
- const defaultStyles = /^-+d/.test(argsList);
36
- index_1.default.compile(folder, { outputFolder, templatesFolder, imagesFolder, eleventy, defaultStyles });
37
- }
38
- else if (arg(1).includes('p')) {
39
- const input = arg(2);
40
- console.log(index_1.default.parse(input));
41
- }
42
- else if (arg(1).includes('v')) {
43
- console.log('The current version of Wikity is ' + common_1.VERSION);
44
- }
45
- else {
46
- console.log('Unknown command; type `wikity help` for help');
47
- }
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const VERSION = require('../package.json').version;
7
+ const index_1 = __importDefault(require("./index"));
8
+ // Helper functions
9
+ const indent = (n) => ' '.repeat(n * 4);
10
+ const usage = (command, ...desc) => {
11
+ console.log('\n' + indent(2) + command);
12
+ desc.forEach((msg) => console.log(indent(2.5) + msg));
13
+ };
14
+ const arg = (n) => process.argv[n + 1] || '';
15
+ const args = process.argv.slice(1);
16
+ // Run CLI
17
+ if (!arg(1)) {
18
+ // No arguments
19
+ console.log('Type `wikity help` for a list of commands.');
20
+ }
21
+ else if (arg(1).includes('h')) {
22
+ // Show help message
23
+ console.log(`\n${indent(1)}Wikity CLI commands:`);
24
+ usage(`wikity (help|-h)`, `Display this help message.`);
25
+ usage(`wikity compile [<folder>] [-o <folder>] [-t <folder>] -i <folder>] [-e] [-d]`, `Compile wikitext files from a given folder.`, ` [<folder>]\n${indent(3.5)}Input folder ('.' (current folder) if unset).`, ` (-o|--outputFolder) <folder>\n${indent(3.5)}Folder that compiled HTML files are placed in ('wikity-out' if unset).`, ` (-t|--templatesFolder) <folder>\n${indent(3.5)}Where to place wiki templates ('templates' if unset).`, ` (-i|--imagesFolder) <folder>\n${indent(3.5)}Where to place wiki images ('images' if unset).`, ` (-e|--eleventy)\n${indent(3.5)}Compiles files with Eleventy front matter (false if unset).`, ` (-d|--defaultStyles)\n${indent(3.5)}Add default wiki styling to all pages (true if unset).`);
26
+ usage(`wikity (parse|-p) "<input>"`, `Parse raw wikitext from the command line.`);
27
+ usage(`wikity (version|-v)`, `Display the current version of Wikity.`);
28
+ }
29
+ else if (arg(1).includes('c')) {
30
+ // Run compilation
31
+ const configArgs = args.slice(2);
32
+ const argsList = configArgs.join(' ');
33
+ // retrieve item from arguments list
34
+ const getArgContent = (arg) => arg.test(argsList) && configArgs.filter((_, i) => arg.test(configArgs[i - 1])).join(' ') || undefined;
35
+ // Fetch user-supplied arguments
36
+ const folder = arg(2) || '.';
37
+ const outputFolder = getArgContent(/^-+o/);
38
+ const templatesFolder = getArgContent(/^-+t/);
39
+ const imagesFolder = getArgContent(/^-+i/);
40
+ const eleventy = /^-+e/.test(argsList);
41
+ const defaultStyles = /^-+d/.test(argsList);
42
+ index_1.default.compile(folder, { outputFolder, templatesFolder, imagesFolder, eleventy, defaultStyles });
43
+ }
44
+ else if (arg(1).includes('p')) {
45
+ // Run parsing
46
+ // second argument is inputted text
47
+ const input = arg(2);
48
+ const output = index_1.default.parse(input);
49
+ console.log(output);
50
+ }
51
+ else if (arg(1).includes('v')) {
52
+ // Show version
53
+ console.log('The current version of Wikity is ' + VERSION);
54
+ }
55
+ else {
56
+ // Unknown command
57
+ console.log('Unknown command; type `wikity help` for help');
58
+ }
@@ -0,0 +1,20 @@
1
+ export type Metadata = Record<string, any>;
2
+ export interface Config {
3
+ /** The folder that Wikity's compiled HTML files are outputted to (defaults to 'wikity-out') */
4
+ outputFolder?: string;
5
+ /** The folder that wiki templates are to be stored in relative to the root folder */
6
+ templatesFolder?: string;
7
+ /** The folder that images are to be stored in relative to the root folder */
8
+ imagesFolder?: string;
9
+ /** Whether to be set up for Eleventy integration (defaults to false) */
10
+ eleventy?: boolean;
11
+ /** Whether to use default wiki styling (defaults to true) */
12
+ defaultStyles?: boolean;
13
+ /** Custom CSS styles to add to the wiki pages */
14
+ customStyles?: string;
15
+ }
16
+ export interface Result {
17
+ data: string;
18
+ metadata: Metadata;
19
+ }
20
+ export declare function RegExpBuilder(regex: string, flag?: string): RegExp;
package/dist/common.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RegExpBuilder = void 0;
4
+ function RegExpBuilder(regex, flag = 'mgi') {
5
+ return RegExp(regex.replace(/ /g, '').replace(/\|\|.+?\|\|/g, ''), flag);
6
+ }
7
+ exports.RegExpBuilder = RegExpBuilder;
@@ -1,3 +1,3 @@
1
- import { Config } from './common';
2
- export declare function eleventyCompile(dir?: string, config?: Config): void;
3
- export declare function compile(dir?: string, config?: Config): void;
1
+ import { Config } from './common';
2
+ export declare function eleventyCompile(dir?: string, config?: Config): void;
3
+ export declare function compile(dir?: string, config?: Config): void;
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.compile = exports.eleventyCompile = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const glob_1 = __importDefault(require("glob"));
10
+ const dedent_1 = __importDefault(require("dedent"));
11
+ const formatter = require('html-formatter'); // does not have type package
12
+ const parse_1 = require("./parse");
13
+ const wiki_css_1 = __importDefault(require("./wiki.css"));
14
+ function eleventyCompile(dir = '.', config = {}) {
15
+ compile(dir, { eleventy: true, ...config });
16
+ }
17
+ exports.eleventyCompile = eleventyCompile;
18
+ function compile(dir = '.', config = {}) {
19
+ var _a, _b, _c;
20
+ // set defaults
21
+ (_a = config.templatesFolder) !== null && _a !== void 0 ? _a : (config.templatesFolder = 'templates');
22
+ (_b = config.imagesFolder) !== null && _b !== void 0 ? _b : (config.imagesFolder = 'images');
23
+ (_c = config.outputFolder) !== null && _c !== void 0 ? _c : (config.outputFolder = 'wikity-out');
24
+ // directory variables (absolute paths)
25
+ const baseDir = path_1.default.resolve(dir);
26
+ const templatesFolder = path_1.default.join(baseDir, config.templatesFolder);
27
+ const imagesFolder = path_1.default.join(baseDir, config.imagesFolder);
28
+ const outputFolder = path_1.default.join(baseDir, config.outputFolder);
29
+ const outputImagesFolder = path_1.default.join(baseDir, config.outputFolder, config.imagesFolder);
30
+ const newConfig = { ...config, templatesFolder, imagesFolder, outputFolder };
31
+ let stylesCreated = false;
32
+ // Write wikitext files
33
+ const files = glob_1.default.sync(dir + "/**/*.wiki", {});
34
+ files.forEach((file) => {
35
+ var _a;
36
+ const fileData = fs_1.default.readFileSync(file, { encoding: 'utf8' });
37
+ const { data: parsedContent, metadata } = (0, parse_1.parse)(fileData, newConfig);
38
+ let outText = parsedContent;
39
+ const filename = file.replace(dir, '').replace(/^[\/\\]/, '');
40
+ const outFilename = filename.replace(/ /g, '_').replace('.wiki', '.html');
41
+ const outFilePath = path_1.default.join(outputFolder, outFilename);
42
+ const urlPath = outFilename.replace(/(?<=^|\/)\w/g, m => m.toUpperCase()); // capitalise first letters
43
+ const displayTitle = metadata.displayTitle || urlPath.replace('.html', '');
44
+ // Eleventy configuration
45
+ const frontMatter = config.eleventy ? (0, dedent_1.default) `
46
+ ---
47
+ permalink: /wiki/${urlPath}
48
+ ---
49
+ ` : '';
50
+ // Create TOC
51
+ if (!metadata.notoc && (metadata.toc || (((_a = outText.match(/<h\d[^>]*>/g)) === null || _a === void 0 ? void 0 : _a.length) || 0) > 3)) {
52
+ let toc = '';
53
+ let headings = Array.from(parsedContent.match(/<h\d[^>]*>.+?<\/h\d>/gs) || []);
54
+ headings.forEach(match => {
55
+ var _a;
56
+ const text = match.replace(/\s*<\/?h\d[^>]*>\s*/g, '');
57
+ const lvl = +(((_a = match.match(/\d/g)) === null || _a === void 0 ? void 0 : _a[0]) || -1);
58
+ toc += `${`<ol>`.repeat(lvl - 1)} <li> <a href="#${encodeURI(text.replace(/ /g, '_'))}">${text}</a> </li> ${`</ol>`.repeat(lvl - 1)}`;
59
+ });
60
+ const tocElem = (0, dedent_1.default) `
61
+ <div id="toc">
62
+ <span id="toc-heading">
63
+ <strong>Contents</strong>
64
+ [<a href="javascript:void(0)" onclick="
65
+ document.querySelector('#toc ol').setAttribute('style', this.innerText === 'hide' ? 'display: none;' : '');
66
+ this.innerText = this.innerText === 'hide' ? 'show' : 'hide';
67
+ ">hide</a>]
68
+ </span>
69
+ <ol>${toc}</ol>
70
+ </div>
71
+ `;
72
+ // Set TOC on page
73
+ if (outText.includes('<toc></toc>'))
74
+ outText = outText.replace('<toc></toc>', tocElem);
75
+ else
76
+ outText = outText.replace(/<h\d[^>]*>/, tocElem + '$&');
77
+ }
78
+ // Create plaintext of HTML for use as description/metadata property.
79
+ const plaintextData = parsedContent.replace(/<.+?>/gs, ' ');
80
+ // Create HTML
81
+ const folderUpCount = file.split(/[\/\\]/).length - dir.split(/[\/\\]/).length; // number of folders to go up by to get to root
82
+ const html = (0, dedent_1.default) `
83
+ <html>
84
+ <head>
85
+ <meta charset="utf-8">
86
+ <meta name="viewport" content="initial-scale=1.0, width=device-width">
87
+ <meta name="description" content="${plaintextData.substring(0, 256)}...">
88
+ <title>${displayTitle}</title>
89
+ <link id="default-styles" rel="stylesheet" href="${'../'.repeat(folderUpCount)}./wiki.css">
90
+ </head>
91
+ <body>
92
+ <header>
93
+ <h1 id="page-title">${displayTitle}</h1>
94
+ </header>
95
+ <main>
96
+ <p>\n${outText}
97
+ </p>
98
+ </main>
99
+ <footer>
100
+ <p id="credit_wikity">Created using <a href="https://github.com/Nixinova/Wikity">Wikity</a></p>
101
+ </footer>
102
+ </body>
103
+ </html>
104
+ `;
105
+ // Write to file
106
+ if (!fs_1.default.existsSync(path_1.default.dirname(outFilePath))) {
107
+ fs_1.default.mkdirSync(path_1.default.dirname(outFilePath));
108
+ }
109
+ const renderedHtml = formatter.render(html).replace(/(<\/\w+>)(\S)/g, '$1 $2');
110
+ fs_1.default.writeFileSync(outFilePath, frontMatter + '\n' + renderedHtml, 'utf8');
111
+ // Move images
112
+ (0, glob_1.default)(imagesFolder + '/*', {}, (err, files) => {
113
+ if (err) {
114
+ console.warn(err);
115
+ }
116
+ if (!fs_1.default.existsSync(outputImagesFolder)) {
117
+ fs_1.default.mkdirSync(outputImagesFolder);
118
+ }
119
+ for (const file of files) {
120
+ fs_1.default.copyFileSync(file, path_1.default.join(outputImagesFolder, path_1.default.basename(file)));
121
+ }
122
+ ;
123
+ });
124
+ // Create site styles
125
+ if (!stylesCreated) {
126
+ stylesCreated = true;
127
+ let styles = '';
128
+ if (config.defaultStyles !== false) {
129
+ styles += wiki_css_1.default;
130
+ }
131
+ if (config.customStyles) {
132
+ styles += config.customStyles;
133
+ }
134
+ const cssOutput = config.eleventy ? (0, dedent_1.default) `
135
+ ---
136
+ permalink: /wiki.css
137
+ ---
138
+ ${styles}
139
+ ` : styles;
140
+ const cssOutFilename = config.eleventy ? 'wiki.css.njk' : 'wiki.css';
141
+ fs_1.default.writeFileSync(path_1.default.join(outputFolder, cssOutFilename), cssOutput);
142
+ }
143
+ });
144
+ }
145
+ exports.compile = compile;
@@ -1,8 +1,11 @@
1
- import { compile, eleventyCompile } from './compile';
2
- import { rawParse } from './parse';
3
- declare const _default: {
4
- parse: typeof rawParse;
5
- compile: typeof compile;
6
- eleventyPlugin: typeof eleventyCompile;
7
- };
8
- export = _default;
1
+ import { compile, eleventyCompile } from './compile';
2
+ import { rawParse } from './parse';
3
+ declare const _default: {
4
+ /** Parse wikitext from a string */
5
+ parse: typeof rawParse;
6
+ /** Compile a folder of wikitext files */
7
+ compile: typeof compile;
8
+ /** Compile a folder of wikitext files for output in Eleventy @deprecated */
9
+ eleventyPlugin: typeof eleventyCompile;
10
+ };
11
+ export = _default;
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ const compile_1 = require("./compile");
3
+ const parse_1 = require("./parse");
4
+ module.exports = {
5
+ /** Parse wikitext from a string */
6
+ parse: parse_1.rawParse,
7
+ /** Compile a folder of wikitext files */
8
+ compile: compile_1.compile,
9
+ /** Compile a folder of wikitext files for output in Eleventy @deprecated */
10
+ eleventyPlugin: compile_1.eleventyCompile,
11
+ };
@@ -1,3 +1,3 @@
1
- import { Config, Result } from './common';
2
- export declare function rawParse(data: string, config?: Config): string;
3
- export declare function parse(data: string, config?: Config): Result;
1
+ import { Config, Result } from './common';
2
+ export declare function rawParse(data: string, config?: Config): string;
3
+ export declare function parse(data: string, config?: Config): Result;
package/dist/parse.js ADDED
@@ -0,0 +1,271 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parse = exports.rawParse = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const escape_html_1 = __importDefault(require("escape-html"));
10
+ const dateformat_1 = __importDefault(require("dateformat"));
11
+ const common_1 = require("./common");
12
+ const r = String.raw;
13
+ const MAX_RECURSION = 20;
14
+ const arg = r `\s*([^|}]+?)\s*`;
15
+ function fullyEscape(text) {
16
+ return (0, escape_html_1.default)(text)
17
+ .replace(/{/g, '&#123;'); // avoid keeping plain {{}} which is parsed as a template call
18
+ }
19
+ function rawParse(data, config = {}) {
20
+ return parse(data, config).data;
21
+ }
22
+ exports.rawParse = rawParse;
23
+ function parse(data, config = {}) {
24
+ var _a, _b, _c;
25
+ const templatesFolder = (_a = config.templatesFolder) !== null && _a !== void 0 ? _a : 'templates';
26
+ const imagesFolder = (_b = config.imagesFolder) !== null && _b !== void 0 ? _b : 'images';
27
+ const outputFolder = (_c = config.outputFolder) !== null && _c !== void 0 ? _c : 'wikity-out';
28
+ const vars = {};
29
+ const metadata = {};
30
+ const nowikis = [];
31
+ const refs = [];
32
+ let nowikiCount = 0;
33
+ let rawExtLinkCount = 0;
34
+ let refCount = 0;
35
+ let outText = data;
36
+ for (let l = 0, last = ''; l < MAX_RECURSION; l++) {
37
+ if (last === outText)
38
+ break;
39
+ last = outText;
40
+ outText = outText
41
+ // Nowiki: <nowiki></nowiki>
42
+ .replace((0, common_1.RegExpBuilder)(r `<nowiki> ([^]+?) </nowiki>`), (_, m) => `%NOWIKI#${nowikis.push(m), nowikiCount++}%`)
43
+ // Sanitise unacceptable HTML
44
+ .replace((0, common_1.RegExpBuilder)(r `<(/?) \s* (?= script|link|meta|iframe|frameset|object|embed|applet|form|input|button|textarea )`), '&lt;$1')
45
+ .replace((0, common_1.RegExpBuilder)(r `(?<= <[^>]+ ) (\bon(\w+))`), 'data-$2')
46
+ // Comments: <!-- -->
47
+ .replace(/<!--[^]+?-->/g, '')
48
+ // Lines: ----
49
+ .replace(/^-{4,}/gm, '<hr>')
50
+ // Metadata: displayTitle, __NOTOC__, etc
51
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* displayTitle: ([^}]+) }}`), (_, title) => (metadata.displayTitle = title, ''))
52
+ .replace((0, common_1.RegExpBuilder)(r `__NOINDEX__`), () => (metadata.noindex = true, ''))
53
+ .replace((0, common_1.RegExpBuilder)(r `__NOTOC__`), () => (metadata.notoc = true, ''))
54
+ .replace((0, common_1.RegExpBuilder)(r `__FORCETOC__`), () => (metadata.toc = true, ''))
55
+ .replace((0, common_1.RegExpBuilder)(r `__TOC__`), () => (metadata.toc = true, `<toc></toc>`))
56
+ // Magic words: {{!}}, {{reflist}}, etc
57
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* ! \s* }}`), '&vert;')
58
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* = \s* }}`), '&equals;')
59
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* [Rr]eflist \s* }}`), '<references/>')
60
+ // String functions: {{lc:}}, {{ucfirst:}}, {{len:}}, etc
61
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? urlencode: ${arg} }}`), (_, m) => encodeURI(m))
62
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? urldecode: ${arg} }}`), (_, m) => decodeURI(m))
63
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? lc: ${arg} }}`), (_, m) => m.toLowerCase())
64
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? uc: ${arg} }}`), (_, m) => m.toUpperCase())
65
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? lcfirst: ${arg} }}`), (_, m) => m[0].toLowerCase() + m.substr(1))
66
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? ucfirst: ${arg} }}`), (_, m) => m[0].toUpperCase() + m.substr(1))
67
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? len: ${arg} }}`), (_, m) => m.length)
68
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? pos: ${arg} \|${arg} (?: \s*\|${arg} )? }}`), (_, find, str, n = 0) => find.substr(n).indexOf(str))
69
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? sub: ${arg} \|${arg} (?:\|${arg})? }}`), (_, str, from, len) => str.substr(+from - 1, +len))
70
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? padleft: ${arg} \|${arg} \|${arg} }}`), (_, str, n, char) => str.padStart(+n, char))
71
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? padright: ${arg} \|${arg} \|${arg} }}`), (_, str, n, char) => str.padEnd(+n, char))
72
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? replace: ${arg} \|${arg} \|${arg} }}`), (_, str, find, rep) => str.split(find).join(rep))
73
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* #? explode: ${arg} \|${arg} \|${arg} }}`), (_, str, delim, pos) => str.split(delim)[+pos])
74
+ // Parser functions: {{#if:}}, {{#switch:}}, etc
75
+ .replace((0, common_1.RegExpBuilder)(r `{{ \s* (#\w+) \s* : \s* ( [^{}]+ ) \s* }} ( ?!} )`), (_, name, content) => {
76
+ if (/{{\s*#/.test(content))
77
+ return _;
78
+ const args = content.trim().split(/\s*\|\s*/);
79
+ switch (name) {
80
+ case '#if':
81
+ return (args[0] ? args[1] : args[2]) || '';
82
+ case '#ifeq':
83
+ return (args[0] === args[1] ? args[2] : args[3]) || '';
84
+ case '#vardefine':
85
+ vars[args[0]] = args[1] || '';
86
+ return '';
87
+ case '#var':
88
+ if ((0, common_1.RegExpBuilder)(r `{{ \s* #vardefine \s* : \s* ${args[0]}`).test(outText))
89
+ return _; // wait until var is set
90
+ return vars[args[0]] || args[1] || '';
91
+ case '#switch':
92
+ return args.slice(1)
93
+ .map(arg => arg.split(/\s*=\s*/))
94
+ .filter(duo => args[0] === duo[0].replace('#default', args[0]))[0][1];
95
+ case '#time':
96
+ case '#date':
97
+ case '#datetime':
98
+ // make sure the characters are not inside a string
99
+ let parsedMatch = args[0].replace(/".+?"/g, '').replace(/'.+?'/g, '');
100
+ if (/[abcefgijkqruvx]/i.test(parsedMatch)) {
101
+ const errMsg = `Wikity does not use Wikipedia's #time function syntax. Use repetition-based formatting (e.g. yyyy-mm-dd) instead.`;
102
+ console.warn(`<Wikity> [WARN] ${errMsg}`);
103
+ }
104
+ return (0, dateformat_1.default)(args[1] ? new Date(args[1]) : new Date(), args[0]);
105
+ }
106
+ })
107
+ // Templates: {{template}}
108
+ .replace((0, common_1.RegExpBuilder)(r `(?<!{) {{ \s* ([^#{}|]+?) (\|[^{}]+)? }} (?!})`), (_, title, params = '') => {
109
+ const page = path_1.default.join(templatesFolder, title.trim().replace(/ /g, '_'));
110
+ let content = '';
111
+ // Try retrieve template content
112
+ try {
113
+ content = fs_1.default.readFileSync(page + '.wiki', { encoding: 'utf8' });
114
+ }
115
+ catch {
116
+ // Return redlink if template doesn't exist
117
+ const relPage = path_1.default.basename(templatesFolder) + '/' + path_1.default.relative(templatesFolder, page);
118
+ return `<a class="internal-link redlink" title="${title}" href="${relPage}">${title}</a>`;
119
+ }
120
+ // Remove non-template sections
121
+ content = content
122
+ .replace(/<noinclude>.*?<\/noinclude>/gs, '')
123
+ .replace(/.*<(includeonly|onlyinclude)>|<\/(includeonly|onlyinclude)>.*/gs, '');
124
+ // Substitute arguments
125
+ const argMatch = (arg) => (0, common_1.RegExpBuilder)(r `{{{ \s* ${arg} (?:\|([^}]*))? \s* }}}`);
126
+ const args = params.split('|');
127
+ // provided key=value template arguments
128
+ for (let i = 1; i < args.length; i++) {
129
+ const parts = args[i].split('=');
130
+ const [arg, val] = parts[1]
131
+ ? [parts[0], ...parts.slice(1)]
132
+ : [i.toString(), parts[0]];
133
+ content = content.replace(argMatch(arg), (_, defaultVal) => val || defaultVal || '');
134
+ }
135
+ return content;
136
+ })
137
+ // Unparsed arguments
138
+ .replace((0, common_1.RegExpBuilder)(r `{{{ \s* [^{}|]+? (?:\|([^}]*))? \s* }}}`), (_, _name, defaultVal) => {
139
+ return defaultVal !== null && defaultVal !== void 0 ? defaultVal : '';
140
+ })
141
+ // Images: [[File:Image.png|options|caption]]
142
+ .replace((0, common_1.RegExpBuilder)(r `\[\[ (?:File|Image): (.+?) (\|.+?)? \]\]`), (_, file, params = '') => {
143
+ if (/{{/.test(params))
144
+ return _;
145
+ const path = path_1.default.join(imagesFolder, file.trim().replace(/ /g, '_'));
146
+ let caption = '';
147
+ let imageData = {};
148
+ let imageArgs = params.split('|').map((arg) => arg.replace(/"/g, '&quot;'));
149
+ for (const param of imageArgs) {
150
+ if (['left', 'right', 'center', 'none'].includes(param)) {
151
+ imageData.float = param;
152
+ }
153
+ if (['baseline', 'sub', 'super', 'top', 'text-bottom', 'middle', 'bottom', 'text-bottom'].includes(param)) {
154
+ imageData.align = param;
155
+ }
156
+ else if (['border', 'frameless', 'frame', 'framed', 'thumb', 'thumbnail'].includes(param)) {
157
+ imageData.type = { framed: 'frame', thumbnail: 'thumb' }[param] || param;
158
+ if (imageData.type === 'thumb') {
159
+ imageData.hasCaption = true;
160
+ }
161
+ }
162
+ else if (param.endsWith('px')) {
163
+ param.replace(/(?:(\w+)?(x))?(\w+)px/, (_, size1, auto, size2) => {
164
+ if (size1) {
165
+ Object.assign(imageData, { width: size1, height: size2 });
166
+ }
167
+ else if (auto) {
168
+ Object.assign(imageData, { width: 'auto', height: size2 });
169
+ }
170
+ else {
171
+ Object.assign(imageData, { width: size2, height: 'auto' });
172
+ }
173
+ return '';
174
+ });
175
+ }
176
+ else if (param.startsWith('upright=')) {
177
+ imageData.width = +param.replace('upright=', '') * 300;
178
+ }
179
+ else if (param.startsWith('link=')) {
180
+ imageData.link = param.replace('link=', '');
181
+ }
182
+ else if (param.startsWith('alt=')) {
183
+ imageData.alt = param.replace('alt=', '');
184
+ }
185
+ else if (param.startsWith('style=')) {
186
+ imageData.style = param.replace('style=', '');
187
+ }
188
+ else if (param.startsWith('class=')) {
189
+ imageData.class = param.replace('class=', '');
190
+ }
191
+ else {
192
+ caption = param;
193
+ }
194
+ }
195
+ let content = `
196
+ <figure
197
+ class="
198
+ ${imageData.class || ''}
199
+ image-container
200
+ image-${imageData.type || 'default'}
201
+ "
202
+ style="
203
+ float: ${imageData.float || 'none'};
204
+ vertical-align: ${imageData.align || 'unset'};
205
+ ${imageData.style || ''}
206
+ "
207
+ >
208
+ <img
209
+ src="${path_1.default.basename(imagesFolder)}/${path_1.default.relative(imagesFolder, path)}"
210
+ alt="${imageData.alt || file}"
211
+ width="${imageData.width || 300}"
212
+ height="${imageData.height || 300}"
213
+ >
214
+ ${imageData.hasCaption ? `<figcaption>${caption}</figcaption>` : ''}
215
+ </figure>
216
+ `;
217
+ if (imageData.link) {
218
+ content = `<a href="/${imageData.link}" title="${imageData.link}">${content}</a>`;
219
+ }
220
+ return content;
221
+ })
222
+ // Markup: '''bold''' and '''italic'''
223
+ .replace((0, common_1.RegExpBuilder)(r `''' ([^']+?) '''`), '<b>$1</b>')
224
+ .replace((0, common_1.RegExpBuilder)(r `'' ([^']+?) ''`), '<i>$1</i>')
225
+ // Headings: ==heading==
226
+ .replace((0, common_1.RegExpBuilder)(r `^ (=+) \s* (.+?) \s* \1 \s* $`), (_, lvl, txt) => `<h${lvl.length} id="${encodeURI(txt.replace(/ /g, '_'))}">${txt}</h${lvl.length}>`)
227
+ // Internal links: [[Page]] and [[Page|Text]]
228
+ .replace((0, common_1.RegExpBuilder)(r `\[\[ ([^\]|]+?) \]\]`), `<a class="internal-link" title="$1" href="$1">$1</a>`)
229
+ .replace((0, common_1.RegExpBuilder)(r `\[\[ ([^\]|]+?) \| ([^\]]+?) \]\]`), `<a class="internal-link" title="$1" href="/$1">$2</a>`)
230
+ .replace((0, common_1.RegExpBuilder)(r `(</a>)([a-z]+)`), '$2$1')
231
+ // External links: [href Page] and just [href]
232
+ .replace((0, common_1.RegExpBuilder)(r `\[ ((?:\w+:)?\/\/ [^\s\]]+) (\s [^\]]+?)? \]`), (_, href, txt) => `<a class="external-link" href="${href}">${txt || '[' + (++rawExtLinkCount) + ']'}</a>`)
233
+ // Bulleted list: *item
234
+ .replace((0, common_1.RegExpBuilder)(r `^ (\*+) (.+?) $`), (_, lvl, txt) => `${'<ul>'.repeat(lvl.length)}<li>${txt}</li>${'</ul>'.repeat(lvl.length)}`)
235
+ .replace((0, common_1.RegExpBuilder)(r `</ul> (\s*?) <ul>`), '$1')
236
+ // Numbered list: #item
237
+ .replace((0, common_1.RegExpBuilder)(r `^ (#+) (.+?) $`), (_, lvl, txt) => `${'<ol>'.repeat(lvl.length)}<li>${txt}</li>${'</ol>'.repeat(lvl.length)}`)
238
+ .replace((0, common_1.RegExpBuilder)(r `</ol> (\s*?) <ol>`), '$1')
239
+ // Definition list: ;head, :item
240
+ .replace((0, common_1.RegExpBuilder)(r `^ ; (.+) $`), '<dl><dt>$1</dt></dl>')
241
+ .replace((0, common_1.RegExpBuilder)(r `^ (:+) (.+?) $`), (_, lvl, txt) => `${'<dl>'.repeat(lvl.length)}<dd>${txt}</dd>${'</dl>'.repeat(lvl.length)}`)
242
+ .replace((0, common_1.RegExpBuilder)(r `</dl> (\s*?) <dl>`), '$1')
243
+ // Tables: {|, |+, !, |-, |, |}
244
+ .replace((0, common_1.RegExpBuilder)(r `^ \{\| (.*?) $`), (_, attrs) => `<table ${attrs}><tr>`)
245
+ .replace((0, common_1.RegExpBuilder)(r `^ ! ([^]+?) (?= \n^[!|] )`), (_, content) => `<th>${content}</th>`)
246
+ .replace((0, common_1.RegExpBuilder)(r `^ \|\+ (.*?) $`), (_, content) => `<caption>${content}</caption>`)
247
+ .replace((0, common_1.RegExpBuilder)(r `^ \|[^-+}] ([^]*?) (?= \n | \|\| )`), (_, content) => `<td>${content}</td>`)
248
+ .replace((0, common_1.RegExpBuilder)(r `\|\|[^-+}] ([^]*?) (?= \n | \|\| )`), (_, content) => `<td>${content}</td>`)
249
+ .replace((0, common_1.RegExpBuilder)(r `^ \|- (.*?) $`), (_, attrs) => `</tr><tr ${attrs}>`)
250
+ .replace((0, common_1.RegExpBuilder)(r `^ \|\}`), `</tr></table>`)
251
+ // References: <ref></ref>, <references/>
252
+ .replace((0, common_1.RegExpBuilder)(r `<ref> (.+?) </ref>`), (_, text) => {
253
+ refs.push(text);
254
+ refCount++;
255
+ return `<sup><a id="cite-${refCount}" class="ref" href="#ref-${refCount}">[${refCount}]</a></sup>`;
256
+ })
257
+ .replace((0, common_1.RegExpBuilder)(r `<references \s* /?>`), '<ol>' + refs.map((ref, i) => `<li id="ref-${+i + 1}"> <a href="#cite-${+i + 1}">↑</a> ${ref} </li>`).join('\n') + '</ol>')
258
+ // Nonstandard: ``code`` and ```code blocks```
259
+ .replace((0, common_1.RegExpBuilder)(r ` \`\`\` ([^\`]+?) \`\`\` `), '<pre>$1</pre>')
260
+ .replace((0, common_1.RegExpBuilder)(r ` \`\` ([^\`]+?) \`\` `), '<code>$1</code>')
261
+ // Spacing
262
+ .replace(/(\r?\n){2}/g, '\n</p><p>\n');
263
+ }
264
+ // Final changes (run only once)
265
+ outText = outText
266
+ // Restore nowiki contents
267
+ .replace(/%NOWIKI#(\d+)%/g, (_, n) => fullyEscape(nowikis[n]));
268
+ const result = { data: outText, metadata: metadata };
269
+ return result;
270
+ }
271
+ exports.parse = parse;
@@ -0,0 +1,2 @@
1
+ declare const _default: string;
2
+ export default _default;