mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			261 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const sanitizeHtml = require('sanitize-html');
 | |
| 
 | |
| const fs = require("fs");
 | |
| const path = require("path");
 | |
| const html = require("html");
 | |
| 
 | |
| const TMP_API_DOCS = './tmp/api_docs';
 | |
| const TMP_FE_DOCS = TMP_API_DOCS + '/frontend_api';
 | |
| const TMP_BE_DOCS = TMP_API_DOCS + '/backend_api';
 | |
| 
 | |
| const sourceFiles = getFilesRecursively(TMP_API_DOCS);
 | |
| 
 | |
| for (const sourcePath of sourceFiles) {
 | |
|     const content = fs.readFileSync(sourcePath).toString();
 | |
|     const transformedContent = transform(content);
 | |
|     const prettifiedContent = html.prettyPrint(transformedContent, {indent_size: 2});
 | |
|     const filteredContent = prettifiedContent
 | |
|         .replace(/<br \/>Documentation generated by <a href="https:\/\/github.com\/jsdoc\/jsdoc">[^<]+<\/a>/gi, '')
 | |
|         .replace(/JSDoc: (Class|Module): [a-z]+/gi, '');
 | |
| 
 | |
|     const destPath = sourcePath.replaceAll("tmp", "docs");
 | |
| 
 | |
|     fs.mkdirSync(path.dirname(destPath), {recursive: true});
 | |
|     fs.writeFileSync(destPath, filteredContent.trim());
 | |
| 
 | |
|     console.log(destPath);
 | |
| }
 | |
| 
 | |
| const USER_GUIDE_DIR = './docs/user_guide';
 | |
| const META_PATH = USER_GUIDE_DIR + '/!!!meta.json';
 | |
| 
 | |
| const meta = JSON.parse(fs.readFileSync(META_PATH).toString());
 | |
| const rootNoteMeta = meta.files[0];
 | |
| 
 | |
| const {noteMeta: scriptApiDocsRoot, filePath: scriptApiDocsRootFilePath, notePath: scriptApiDocsRootNotePath} =
 | |
|     findNoteMeta(rootNoteMeta, 'Script API', []);
 | |
| const BE_FILES = ['AbstractBeccaEntity', 'BAttribute', 'BBranch', 'BEtapiToken', 'BNote', 'BNoteRevision', 'BOption', 'BRecentNote', 'module-sql'];
 | |
| 
 | |
| const FE_FILES = ['FNote', 'FAttribute', 'FBranch', 'FNoteComplement'];
 | |
| 
 | |
| scriptApiDocsRoot.dirFileName = scriptApiDocsRoot.dataFileName.substr(0, scriptApiDocsRoot.dataFileName.length - 5);
 | |
| scriptApiDocsRoot.children = getScriptApiMeta();
 | |
| 
 | |
| fs.writeFileSync(META_PATH, JSON.stringify(meta, null, 2));
 | |
| const scriptApiDocsRootDir =  USER_GUIDE_DIR + scriptApiDocsRootFilePath;
 | |
| 
 | |
| fs.mkdirSync(scriptApiDocsRootDir, {recursive: true});
 | |
| fs.mkdirSync(scriptApiDocsRootDir + '/BackendScriptApi', {recursive: true});
 | |
| fs.mkdirSync(scriptApiDocsRootDir + '/FrontendScriptApi', {recursive: true});
 | |
| 
 | |
| const BE_ROOT = scriptApiDocsRootDir + '/BackendScriptApi.html';
 | |
| const FE_ROOT = scriptApiDocsRootDir + '/FrontendScriptApi.html';
 | |
| 
 | |
| fs.copyFileSync(TMP_BE_DOCS + '/BackendScriptApi.html', BE_ROOT);
 | |
| fs.copyFileSync(TMP_FE_DOCS + '/FrontendScriptApi.html', FE_ROOT);
 | |
| 
 | |
| for (const file of BE_FILES) {
 | |
|     fs.copyFileSync(TMP_BE_DOCS + '/' + file + '.html', `${scriptApiDocsRootDir}/BackendScriptApi/${file}.html`);
 | |
| }
 | |
| rewriteLinks(BE_ROOT, BE_FILES, 'BackendScriptApi');
 | |
| 
 | |
| for (const file of FE_FILES) {
 | |
|     fs.copyFileSync(TMP_FE_DOCS + '/' + file + '.html', `${scriptApiDocsRootDir}/FrontendScriptApi/${file}.html`);
 | |
| }
 | |
| rewriteLinks(FE_ROOT, FE_FILES, 'FrontendScriptApi');
 | |
| 
 | |
| fs.rmSync(USER_GUIDE_DIR + '/index.html', {force: true});
 | |
| fs.rmSync(USER_GUIDE_DIR + '/navigation.html', {force: true});
 | |
| fs.rmSync(USER_GUIDE_DIR + '/style.css', {force: true});
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| function getFilesRecursively(directory) {
 | |
|     const files = [];
 | |
| 
 | |
|     function getFilesRecursivelyInner(directory) {
 | |
|         const filesInDirectory = fs.readdirSync(directory);
 | |
|         for (const file of filesInDirectory) {
 | |
|             const absolute = path.join(directory, file);
 | |
|             if (fs.statSync(absolute).isDirectory()) {
 | |
|                 getFilesRecursivelyInner(absolute);
 | |
|             } else if (file.endsWith('.html')) {
 | |
|                 files.push(absolute);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     getFilesRecursivelyInner(directory);
 | |
| 
 | |
|     return files;
 | |
| }
 | |
| 
 | |
| function transform(content) {
 | |
|     const result = sanitizeHtml(content, {
 | |
|         allowedTags: [
 | |
|             'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
 | |
|             'li', 'b', 'i', 'strong', 'em', 'strike', 's', 'del', 'abbr', 'code', 'hr', 'br', 'div',
 | |
|             'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'section', 'img',
 | |
|             'figure', 'figcaption', 'span', 'label', 'input',
 | |
|         ],
 | |
|         nonTextTags: [ 'style', 'script', 'textarea', 'option', 'h1', 'h2', 'h3', 'nav' ],
 | |
|         allowedAttributes: {
 | |
|             'a': [ 'href', 'class', 'data-note-path' ],
 | |
|             'img': [ 'src' ],
 | |
|             'section': [ 'class', 'data-note-id' ],
 | |
|             'figure': [ 'class' ],
 | |
|             'span': [ 'class', 'style' ],
 | |
|             'label': [ 'class' ],
 | |
|             'input': [ 'class', 'type', 'disabled' ],
 | |
|             'code': [ 'class' ],
 | |
|             'ul': [ 'class' ],
 | |
|             'table': [ 'class' ],
 | |
|             'en-media': [ 'hash' ]
 | |
|         },
 | |
|         allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'data', 'evernote'],
 | |
|         transformTags: {
 | |
|             // 'h5': sanitizeHtml.simpleTransform('strong', {}, false),
 | |
|             'table': sanitizeHtml.simpleTransform('table', {}, false)
 | |
|         },
 | |
|     });
 | |
| 
 | |
|     return result.replace(/<table>/gi, '<figure class="table"><table>')
 | |
|         .replace(/<\/table>/gi, '</table></figure>')
 | |
|         .replace(/<div><\/div>/gi, '')
 | |
|         .replace(/<h5>/gi, '<p><strong>')
 | |
|         .replace(/<\/h5>/gi, '</strong></p>')
 | |
|         .replace(/<h4>/gi, '<h2>')
 | |
|         .replace(/<\/h4>/gi, '</h2>')
 | |
|         .replace(/<span class="signature-attributes">opt<\/span>/gi, '')
 | |
|         .replace(/<h2>.*new (BackendScriptApi|FrontendScriptApi).*<\/h2>/gi, '')
 | |
|         ;
 | |
| }
 | |
| 
 | |
| function findNoteMeta(noteMeta, name, notePath) {
 | |
|     if (noteMeta.title === name) {
 | |
|         return {
 | |
|             noteMeta,
 | |
|             filePath: '/' + noteMeta.dirFileName,
 | |
|             notePath
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     for (const childMeta of noteMeta.children || []) {
 | |
|         const ret = findNoteMeta(childMeta, name, [...notePath, childMeta.noteId]);
 | |
| 
 | |
|         if (ret) {
 | |
|             return {
 | |
|                 noteMeta: ret.noteMeta,
 | |
|                 filePath: '/' + noteMeta.dirFileName + ret.filePath,
 | |
|                 notePath: ret.notePath
 | |
|             };
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return null;
 | |
| }
 | |
| 
 | |
| function rewriteLinks(rootFilePath, files, dir) {
 | |
|     let content = fs.readFileSync(rootFilePath).toString();
 | |
| 
 | |
|     for (const file of files) {
 | |
|         content = content.replaceAll(`href="${file}.html"`, `href="${dir}/${file}.html"`);
 | |
|     }
 | |
| 
 | |
|     fs.writeFileSync(rootFilePath, content);
 | |
| }
 | |
| 
 | |
| function createChildren(files, notePath) {
 | |
|     let positionCounter = 0;
 | |
| 
 | |
|     const camelCase = name => {
 | |
|         if (name === 'module-sql') {
 | |
|             return 'moduleSql';
 | |
|         } else if (/[^a-z]+/i.test(name)) {
 | |
|             throw new Error(`Bad name '${name}'`);
 | |
|         }
 | |
| 
 | |
|         return name.charAt(0).toLowerCase() + name.substr(1);
 | |
|     };
 | |
| 
 | |
|     return files.map(file => {
 | |
|         positionCounter += 10;
 | |
| 
 | |
|         const noteId = "_" + camelCase(file);
 | |
| 
 | |
|         return {
 | |
|             "isClone": false,
 | |
|             "noteId": noteId,
 | |
|             "notePath": [
 | |
|                 ...notePath,
 | |
|                 '_' + camelCase(file)
 | |
|             ],
 | |
|             "title": file,
 | |
|             "notePosition": positionCounter,
 | |
|             "prefix": null,
 | |
|             "isExpanded": false,
 | |
|             "type": "text",
 | |
|             "mime": "text/html",
 | |
|             "attributes": [],
 | |
|             "format": "html",
 | |
|             "dataFileName": file + ".html"
 | |
|         }
 | |
|     });
 | |
| }
 | |
| 
 | |
| function getScriptApiMeta() {
 | |
|     return [
 | |
|         {
 | |
|             "isClone": false,
 | |
|             "noteId": "_frontendApi",
 | |
|             "notePath": [
 | |
|                 ...scriptApiDocsRootNotePath,
 | |
|                 "_frontendApi"
 | |
|             ],
 | |
|             "title": "API docs",
 | |
|             "notePosition": 10,
 | |
|             "prefix": null,
 | |
|             "isExpanded": false,
 | |
|             "type": "text",
 | |
|             "mime": "text/html",
 | |
|             "attributes": [],
 | |
|             "format": "html",
 | |
|             "dataFileName": "FrontendScriptApi.html",
 | |
|             "dirFileName": "FrontendScriptApi",
 | |
|             "children": createChildren(FE_FILES, [
 | |
|                 ...scriptApiDocsRootNotePath,
 | |
|                 "_frontendApi"
 | |
|             ])
 | |
|         },
 | |
|         {
 | |
|             "isClone": false,
 | |
|             "noteId": "_backendApi",
 | |
|             "notePath": [
 | |
|                 ...scriptApiDocsRootNotePath,
 | |
|                 "_backendApi"
 | |
|             ],
 | |
|             "title": "API docs",
 | |
|             "notePosition": 20,
 | |
|             "prefix": null,
 | |
|             "isExpanded": false,
 | |
|             "type": "text",
 | |
|             "mime": "text/html",
 | |
|             "attributes": [],
 | |
|             "format": "html",
 | |
|             "dataFileName": "BackendScriptApi.html",
 | |
|             "dirFileName": "BackendScriptApi",
 | |
|             "children": createChildren(BE_FILES, [
 | |
|                 ...scriptApiDocsRootNotePath,
 | |
|                 "_backendApi"
 | |
|             ])
 | |
|         }
 | |
|     ];
 | |
| }
 | |
| 
 |