From f562c3fdf1bf4d85101251cf2254c43e2337ccf1 Mon Sep 17 00:00:00 2001 From: CismonX Date: Fri, 23 Apr 2021 20:38:07 +0800 Subject: [PATCH] Remove requirement for package `node-html-parser`. --- ext/html-preview.pm | 43 ++++++++++++++++++++++++++ package-lock.json | 21 ++----------- package.json | 8 +---- scripts/package.sh | 8 ++++- src/contexts/preview.ts | 18 ++--------- src/global_context.ts | 5 ++- src/options.ts | 4 --- src/utils/converter.ts | 28 +++++++++-------- src/utils/dom.ts | 67 ----------------------------------------- 9 files changed, 74 insertions(+), 128 deletions(-) create mode 100644 ext/html-preview.pm delete mode 100644 src/utils/dom.ts diff --git a/ext/html-preview.pm b/ext/html-preview.pm new file mode 100644 index 0000000..324d5c6 --- /dev/null +++ b/ext/html-preview.pm @@ -0,0 +1,43 @@ +# +# ext/html-preview.pm +# +# Copyright (C) 2021 CismonX +# +# This file is part of vscode-texinfo. +# +# vscode-texinfo is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# vscode-texinfo is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along with +# vscode-texinfo. If not, see . +# + +use strict; + +sub vscode_convert_texinfo_image_uri { + my ( $self, $cmdname, $command, $args ) = @_; + + my $filename = $args->[0]->{'monospacetext'}; + if ( defined($filename) + && rindex( $filename, 'http://', 0 ) == -1 + && rindex( $filename, 'https://', 0 ) == -1 ) + { + $self->set_conf( 'IMAGE_LINK_PREFIX', + $self->{'parser'}->{'values'}->{'__vscode_texinfo_image_uri_base'} + ); + } + return &{ $self->default_commands_conversion($cmdname) } + ( $self, $cmdname, $command, $args ); +} + +texinfo_register_command_formatting( 'image', + \&vscode_convert_texinfo_image_uri ); + +1; diff --git a/package-lock.json b/package-lock.json index d288a91..ebbe001 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1440,12 +1440,6 @@ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, "hosted-git-info": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", @@ -1966,15 +1960,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node-html-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-2.2.1.tgz", - "integrity": "sha512-Vccqb62t6t7DkMVwqPQgb0NWO+gUMMDm+1X3LzqbtXLqjilCTtUYTlniKk08yuA1zIhEFVzu/dozpqs5KZbRFQ==", - "dev": true, - "requires": { - "he": "1.2.0" - } - }, "node-releases": { "version": "1.1.71", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", @@ -2749,9 +2734,9 @@ "dev": true }, "ts-loader": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.0.2.tgz", - "integrity": "sha512-whFcWsvFRb91lzLLwU06jKS8ZwQsXA7Rk2NNLBjWNDFoaZgfSjrh8UJvc7sMknR9Vhs6NroQlw+0+2wW3fjR9Q==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.1.0.tgz", + "integrity": "sha512-yjgM84n/NhzPbcAvvjGFihJxkXmwaUOQLcJezJqT9l/eD0CRcF6zu/dL21NTr4iyW47Rs4lJZawN/d3lSX07sw==", "dev": true, "requires": { "chalk": "^4.1.0", diff --git a/package.json b/package.json index cecf813..55496a0 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,7 @@ "json5": "^2.2.0", "language-texinfo": "^1.0.0", "minify-xml": "^2.5.0", - "node-html-parser": "^2.2.1", - "ts-loader": "^9.0.2", + "ts-loader": "^9.1.0", "ts-node": "^9.1.1", "typescript": "^4.2.4", "vsce": "^1.87.0", @@ -171,11 +170,6 @@ "minimum": 0, "description": "Max number of errors before quit when trying to display preview." }, - "texinfo.preview.localImage": { - "type": "boolean", - "default": false, - "description": "Display local images in in preview." - }, "texinfo.preview.maxSize": { "type": "integer", "default": 2, diff --git a/scripts/package.sh b/scripts/package.sh index c615f0c..2877fb5 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -23,7 +23,13 @@ sed -i '' -e '2d' package.json json5 -o language-configuration.json{,} # Remove comments from Markdown files. sed -i '' -e '1,8d' README.md CHANGELOG.md -cd ../.. +cd ext +# Minify Perl scripts. +if [ -x "$(command -v perltidy)" ]; then + perltidy --mangle -dac -b html-preview.pm + rm html-preview.pm.bak +fi +cd ../../.. # Re-package .vsix file. node ./scripts/make-vsix.js $VSIX_FILE_NAME diff --git a/src/contexts/preview.ts b/src/contexts/preview.ts index 60c83ae..5589e26 100644 --- a/src/contexts/preview.ts +++ b/src/contexts/preview.ts @@ -24,7 +24,6 @@ import * as vscode from 'vscode'; import DocumentContext from './document'; import Converter from '../utils/converter'; import { getNodeHtmlRef, prompt } from '../utils/misc'; -import { Operator, Optional } from '../utils/types'; /** * Stores information of a Texinfo document preview. @@ -56,8 +55,9 @@ export default class PreviewContext { this.pendingUpdate = false; // Inform the user that the preview is updating if `makeinfo` takes too long. setTimeout(() => this.updating && this.updateTitle(), 500); - const { data, error } = await new Converter(this.document.fileName, this.globalContext.options, this.logger) - .convertToHtml(this.imageTransformer, this.script); + const initFile = this.globalContext.extensionPath + '/ext/html-preview.pm'; + const converter = new Converter(this.document.fileName, initFile, this.globalContext.options, this.logger); + const { data, error } = await converter.toHTML(path => this.panel.webview.asWebviewUri(path), this.script); if (error) { this.logger.log(error); this.diagnosis.update(this.document, error); @@ -102,18 +102,6 @@ export default class PreviewContext { */ private updating = false; - private get imageTransformer(): Optional> { - if (!this.globalContext.options.localImage) return undefined; - const pathName = path.dirname(this.document.fileName); - return src => { - // Do not transform URIs of online images. - if (src.startsWith('https://') || src.startsWith('http://')) return src; - const srcUri = vscode.Uri.file(pathName + '/' + src); - // To display images in webviews, image URIs in HTML should be converted to VSCode-recognizable ones. - return this.panel.webview.asWebviewUri(srcUri).toString(); - }; - } - /** * Generate script used for jumping to the corresponding location of preview with code lens. */ diff --git a/src/global_context.ts b/src/global_context.ts index 18e9f93..0f03d5f 100644 --- a/src/global_context.ts +++ b/src/global_context.ts @@ -36,13 +36,12 @@ import FoldingRangeProvider from './providers/folding_range'; export default class GlobalContext { readonly contextMapping = new ContextMapping(this); - readonly diagnosis = new Diagnosis; - readonly indicator = new Indicator(this); - readonly logger = new Logger; + readonly extensionPath = this.context.extensionPath; + /** * Note: `Options`' no singleton. Do not wire directly, always use `globalContext.options` instead. */ diff --git a/src/options.ts b/src/options.ts index 5c54c87..cf46d68 100644 --- a/src/options.ts +++ b/src/options.ts @@ -52,10 +52,6 @@ export default class Options { return this.getNumber('preview.errorLimit'); } - get localImage() { - return this.getBoolean('preview.localImage'); - } - get maxSize() { return this.getNumber('preview.maxSize') * 1024 * 1024; } diff --git a/src/utils/converter.ts b/src/utils/converter.ts index 813015d..cba6d19 100644 --- a/src/utils/converter.ts +++ b/src/utils/converter.ts @@ -19,10 +19,10 @@ * vscode-texinfo. If not, see . */ + import * as path from 'path'; import * as vscode from 'vscode'; import Logger from '../logger'; import Options from '../options'; -import DOM from './dom'; import { exec } from './misc'; import { Operator } from './types'; @@ -31,25 +31,27 @@ import { Operator } from './types'; */ export default class Converter { - async convertToHtml(imgTransformer?: Operator, insertScript?: string) { - const options = ['-o-', '--no-split', '--html', `--error-limit=${this.options.errorLimit}`]; + async toHTML(imgTransformer: Operator, insertScript?: string) { + const newPath = imgTransformer(vscode.Uri.file(path.dirname(this.path))).toString() + '/'; + const options = ['-o-', '--no-split', '--html', `--error-limit=${this.options.errorLimit}`, + `--init-file=${this.initFile}`, '-D', `__vscode_texinfo_image_uri_base ${newPath}`]; this.options.noHeaders && options.push('--no-headers'); this.options.noValidation && options.push('--no-validate'); this.options.noWarnings && options.push('--no-warn'); + if (insertScript !== undefined) { + options.push('--set-customization-variable', `EXTRA_HEAD `); + } this.includeCustomCSS(this.options.customCSS, options); this.addVars(this.options.vars, options); - const result = await exec(this.options.makeinfo, options.concat(this.path), this.options.maxSize); - if (result.data !== undefined) { - // No worry about performance here, as the DOM is lazily initialized. - const dom = new DOM(result.data); - imgTransformer && dom.transformImageUri(imgTransformer); - insertScript && dom.insertScript(insertScript); - result.data = dom.outerHTML; - } - return result; + return await exec(this.options.makeinfo, options.concat(this.path), this.options.maxSize); } - constructor(private readonly path: string, private readonly options: Options, private readonly logger: Logger) {} + constructor( + private readonly path: string, + private readonly initFile: string, + private readonly options: Options, + private readonly logger: Logger, + ) {} private addVars(vars: readonly string[], options: string[]) { vars.forEach(varName => options.push('-D', varName)); diff --git a/src/utils/dom.ts b/src/utils/dom.ts deleted file mode 100644 index 55ec77c..0000000 --- a/src/utils/dom.ts +++ /dev/null @@ -1,67 +0,0 @@ -/** - * utils/dom.ts - * - * Copyright (C) 2020,2021 CismonX - * - * This file is part of vscode-texinfo. - * - * vscode-texinfo is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * vscode-texinfo is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along with - * vscode-texinfo. If not, see . - */ - -import * as htmlparser from 'node-html-parser'; -import { Operator } from './types'; - -/** - * Parse HTML into DOM and transform elements. - */ -export default class DOM { - - get outerHTML() { - if (this.changed) { - this.html = this.value.outerHTML; - this.changed = false; - } - return this.html; - } - - insertScript(script: string) { - this.value.querySelector('head').insertAdjacentHTML('beforeend', ``); - this.changed = true; - } - - /** - * Transform and replace the `src` attribute value of all `img` elements from HTML using given function. - * - * @param transformer - */ - transformImageUri(transformer: Operator) { - const elements = this.value.querySelectorAll('img'); - if (elements.length === 0) return; - elements.forEach(element => { - const src = element.getAttribute('src'); - src && element.setAttribute('src', transformer(src)); - }); - this.changed = true; - } - - constructor(private html: string) {} - - private _value?: htmlparser.HTMLElement; - - private changed = false; - - private get value() { - return this._value ??= htmlparser.parse(this.html); - } -}