Remove preact and htm dependencies

Saves about 10kB, which isn't as much as I had hoped actually.
Fixes #42.
This commit is contained in:
Florine W. Dekker 2021-04-18 14:40:30 +02:00
parent bcbbbcb60a
commit 84efe5fcc8
Signed by: FWDekker
GPG Key ID: B1B567AF58D6EE0F
4 changed files with 70 additions and 72 deletions

BIN
package-lock.json generated

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"name": "interlanguage-checker",
"version": "1.10.23",
"version": "1.10.24",
"description": "Check the consistency of MediaWiki interlanguage links in a simple overview.",
"author": "Felix W. Dekker",
"browser": "dist/bundle.js",
@ -17,9 +17,7 @@
},
"dependencies": {
"fetch-jsonp": "^1.1.3",
"fork-awesome": "^1.1.7",
"htm": "^3.0.4",
"preact": "^10.5.13"
"fork-awesome": "^1.1.7"
},
"devDependencies": {
"css-loader": "^5.2.2",

View File

@ -1,5 +1,18 @@
import {html} from "htm/preact";
import {Component} from "preact";
window.ilc = window.ilc || {};
/**
* Upon clicking the icon at `target`, copies the string `[[${link}]]` to the clipboard and temporarily replaces the
* clipboard icon with a checkmark.
*
* @param target the icon that is clicked on
* @param link {String} the link to copy to the clipboard
*/
window.ilc.onClickCopy = function(target, link) {
// noinspection JSIgnoredPromiseFromCall
navigator.clipboard.writeText(`[[${link}]]`);
target.classList.replace("fa-clipboard", "fa-check");
setTimeout(() => target.classList.replace("fa-check", "fa-clipboard"), 1000);
}
/**
@ -24,7 +37,7 @@ export class ValidatableInput {
/**
* Returns the value of the underlying input element.
*
* @return {string} the value of the underlying input element
* @return {String} the value of the underlying input element
*/
getValue() {
return this.input.value;
@ -42,7 +55,7 @@ export class ValidatableInput {
/**
* Validates the input.
*
* @return {string} an empty string if the input string is valid, and a string explaining why it is is invalid
* @return {String} an empty string if the input string is valid, and a string explaining why it is is invalid
* otherwise
*/
validate() {
@ -214,21 +227,20 @@ export class MessageHandler {
*
* @property pages {Page[]} the pages in the network
*/
export class InterlangTable extends Component {
export class InterlangTable {
/**
* Generates an icon element with the given title and additional classes.
*
* @param icon {string} the name of the icon to display
* @param title {string} the title of the icon, used for the `title` attribute
* @param [classes] {string[]} the additional classes to apply to the icon
* @return {VNode} an icon element with the given title and additional classes
* @return {String} an icon element with the given title and additional classes
* @private
*/
_createIcon(icon, title, classes) {
return html`<i class="fa fa-${icon} ${(classes || []).join(" ")}" title="${title}"></i>`
return `<i class="fa fa-${icon} ${(classes || []).join(" ")}" title="${title}"></i>`;
}
/**
* Returns an appropriate label for the given page.
*
@ -238,7 +250,7 @@ export class InterlangTable extends Component {
*
* @param pages {Page[]} a list of all pages
* @param page {Page} the page to generate a label of
* @return {VNode} an appropriate label with icons for the given page
* @return {String} an appropriate label with icons for the given page
* @private
*/
_generateLabel(pages, page) {
@ -246,52 +258,40 @@ export class InterlangTable extends Component {
? page.link.toString()
: page.link.lang;
const onClickCopy = (event) => {
navigator.clipboard.writeText(`[[${page.link}]]`);
event.target.classList.replace("fa-clipboard", "fa-check");
setTimeout(() => event.target.classList.replace("fa-check", "fa-clipboard"), 1000);
};
return html`
<span class="${page.exists ? "" : "redLink"}">
<a href="${page.url}" target="_blank" title="${page.link}">${labelText}</a>
<span> </span>
<a href="${page.url}?action=edit" target="_blank" title="Edit"><i class="fa fa-pencil"></i></a>
<span> </span>
<a title="Copy"><i class="fa fa-clipboard" onclick="${onClickCopy}"></i></a>
</span>
`;
return "" +
`<span class="${page.exists ? "" : "redLink"}">` +
/**/`<a href="${page.url}" target="_blank" title="${page.link}">${labelText}</a>` +
/**/`<span> </span>` +
/**/`<a href="${page.url}?action=edit" target="_blank" title="Edit"><i class="fa fa-pencil"></i></a>` +
/**/`<span> </span>` +
/**/`<a title="Copy"><i class="fa fa-clipboard" onclick="window.ilc.onClickCopy(this, '${page.link}')"></i></a>` +
`</span>`;
}
/**
* Generates the head of the table generated by `#toTable`.
*
* @param network {InterlangNetwork} the network to generate the head for
* @return {VNode} the head of the table generated by `#toTable`
* @return {String} the head of the table generated by `#toTable`
* @private
*/
_generateTableHead(network) {
const topRow = html`
<tr>
<th rowspan="2"></th>
<th class="sourceLabel" rowspan="2">Source</th>
<th colspan="${network.pages.length}">Destination</th>
</tr>
`;
const bottomRow = html`
<tr>
${network.pages.map(page => html`<th>${this._generateLabel(network.pages, page)}</th>`)}
</tr>
`;
return html`<thead>${topRow}${bottomRow}</thead>`;
return "" +
`<thead>` +
/**/`<tr>` +
/****/`<th rowspan="2"></th>` +
/****/`<th class="sourceLabel" rowspan="2">Source</th>` +
/****/`<th colspan="${network.pages.length}">Destination</th>` +
/**/`</tr>` +
/**/`<tr>${network.pages.map(page => `<th>${this._generateLabel(network.pages, page)}</th>`)}</tr>` +
`</thead>`;
}
/**
* Generates the body of the table generated by `#toTable`.
*
* @param network {InterlangNetwork} the network to generate the body for
* @return {HTMLElement} the body of the table generated by `#toTable`
* @return {String} the body of the table generated by `#toTable`
* @private
*/
_generateTableBody(network) {
@ -315,7 +315,7 @@ export class InterlangTable extends Component {
return this._createIcon("chain-broken", "Misses one or more links 😕", ["error"]);
}
})
.map(it => html`${it}<span> </span>`);
.map(it => `${it}<span> </span>`);
const label = this._generateLabel(network.pages, srcPage);
const cells = network.pages.map(dstPage => {
const linkState = verdict.pages.find(it => it.page.link.equals(dstPage.link)).verdict;
@ -327,7 +327,7 @@ export class InterlangTable extends Component {
case "unlinked":
return this._createIcon("times", "Link is missing 😕", ["error"]);
case "self-unlinked":
return html`<span></span>`;
return `<span></span>`;
case "redirected":
return this._createIcon("mail-forward", "Links to a redirect 😕", ["warning"]);
default:
@ -335,30 +335,29 @@ export class InterlangTable extends Component {
}
});
return html`
<tr>
<th>${icons}</th>
<th class="sourceLabel">${label}</th>
${cells.map(it => html`<td>${it}</td>`)}
</tr>`;
return "" +
`<tr>` +
/**/`<th>${icons}</th>` +
/**/`<th class="sourceLabel">${label}</th>` +
/**/cells.map(it => `<td>${it}</td>`) +
`</tr>`;
});
return html`<tbody>${rows}</tbody>`;
return `<tbody>${rows}</tbody>`;
}
/**
* Renders the the table describing the interlanguage network.
*
* @param props {Object} the element's rendering properties
* @param props.network {InterlangNetwork} the network of pages to render
* @return {VNode} the generated table
* @param id {String} the ID to assign to the table element
* @param network {InterlangNetwork} the network of pages to render
* @return {String} the generated table
*/
render(props) {
return html`
<table id="${props.id}">
${this._generateTableHead(props.network)}
${this._generateTableBody(props.network)}
</table>
`;
render(id, network) {
return "" +
`<table id="${id}">` +
/**/this._generateTableHead(network) +
/**/this._generateTableBody(network) +
`</table>`;
}
}

View File

@ -1,5 +1,5 @@
const {$, doAfterLoad, footer, header, nav, showPage} = window.fwdekker;
import {html, render} from "htm/preact";
// noinspection JSUnresolvedVariable
const {$, doAfterLoad, footer, header, nav, showPage, stringToHtml} = window.fwdekker;
import "fork-awesome/css/fork-awesome.css";
import {InterlangTable, MessageHandler, ValidatableInput} from "./DOM";
import {discoverNetwork, InterlangNetwork, MediaWiki, MediaWikiManager} from "./MediaWiki";
@ -42,12 +42,14 @@ doAfterLoad(async () => {
return "API URL must not be empty.";
try {
new URL(value); // Throws exception if invalid
new URL(value); // Throws exception if invalid
return "";
} catch (error) {
try {
new URL(`http://${value}`);
$("#url").value = `http://${value}`;
// noinspection HttpUrlsUsage
const url = `http://${value}`;
new URL(url); // Throws exception if invalid
$("#url").value = url;
return "";
} catch {
return error.message;
@ -110,18 +112,17 @@ doAfterLoad(async () => {
const form = $("#networkTableForm");
form.textContent = "";
render(html`
<${InterlangTable} id="networkTable" network=${network} />`, form);
form.appendChild(stringToHtml((new InterlangTable()).render("networkTable", network), "table"));
switch (network.getVerdict()) {
case "perfect":
messageHandler.handle("complete", "A perfect network! 🙂");
break;
case "broken":
messageHandler.handle("warning", "The network is broken 😞<br />Hover over an icon for more information.");
messageHandler.handle("warning", "The network is broken 😞<br />Hover over an icon in the left column for more information.");
break;
case "flawed":
messageHandler.handle("warning", "The network is complete but flawed 😕<br />Hover over an icon for more information.");
messageHandler.handle("warning", "The network is complete but flawed 😕<br />Hover over an icon in the left column for more information.");
break;
}
})