mirror of
https://github.com/koloml/philomena-tagging-assistant.git
synced 2026-11-07 16:18:19 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
866a295dbb | ||
|
|
9c5ef143e7 | ||
|
|
5435e055c3 | ||
|
|
2b337e2fd6 |
No files matched your search
@@ -4,6 +4,7 @@ import path from "path";
|
||||
import fs from "fs";
|
||||
import { SwapDefinedVariablesPlugin } from "../plugins/swap-defined-variables.js";
|
||||
import { ScssViteReadEnvVariableFunctionPlugin } from "../plugins/scss-read-env-variable-function.js";
|
||||
import { ConvertCjsToAmd } from "../plugins/convert-cjs-to-amd.js";
|
||||
|
||||
/**
|
||||
* Create the result base file name for the file.
|
||||
@@ -37,7 +38,7 @@ function wrapScriptIntoIIFE() {
|
||||
Object.keys(bundle).forEach(fileName => {
|
||||
const file = bundle[fileName];
|
||||
|
||||
file.code = `(() => {\n${file.code}})();`
|
||||
file.code = `(()=>{${file.code}})();`
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -188,19 +189,16 @@ export async function buildScriptsAndStyles(buildOptions) {
|
||||
configFile: false,
|
||||
publicDir: false,
|
||||
build: {
|
||||
rollupOptions: {
|
||||
rolldownOptions: {
|
||||
input: amdScriptsInput,
|
||||
output: {
|
||||
dir: buildOptions.outputDir,
|
||||
entryFileNames: '[name].js',
|
||||
chunkFileNames: 'chunks/[name]-[hash].js',
|
||||
// ManifestV3 doesn't allow to use modern ES modules syntax, so we build all content scripts as AMD modules.
|
||||
format: "amd",
|
||||
inlineDynamicImports: false,
|
||||
amd: {
|
||||
// amd-lite requires names even for the entry-point scripts, so we should make sure to add those.
|
||||
autoId: true,
|
||||
},
|
||||
// Vite 8 no longer have support for `amd` format extension depends on
|
||||
// TODO Make plugin to live-convert cjs module require/exports into AMD
|
||||
format: "cjs",
|
||||
codeSplitting: true,
|
||||
// All these modules are not intended to be used outside of extension anyway
|
||||
minifyInternalExports: true,
|
||||
}
|
||||
@@ -211,6 +209,7 @@ export async function buildScriptsAndStyles(buildOptions) {
|
||||
alias: aliasesSettings,
|
||||
},
|
||||
plugins: [
|
||||
ConvertCjsToAmd(),
|
||||
wrapScriptIntoIIFE(),
|
||||
collectDependenciesForManifestBuilding((fileName, dependencies) => {
|
||||
pathsReplacementByOutputPath
|
||||
@@ -228,7 +227,7 @@ export async function buildScriptsAndStyles(buildOptions) {
|
||||
configFile: false,
|
||||
publicDir: false,
|
||||
build: {
|
||||
rollupOptions: {
|
||||
rolldownOptions: {
|
||||
input: libsAndStylesInput,
|
||||
output: {
|
||||
dir: buildOptions.outputDir,
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* # CJS → AMD module format converter.
|
||||
*
|
||||
* Incredibly scary and potentially unstable way to bring back AMD modules on Vite 8+. Converts require() calls into
|
||||
* list of dependencies and forms define() function with module name, dependencies and exports.
|
||||
*
|
||||
* @return {import('vite').Plugin}
|
||||
*/
|
||||
export function ConvertCjsToAmd() {
|
||||
const requireAssignmentsRegExp = /(?:const\s*|,\s*)(?<variable>[a-z0-9_$]+)\s*=\s*require\((?<path>['"][^'"]+['"])\)/iy;
|
||||
const inlineRequireRegExp = /require\((?<path>['"][^'"]+['"])\)\.(?<variable>[a-z0-9_$]+)/gi
|
||||
const exportsDefinitionRegExp = /Object.defineProperty\(exports,['"](?<export_variable>[^'"]+)['"],{enumerable:!\d,get:function\(\){return\s*(?<assigned_variable>[^};]+)}}\)(?<separator>[,;])/gi;
|
||||
const exportVariablePrefix = "$";
|
||||
const exportVariableCollisionsRegExp = /\$[a-z_$]+/g;
|
||||
const amdExportsModule = '"exports"';
|
||||
|
||||
/**
|
||||
* Clears the name of the module to be fit with what we had before.
|
||||
* @param {string} path Path to normalize.
|
||||
* @returns {string} Normalized path.
|
||||
*/
|
||||
function normalizeDependencyName(path) {
|
||||
return path.replace(/\.js(['"])$/, "$1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Deduce the potentially unused variable from the current code. Uses special rarely encountered prefix.
|
||||
* @param {string} code Code to parse the used symbols from. Ideally, code should be passed here before any
|
||||
* replacements.
|
||||
* @param {Set<string>} usedSymbols Set of symbols which were already used or found in code.
|
||||
* @returns {string} Not-yet used variable which is likely safe to use.
|
||||
*/
|
||||
function findUnusedSpecialVariable(code, usedSymbols) {
|
||||
// Run complete scan of the source code first, to find any potential collisions.
|
||||
if (!usedSymbols.size) {
|
||||
let match;
|
||||
|
||||
exportVariableCollisionsRegExp.lastIndex = 0;
|
||||
|
||||
while (match = exportVariableCollisionsRegExp.exec(code)) {
|
||||
usedSymbols.add(match[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!usedSymbols.size || !usedSymbols.has(exportVariablePrefix)) {
|
||||
usedSymbols.add(exportVariablePrefix);
|
||||
return exportVariablePrefix;
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
let resultVariable;
|
||||
|
||||
do {
|
||||
resultVariable = exportVariablePrefix + count.toString(36);
|
||||
} while (count++ < 1000 && usedSymbols.has(resultVariable));
|
||||
|
||||
if (usedSymbols.has(resultVariable)) {
|
||||
throw new Error('Failed to convert CJS to AMD: Failed to find non-colliding variable after 100 tries!');
|
||||
}
|
||||
|
||||
usedSymbols.add(resultVariable);
|
||||
return resultVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function doing the conversion of one chunk.
|
||||
* @param {import('rolldown').OutputChunk} chunk
|
||||
*/
|
||||
function convertChunkToAmd(chunk) {
|
||||
/** @type {string} */
|
||||
let chunkCode = chunk.code;
|
||||
let lastRequireIndex = 0;
|
||||
/**
|
||||
* Saved per-chunk set of used symbols. This set is reused for multiple calls to not parse code multiple times.
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
const chunkUsedSymbols = new Set();
|
||||
|
||||
/** @type {Record<string, string>} */
|
||||
let dependenciesVarsToPaths = {};
|
||||
|
||||
// region Extracting `const x = require()` calls from the start of the source code...
|
||||
|
||||
do {
|
||||
requireAssignmentsRegExp.lastIndex = lastRequireIndex;
|
||||
const result = requireAssignmentsRegExp.exec(chunkCode);
|
||||
|
||||
if (!result) {
|
||||
break;
|
||||
}
|
||||
|
||||
dependenciesVarsToPaths[result.groups.variable] = normalizeDependencyName(result.groups.path);
|
||||
lastRequireIndex += result["0"].length;
|
||||
} while (true);
|
||||
|
||||
if (lastRequireIndex > 0) {
|
||||
const characterAfterRequires = chunkCode[lastRequireIndex];
|
||||
|
||||
if (characterAfterRequires !== ';') {
|
||||
throw new Error("Failed to convert CJS to AMD: reached last require() assignment, but list didn't stop.");
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Finding and replacing inlined `require().x` calls...
|
||||
|
||||
chunkCode = chunkCode.replaceAll(inlineRequireRegExp, (match, dependencyPath, variable) => {
|
||||
const dependencyVariable = findUnusedSpecialVariable(chunkCode, chunkUsedSymbols);
|
||||
dependenciesVarsToPaths[dependencyVariable] = dependencyPath;
|
||||
return `${dependencyVariable}.${variable}`;
|
||||
});
|
||||
|
||||
// endregion
|
||||
|
||||
// region Finding and replacing all exports with AMD exports...
|
||||
|
||||
/** @type {string|undefined} */
|
||||
let chunkExportsVariable;
|
||||
|
||||
exportsDefinitionRegExp.lastIndex = 0;
|
||||
|
||||
chunkCode = chunkCode.replaceAll(exportsDefinitionRegExp, (substring, exportVariable, assignedVariable, separator) => {
|
||||
chunkExportsVariable ??= findUnusedSpecialVariable(chunkCode, chunkUsedSymbols);
|
||||
|
||||
if (!(chunkExportsVariable in dependenciesVarsToPaths)) {
|
||||
dependenciesVarsToPaths = {
|
||||
[chunkExportsVariable]: amdExportsModule,
|
||||
...dependenciesVarsToPaths,
|
||||
};
|
||||
}
|
||||
|
||||
return `${chunkExportsVariable}.${exportVariable}=${assignedVariable}${separator}`;
|
||||
});
|
||||
|
||||
// endregion
|
||||
|
||||
const normalizedModuleName = normalizeDependencyName(`"${chunk.fileName}"`);
|
||||
const dependenciesVariables = Object.keys(dependenciesVarsToPaths).join(',');
|
||||
const dependenciesPaths = Object.values(dependenciesVarsToPaths).join(',');
|
||||
|
||||
if (lastRequireIndex > 0) {
|
||||
chunkCode = chunkCode.substring(lastRequireIndex + 1);
|
||||
}
|
||||
|
||||
chunk.code = `define(${normalizedModuleName},[${dependenciesPaths}],function(${dependenciesVariables}){${chunkCode}})`;
|
||||
}
|
||||
|
||||
return {
|
||||
name: "koloml:covert-cjs-to-amd",
|
||||
apply: "build",
|
||||
enforce: "pre",
|
||||
|
||||
/**
|
||||
* @param _
|
||||
* @param {Record<string, (import('rolldown').OutputBundle|import('rolldown').OutputChunk)>} bundle
|
||||
*/
|
||||
generateBundle(_, bundle) {
|
||||
for (const chunkId in bundle) {
|
||||
const chunkOrAsset = bundle[chunkId];
|
||||
|
||||
if (chunkOrAsset.type === 'asset') {
|
||||
continue;
|
||||
}
|
||||
|
||||
convertChunkToAmd(chunkOrAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+489
-760
File diff suppressed because it is too large.
Load diff
+2
-2
@@ -24,7 +24,7 @@
|
||||
"svelte": "^5.57.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||
"@sveltejs/vite-plugin-svelte": "^7.3.1",
|
||||
"@types/chrome": "^0.3.5",
|
||||
"@types/node": "^25.9.9",
|
||||
"@vitest/coverage-v8": "^4.1.11",
|
||||
@@ -33,7 +33,7 @@
|
||||
"jsdom": "^29.1.1",
|
||||
"svelte-check": "^4.7.6",
|
||||
"typescript": "^6.0.3",
|
||||
"vite": "^7.3.7",
|
||||
"vite": "^8.3.4",
|
||||
"vitest": "^4.1.11"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -77,7 +77,7 @@ export class BaseComponent<ContainerType extends HTMLElement = HTMLElement> {
|
||||
): () => void {
|
||||
this.#container.addEventListener(event, listener, options);
|
||||
|
||||
return () => this.#container.removeEventListener(event, listener, options);
|
||||
return () => void this.#container.removeEventListener(event, listener, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,15 +11,15 @@ import type { TaggingProfilePopup } from "$content/components/extension/profiles
|
||||
|
||||
export class FullscreenViewer extends BaseComponent {
|
||||
#currentMediaBox: MediaBox | null = null;
|
||||
readonly #videoElement: HTMLVideoElement = document.createElement('video');
|
||||
readonly #imageElement: HTMLImageElement = document.createElement('img');
|
||||
readonly #spinnerElement: HTMLElement = document.createElement('i');
|
||||
readonly #sizeSelectorElement: HTMLSelectElement = document.createElement('select');
|
||||
readonly #closeButtonElement: HTMLElement = document.createElement('i');
|
||||
readonly #tagsPopupElement: HTMLElement = document.createElement('div');
|
||||
readonly #imageTagsToggler: TagsListToggler = TagsListToggler.create();
|
||||
readonly #profileTagsToggler: TagsListToggler = TagsListToggler.create();
|
||||
readonly #tagsPopupHider: HTMLElement = document.createElement('div');
|
||||
#videoElement: HTMLVideoElement = document.createElement('video');
|
||||
#imageElement: HTMLImageElement = document.createElement('img');
|
||||
#spinnerElement: HTMLElement = document.createElement('i');
|
||||
#sizeSelectorElement: HTMLSelectElement = document.createElement('select');
|
||||
#closeButtonElement: HTMLElement = document.createElement('i');
|
||||
#tagsPopupElement: HTMLElement = document.createElement('div');
|
||||
#imageTagsToggler: TagsListToggler = TagsListToggler.create();
|
||||
#profileTagsToggler: TagsListToggler = TagsListToggler.create();
|
||||
#tagsPopupHider: HTMLElement = document.createElement('div');
|
||||
#activeProfileListenerUnsubscriber: UnsubscribeFunction | null = null;
|
||||
#touchId: number | null = null;
|
||||
#startX: number | null = null;
|
||||
@@ -412,7 +412,7 @@ export class FullscreenViewer extends BaseComponent {
|
||||
}
|
||||
|
||||
#togglePopupVisibility(maybeState: boolean | undefined = undefined) {
|
||||
if (maybeState === undefined) {
|
||||
if (typeof maybeState === 'undefined') {
|
||||
const isHidden = this.#tagsPopupElement.classList.toggle(FullscreenViewer.#collapsedPopupState);
|
||||
void FullscreenViewer.#preferences.fullscreenViewerPopupShown.set(!isHidden);
|
||||
return;
|
||||
@@ -425,21 +425,21 @@ export class FullscreenViewer extends BaseComponent {
|
||||
return url.endsWith('.mp4') || url.endsWith('.webm');
|
||||
}
|
||||
|
||||
static readonly #preferences = new MiscPreferences();
|
||||
static #preferences = new MiscPreferences();
|
||||
|
||||
static readonly #offsetProperty = '--offset';
|
||||
static readonly #opacityProperty = '--opacity';
|
||||
static readonly #shownState = 'shown';
|
||||
static readonly #swipeState = 'swiped';
|
||||
static readonly #minRequiredDistance = 50;
|
||||
static readonly #collapsedPopupState = 'is-collapsed';
|
||||
static #offsetProperty = '--offset';
|
||||
static #opacityProperty = '--opacity';
|
||||
static #shownState = 'shown';
|
||||
static #swipeState = 'swiped';
|
||||
static #minRequiredDistance = 50;
|
||||
static #collapsedPopupState = 'is-collapsed';
|
||||
|
||||
static readonly #previewSizes: Record<FullscreenViewerSize, string> = {
|
||||
static #previewSizes: Record<FullscreenViewerSize, string> = {
|
||||
full: 'Full',
|
||||
large: 'Large',
|
||||
medium: 'Medium',
|
||||
small: 'Small'
|
||||
}
|
||||
|
||||
static readonly #fallbackSize = 'large';
|
||||
static #fallbackSize = 'large';
|
||||
}
|
||||
@@ -81,5 +81,5 @@ export class ImageShowFullscreenButton extends BaseComponent {
|
||||
return viewer;
|
||||
}
|
||||
|
||||
static readonly #preferences = new MiscPreferences();
|
||||
static #preferences = new MiscPreferences();
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import { createFontAwesomeIcon } from "$lib/dom-utils";
|
||||
import { sortEntitiesByField } from "$lib/utils";
|
||||
|
||||
export default class EditorPresetsBlock extends BaseComponent {
|
||||
readonly #presetsTable = document.createElement('table');
|
||||
readonly #presetBlocks: PresetTableRow[] = [];
|
||||
#presetsTable = document.createElement('table');
|
||||
#presetBlocks: PresetTableRow[] = [];
|
||||
#tags: Set<string> = new Set();
|
||||
|
||||
protected build() {
|
||||
|
||||
@@ -207,6 +207,6 @@ export default class PresetTableRow extends BaseComponent {
|
||||
return new this(document.createElement('tr'), preset);
|
||||
}
|
||||
|
||||
static readonly #tagMissingClassName = 'is-missing';
|
||||
static readonly #presetWarningClassName = 'has-warning';
|
||||
static #tagMissingClassName = 'is-missing';
|
||||
static #presetWarningClassName = 'has-warning';
|
||||
}
|
||||
@@ -16,14 +16,14 @@ import { EVENT_TAG_TOGGLED } from "$content/components/events/tags-list-toggler-
|
||||
|
||||
|
||||
export class TaggingProfilePopup extends BaseComponent {
|
||||
readonly #tagsListToggler = TagsListToggler.create();
|
||||
#tagsListToggler = TagsListToggler.create();
|
||||
#activeProfile: TaggingProfile | null = null;
|
||||
#mediaBoxTools: MediaBoxTools | null = null;
|
||||
#isSubmissionLocked: boolean = false;
|
||||
#isPlanningToSubmit: boolean = false;
|
||||
#isSubmitting: boolean = false;
|
||||
#tagsSubmissionTimer: Timeout | null = null;
|
||||
readonly #emitter = emitterAt(this);
|
||||
#emitter = emitterAt(this);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
@@ -211,7 +211,7 @@ export class TaggingProfilePopup extends BaseComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#tagsListToggler.prependTags(tagsBlacklist.filter(tagName => activeTags.has(tagName)), activeTags);
|
||||
this.#tagsListToggler.prependTags(tagsBlacklist, activeTags);
|
||||
}
|
||||
|
||||
static create(): HTMLElement {
|
||||
@@ -226,7 +226,7 @@ export class TaggingProfilePopup extends BaseComponent {
|
||||
/**
|
||||
* Controller with maintenance settings.
|
||||
*/
|
||||
static readonly #preferences = new TaggingProfilesPreferences();
|
||||
static #preferences = new TaggingProfilesPreferences();
|
||||
|
||||
/**
|
||||
* Subscribe to all necessary feeds to watch for every active profile change. Additionally, will execute the callback
|
||||
@@ -298,9 +298,9 @@ export class TaggingProfilePopup extends BaseComponent {
|
||||
});
|
||||
}
|
||||
|
||||
static readonly #scrapedAPI = new ScrapedAPI();
|
||||
static #scrapedAPI = new ScrapedAPI();
|
||||
|
||||
static readonly #delayBeforeSubmissionMs = 500;
|
||||
static #delayBeforeSubmissionMs = 500;
|
||||
|
||||
/**
|
||||
* Amount of pending submissions or NULL if logic was not yet initialized.
|
||||
|
||||
@@ -10,7 +10,6 @@ export default class TagsListToggler extends BaseComponent {
|
||||
#invalidTagsList: Map<string, HTMLElement> = new Map();
|
||||
#tagsToAdd: Set<string> = new Set();
|
||||
#tagsToRemove: Set<string> = new Set();
|
||||
#renderedTags: Set<string> = new Set();
|
||||
|
||||
protected build() {
|
||||
this.container.classList.add('tags-list');
|
||||
@@ -35,7 +34,6 @@ export default class TagsListToggler extends BaseComponent {
|
||||
|
||||
this.#tagsList = [];
|
||||
this.#invalidTagsList = new Map();
|
||||
this.#renderedTags = new Set();
|
||||
|
||||
this.#renderAndInsertTags(tags, activeTags);
|
||||
}
|
||||
@@ -60,18 +58,14 @@ export default class TagsListToggler extends BaseComponent {
|
||||
#renderAndInsertTags(toggleableTags: string[], activeTags: Set<string>, shouldPrepend: boolean = false) {
|
||||
toggleableTags.sort((a, b) => a.localeCompare(b));
|
||||
|
||||
let lastInserted: HTMLElement | null = null;
|
||||
let lastInserted: HTMLElement|null = null;
|
||||
|
||||
const hasStoredChanges = this.hasChanges;
|
||||
|
||||
for (const tagName of toggleableTags) {
|
||||
if (this.#renderedTags.has(tagName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.#renderedTags.add(tagName);
|
||||
|
||||
for (let tagIndex = 0; tagIndex < toggleableTags.length; tagIndex++) {
|
||||
const tagName = toggleableTags[tagIndex];
|
||||
const tagElement = TagsListToggler.#buildTagElement(tagName);
|
||||
|
||||
this.#tagsList.push(tagElement);
|
||||
|
||||
const isPresent = activeTags.has(tagName);
|
||||
@@ -212,6 +206,7 @@ export default class TagsListToggler extends BaseComponent {
|
||||
*/
|
||||
static #markTagElementWithCategory(tagElement: HTMLElement, category: string) {
|
||||
tagElement.dataset.tagCategory = category;
|
||||
tagElement.setAttribute('data-tag-category', category);
|
||||
}
|
||||
|
||||
static create(): TagsListToggler {
|
||||
@@ -219,11 +214,11 @@ export default class TagsListToggler extends BaseComponent {
|
||||
return new TagsListToggler(tagsListContainer);
|
||||
}
|
||||
|
||||
static readonly #containsClass = 'is-present';
|
||||
static readonly #missingClass = 'is-missing';
|
||||
static #containsClass = 'is-present';
|
||||
static #missingClass = 'is-missing';
|
||||
|
||||
static readonly #addedClass = 'is-added';
|
||||
static readonly #removedClass = 'is-removed';
|
||||
static #addedClass = 'is-added';
|
||||
static #removedClass = 'is-removed';
|
||||
}
|
||||
|
||||
export class BlackListedTagsEncounteredError extends Error {
|
||||
|
||||
@@ -112,14 +112,14 @@ export class BlockCommunication extends BaseComponent {
|
||||
);
|
||||
}
|
||||
|
||||
static readonly #preferences = new TagsPreferences();
|
||||
static #preferences = new TagsPreferences();
|
||||
|
||||
/**
|
||||
* Map of links to their original texts. These texts need to be stored here to make them restorable. Keys is a link
|
||||
* element and value is a text.
|
||||
* @private
|
||||
*/
|
||||
static readonly #originalTagLinkTexts: WeakMap<HTMLElement, string> = new WeakMap();
|
||||
static #originalTagLinkTexts: WeakMap<HTMLElement, string> = new WeakMap();
|
||||
|
||||
static findAndInitializeAll() {
|
||||
for (const container of document.querySelectorAll<HTMLElement>('.block.communication')) {
|
||||
|
||||
@@ -88,12 +88,14 @@ export class TagDropdown extends BaseComponent {
|
||||
// Make sure original category is properly stored.
|
||||
this.originalCategory;
|
||||
|
||||
this.container.dataset.tagCategory = targetCategory;
|
||||
|
||||
if (targetCategory) {
|
||||
this.container.dataset.tagCategory = targetCategory;
|
||||
this.container.setAttribute('data-tag-category', targetCategory);
|
||||
return;
|
||||
}
|
||||
|
||||
delete this.container.dataset.tagCategory;
|
||||
this.container.removeAttribute('data-tag-category');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +203,7 @@ export class TagDropdown extends BaseComponent {
|
||||
await this.#activeProfile.save();
|
||||
}
|
||||
|
||||
static readonly #preferences = new TaggingProfilesPreferences();
|
||||
static #preferences = new TaggingProfilesPreferences();
|
||||
|
||||
/**
|
||||
* Watch for changes to active profile.
|
||||
@@ -260,8 +262,8 @@ export class TagDropdown extends BaseComponent {
|
||||
return dropdownLink;
|
||||
}
|
||||
|
||||
static readonly #categoriesResolver = new CustomCategoriesResolver();
|
||||
static readonly #processedElements: WeakSet<HTMLElement> = new WeakSet();
|
||||
static #categoriesResolver = new CustomCategoriesResolver();
|
||||
static #processedElements: WeakSet<HTMLElement> = new WeakSet();
|
||||
|
||||
static #findAll(parentNode: ParentNode = document): NodeListOf<HTMLElement> {
|
||||
return parentNode.querySelectorAll('.tag.dropdown');
|
||||
|
||||
@@ -7,8 +7,8 @@ import EditorPresetsBlock from "$content/components/extension/presets/EditorPres
|
||||
import { EVENT_PRESET_TAG_CHANGE_APPLIED, type PresetTagChange } from "$content/components/events/preset-block-events";
|
||||
|
||||
export class TagsForm extends BaseComponent {
|
||||
readonly #togglePresetsButton: HTMLButtonElement = document.createElement('button');
|
||||
readonly #presetsList = EditorPresetsBlock.create();
|
||||
#togglePresetsButton: HTMLButtonElement = document.createElement('button');
|
||||
#presetsList = EditorPresetsBlock.create();
|
||||
#plainEditorTextarea: HTMLTextAreaElement | null = null;
|
||||
#fancyEditorInput: HTMLInputElement | null = null;
|
||||
#tagsSet: Set<string> = new Set();
|
||||
@@ -127,6 +127,7 @@ export class TagsForm extends BaseComponent {
|
||||
const categoryName = tagCategories.get(tagName)!;
|
||||
|
||||
tagElement.dataset.tagCategory = categoryName;
|
||||
tagElement.setAttribute('data-tag-category', categoryName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ export default class DupeDiff extends BaseComponent {
|
||||
*
|
||||
* Keys are the icons and values are the patterns extension should check for each URL.
|
||||
*/
|
||||
static readonly #iconsToPatternsMap = new Map<string[] | string, string[] | string>([
|
||||
static #iconsToPatternsMap = new Map<string[] | string, string[] | string>([
|
||||
[
|
||||
['artstation', brandsSubtype],
|
||||
'artstation.com'
|
||||
|
||||
@@ -4,9 +4,9 @@ import DupeImage from "$content/components/philomena/dupe/DupeImage";
|
||||
import { ratingTags } from "$config/tags";
|
||||
|
||||
export default class DupeReportRow extends BaseComponent {
|
||||
readonly #leftImage: DupeImage;
|
||||
readonly #rightImage: DupeImage;
|
||||
readonly #difference: DupeDiff;
|
||||
#leftImage: DupeImage;
|
||||
#rightImage: DupeImage;
|
||||
#difference: DupeDiff;
|
||||
|
||||
constructor(leftCell: HTMLElement, rightCell: HTMLElement, diffCell: HTMLElement, reportOptions: HTMLElement) {
|
||||
super(reportOptions);
|
||||
|
||||
@@ -2,8 +2,8 @@ import { BaseComponent } from "$content/components/base/BaseComponent";
|
||||
|
||||
export class ImageListInfo extends BaseComponent {
|
||||
#tagElement: HTMLElement | null = null;
|
||||
readonly #impliedTags: string[] = [];
|
||||
readonly #showUntaggedImplicationsButton: HTMLAnchorElement = document.createElement('a');
|
||||
#impliedTags: string[] = [];
|
||||
#showUntaggedImplicationsButton: HTMLAnchorElement = document.createElement('a');
|
||||
|
||||
protected build() {
|
||||
const sectionAfterImage = this.container.querySelector('.tag-info__image + .flex__grow');
|
||||
@@ -71,5 +71,5 @@ export class ImageListInfo extends BaseComponent {
|
||||
location.assign(url.href);
|
||||
}
|
||||
|
||||
static readonly #implicationsStarterText = 'Implies:';
|
||||
static #implicationsStarterText = 'Implies:';
|
||||
}
|
||||
@@ -38,7 +38,7 @@ amdLite.define = (name, dependencies, originalCallback) => {
|
||||
|
||||
// Workaround for the entry script not returning anything causing AMD-Lite to send warning about modules not
|
||||
// being loaded/not existing.
|
||||
return callbackResult !== undefined ? callbackResult : {};
|
||||
return typeof callbackResult !== 'undefined' ? callbackResult : {};
|
||||
});
|
||||
|
||||
// Schedule the auto run on the next available frame. Firefox and Chromium have a lot of differences in how they
|
||||
|
||||
@@ -101,7 +101,7 @@ export default class BulkEntitiesTransporter {
|
||||
&& Array.isArray(targetObject.elements);
|
||||
}
|
||||
|
||||
static readonly #transporters: TransportersMapping = {
|
||||
static #transporters: TransportersMapping = {
|
||||
profiles: new EntitiesTransporter(TaggingProfile),
|
||||
groups: new EntitiesTransporter(TagGroup),
|
||||
presets: new EntitiesTransporter(TagEditorPreset),
|
||||
|
||||
@@ -5,9 +5,9 @@ import { emit } from "$content/components/events/comms";
|
||||
import { EVENT_TAG_GROUP_RESOLVED } from "$content/components/events/tag-dropdown-events";
|
||||
|
||||
export default class CustomCategoriesResolver {
|
||||
readonly #exactGroupMatches = new Map<string, TagGroup>();
|
||||
readonly #regExpGroupMatches = new Map<RegExp, TagGroup>();
|
||||
readonly #tagDropdowns: TagDropdown[] = [];
|
||||
#exactGroupMatches = new Map<string, TagGroup>();
|
||||
#regExpGroupMatches = new Map<RegExp, TagGroup>();
|
||||
#tagDropdowns: TagDropdown[] = [];
|
||||
#nextQueuedUpdate: Timeout | null = null;
|
||||
|
||||
constructor() {
|
||||
@@ -125,5 +125,5 @@ export default class CustomCategoriesResolver {
|
||||
);
|
||||
}
|
||||
|
||||
static readonly #unprocessedTagsTimeout = 0;
|
||||
static #unprocessedTagsTimeout = 0;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { validateImportedEntity } from "$lib/extension/transporting/validators";
|
||||
import { exportEntityToObject } from "$lib/extension/transporting/exporters";
|
||||
import StorageEntity from "$lib/extension/base/StorageEntity";
|
||||
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from "lz-string";
|
||||
import type { ImportableElement } from "$lib/extension/transporting/importables";
|
||||
|
||||
/**
|
||||
* Status of the last import.
|
||||
|
||||
@@ -78,5 +78,5 @@ export default class PostParser extends PageParser {
|
||||
);
|
||||
}
|
||||
|
||||
static readonly tagsInputName = 'image[tag_input]';
|
||||
static tagsInputName = 'image[tag_input]';
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import { ScssViteReadEnvVariableFunctionPlugin } from "./.vite/plugins/scss-read-env-variable-function";
|
||||
import { SwapDefinedVariablesPlugin } from "./.vite/plugins/swap-defined-variables";
|
||||
import { ScssViteReadEnvVariableFunctionPlugin } from "./.vite/plugins/scss-read-env-variable-function.js";
|
||||
import { SwapDefinedVariablesPlugin } from "./.vite/plugins/swap-defined-variables.js";
|
||||
|
||||
export default defineConfig(() => {
|
||||
return {
|
||||
|
||||
Reference in new issue
Block a user