import * as fs from 'fs-extra'; import { pathExistsSync } from 'fs-extra'; const Entities = require('html-entities').AllHtmlEntities; const htmlparser2 = require('@joplin/fork-htmlparser2'); const Datauri = require('datauri/sync'); import { CssTypes, parse as cssParse, stringify as cssStringify } from '@adobe/css-tools'; const selfClosingElements = [ 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr', ]; const htmlentities = (s: string): string => { const output = (new Entities()).encode(s); return output.replace(/ /ig, '\t'); }; const dataUriEncode = (filePath: string): string => { try { const result = Datauri(filePath); return result.content; } catch (error) { // If the file path is invalid, the Datauri will throw an exception. // Instead, since we can just ignore that particular file. // Fixes https://github.com/laurent22/joplin/issues/8305 return ''; } }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const attributesHtml = (attr: any) => { const output = []; for (const n in attr) { if (!attr.hasOwnProperty(n)) continue; output.push(`${n}="${htmlentities(attr[n])}"`); } return output.join(' '); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const attrValue = (attrs: any, name: string): string => { if (!attrs[name]) return ''; return attrs[name]; }; const isSelfClosingTag = (tagName: string) => { return selfClosingElements.includes(tagName.toLowerCase()); }; const processCssContent = (cssBaseDir: string, content: string): string => { const o = cssParse(content, { silent: false, }); for (const rule of o.stylesheet.rules) { if (rule.type === 'font-face') { for (const declaration of rule.declarations) { if (declaration.type === CssTypes.comment) { continue; } if (declaration.property === 'src') { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied declaration.value = declaration.value.replace(/url\((.*?)\)/g, (_v: any, url: string) => { const cssFilePath = `${cssBaseDir}/${url}`; if (fs.existsSync(cssFilePath)) { return `url(${dataUriEncode(cssFilePath)})`; } else { return `url(${url})`; } }); } } } } return cssStringify(o); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const processLinkTag = (baseDir: string, _name: string, attrs: any): string => { const href = attrValue(attrs, 'href'); if (!href) return null; const filePath = `${baseDir}/${href}`; if (!pathExistsSync(filePath)) return null; const content = fs.readFileSync(filePath, 'utf8'); return ``; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const processScriptTag = (baseDir: string, _name: string, attrs: any): string => { const src = attrValue(attrs, 'src'); if (!src) return null; const scriptFilePath = `${baseDir}/${src}`; let content = fs.readFileSync(scriptFilePath, 'utf8'); // There's no simple way to insert arbitrary content in ` or `