mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
Convert to consistently use JS modules (#6854)
# Description of Changes Modernises the codebase and gets rid of warnings where Node complains that it doesn't know what type of JS it's supposed to be reading on `.js` files. We might as well update everything to just use correct JS syntax instead of keeping with some files having Node-specific imports.
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: [require("@tailwindcss/postcss"), require("autoprefixer")],
|
||||
import tailwindcssPostcss from "@tailwindcss/postcss";
|
||||
import autoprefixer from "autoprefixer";
|
||||
|
||||
export default {
|
||||
plugins: [tailwindcssPostcss, autoprefixer],
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { icons } = require("@iconify-json/material-symbols");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
import { icons } from "@iconify-json/material-symbols";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
// Check for verbose flag
|
||||
const isVerbose =
|
||||
@@ -19,7 +19,7 @@ const debug = (message) => {
|
||||
// Function to scan codebase for LocalIcon usage
|
||||
function scanForUsedIcons() {
|
||||
const usedIcons = new Set();
|
||||
const srcDir = path.join(__dirname, "..", "src");
|
||||
const srcDir = path.join(import.meta.dirname, "..", "src");
|
||||
|
||||
info("🔍 Scanning codebase for LocalIcon usage...");
|
||||
|
||||
@@ -140,7 +140,7 @@ async function main() {
|
||||
|
||||
// Check if we need to regenerate (compare with existing)
|
||||
const outputPath = path.join(
|
||||
__dirname,
|
||||
import.meta.dirname,
|
||||
"..",
|
||||
"src",
|
||||
"assets",
|
||||
@@ -200,7 +200,7 @@ async function main() {
|
||||
}
|
||||
|
||||
// Create output directory
|
||||
const outputDir = path.join(__dirname, "..", "src", "assets");
|
||||
const outputDir = path.join(import.meta.dirname, "..", "src", "assets");
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { execSync } = require("node:child_process");
|
||||
const {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
writeFileSync,
|
||||
readFileSync,
|
||||
} = require("node:fs");
|
||||
const path = require("node:path");
|
||||
import { execSync } from "node:child_process";
|
||||
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { argv } from "node:process";
|
||||
|
||||
const { argv } = require("node:process");
|
||||
const inputIdx = argv.indexOf("--input");
|
||||
const INPUT_FILE = inputIdx > -1 ? argv[inputIdx + 1] : null;
|
||||
const POSTPROCESS_ONLY = !!INPUT_FILE;
|
||||
|
||||
// __dirname is available in CommonJS by default
|
||||
|
||||
/**
|
||||
* Generate 3rd party licenses for frontend dependencies
|
||||
* This script creates a JSON file similar to the Java backend's 3rdPartyLicenses.json
|
||||
*/
|
||||
|
||||
const OUTPUT_FILE = path.join(
|
||||
__dirname,
|
||||
import.meta.dirname,
|
||||
"..",
|
||||
"src",
|
||||
"assets",
|
||||
@@ -30,7 +23,7 @@ const OUTPUT_FILE = path.join(
|
||||
);
|
||||
// package.json lives at the workspace root (frontend/), not editor/. The
|
||||
// script is at frontend/editor/scripts/, so walk up two levels.
|
||||
const PACKAGE_JSON = path.join(__dirname, "..", "..", "package.json");
|
||||
const PACKAGE_JSON = path.join(import.meta.dirname, "..", "..", "package.json");
|
||||
|
||||
// Ensure the output directory exists
|
||||
const outputDir = path.dirname(OUTPUT_FILE);
|
||||
@@ -192,7 +185,7 @@ try {
|
||||
|
||||
// Write license warnings to a separate file for CI/CD
|
||||
const warningsFile = path.join(
|
||||
__dirname,
|
||||
import.meta.dirname,
|
||||
"..",
|
||||
"src",
|
||||
"assets",
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
/* global document, getComputedStyle */ // used inside page.evaluate (browser context)
|
||||
|
||||
import fs from "node:fs/promises";
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createRequire } from "node:module";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = path.resolve(HERE, "..");
|
||||
|
||||
@@ -69,11 +68,14 @@ export const THEME = {
|
||||
};
|
||||
|
||||
// ---- icon resolution (material-symbols via iconify) ------------------------
|
||||
function resolveIcon(icon) {
|
||||
async function resolveIcon(icon) {
|
||||
if (!icon) return "";
|
||||
if (icon.trim().startsWith("<svg")) return icon; // raw svg passed through
|
||||
const { getIconData, iconToSVG } = require("@iconify/utils");
|
||||
const set = require("@iconify-json/material-symbols/icons.json");
|
||||
const { getIconData, iconToSVG } = await import("@iconify/utils");
|
||||
const { default: set } = await import(
|
||||
"@iconify-json/material-symbols/icons.json",
|
||||
{ with: { type: "json" } }
|
||||
);
|
||||
const data = getIconData(set, icon);
|
||||
if (!data) throw new Error(`icon not found in material-symbols: "${icon}"`);
|
||||
const { attributes, body } = iconToSVG(data);
|
||||
@@ -148,7 +150,7 @@ const escapeHtml = (s) =>
|
||||
let _browser = null;
|
||||
async function getBrowser() {
|
||||
if (_browser) return _browser;
|
||||
const puppeteer = require("puppeteer");
|
||||
const { default: puppeteer } = await import("puppeteer");
|
||||
_browser = await puppeteer.launch({
|
||||
headless: "new",
|
||||
args: ["--no-sandbox"],
|
||||
@@ -163,7 +165,7 @@ export async function renderOgCard({
|
||||
outFile,
|
||||
theme = THEME,
|
||||
}) {
|
||||
const iconSvg = resolveIcon(icon);
|
||||
const iconSvg = await resolveIcon(icon);
|
||||
const html = await buildHtml({ name, description, iconSvg, theme });
|
||||
const browser = await getBrowser();
|
||||
const page = await browser.newPage();
|
||||
@@ -230,7 +232,7 @@ const kebab = (id) => id.replace(/([A-Z])/g, "-$1").toLowerCase();
|
||||
|
||||
// English name/description live next to each tool as the `t(key, fallback)` default.
|
||||
function readRegistryStrings() {
|
||||
const src = require("node:fs").readFileSync(
|
||||
const src = readFileSync(
|
||||
path.join(ROOT, "src/core/data/useTranslatedToolRegistry.tsx"),
|
||||
"utf8",
|
||||
);
|
||||
@@ -268,7 +270,7 @@ export async function generateMissing(theme = THEME) {
|
||||
// Each tool's app icon lives as `icon="<material-symbol>"` just before its
|
||||
// `name: t("home.<id>.title", …)`. Pair each title with the closest preceding icon.
|
||||
function readRegistryIcons() {
|
||||
const src = require("node:fs").readFileSync(
|
||||
const src = readFileSync(
|
||||
path.join(ROOT, "src/core/data/useTranslatedToolRegistry.tsx"),
|
||||
"utf8",
|
||||
);
|
||||
@@ -288,25 +290,26 @@ function readRegistryIcons() {
|
||||
return byId;
|
||||
}
|
||||
|
||||
function iconExists(name) {
|
||||
async function iconExists(name) {
|
||||
if (!name) return false;
|
||||
try {
|
||||
const { getIconData } = require("@iconify/utils");
|
||||
return !!getIconData(
|
||||
require("@iconify-json/material-symbols/icons.json"),
|
||||
name,
|
||||
const { getIconData } = await import("@iconify/utils");
|
||||
const { default: set } = await import(
|
||||
"@iconify-json/material-symbols/icons.json",
|
||||
{ with: { type: "json" } }
|
||||
);
|
||||
return !!getIconData(set, name);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// First candidate that resolves; also tries dropping a "-rounded" suffix.
|
||||
function firstResolvableIcon(candidates) {
|
||||
async function firstResolvableIcon(candidates) {
|
||||
for (const c of candidates) {
|
||||
if (iconExists(c)) return c;
|
||||
if (await iconExists(c)) return c;
|
||||
const alt = c && c.replace(/-rounded$/, "");
|
||||
if (alt && alt !== c && iconExists(alt)) return alt;
|
||||
if (alt && alt !== c && (await iconExists(alt))) return alt;
|
||||
}
|
||||
return "description-outline";
|
||||
}
|
||||
@@ -324,14 +327,14 @@ export async function generateAll(theme = THEME) {
|
||||
const { titles, descs } = readRegistryStrings();
|
||||
const regIcons = readRegistryIcons();
|
||||
const ogMap = JSON.parse(
|
||||
require("node:fs").readFileSync(
|
||||
path.join(ROOT, "src/core/data/ogImageMap.json"),
|
||||
"utf8",
|
||||
),
|
||||
readFileSync(path.join(ROOT, "src/core/data/ogImageMap.json"), "utf8"),
|
||||
);
|
||||
const results = [];
|
||||
for (const [id, basename] of Object.entries(ogMap)) {
|
||||
const icon = firstResolvableIcon([regIcons[id], MISSING_TOOL_ICONS[id]]);
|
||||
const icon = await firstResolvableIcon([
|
||||
regIcons[id],
|
||||
MISSING_TOOL_ICONS[id],
|
||||
]);
|
||||
await renderOgCard({
|
||||
name: titles[id] || humanizeId(id),
|
||||
description: descs[id] || "",
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "@app/tests/helpers/ui-helpers";
|
||||
import path from "path";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const ENCRYPTED_PDF = path.join(FIXTURES_DIR, "encrypted.pdf");
|
||||
const SAMPLE_PDF = path.join(FIXTURES_DIR, "sample.pdf");
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ import { test, expect } from "@app/tests/helpers/stub-test-base";
|
||||
import { uploadFiles } from "@app/tests/helpers/ui-helpers";
|
||||
import path from "path";
|
||||
|
||||
const SAMPLE_PDF = path.join(__dirname, "../test-fixtures/sample.pdf");
|
||||
const SAMPLE_PDF = path.join(
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/sample.pdf",
|
||||
);
|
||||
|
||||
/**
|
||||
* Add Page Numbers walks the user through a multi-step config: position
|
||||
|
||||
@@ -2,7 +2,10 @@ import { test, expect } from "@app/tests/helpers/stub-test-base";
|
||||
import { uploadFiles } from "@app/tests/helpers/ui-helpers";
|
||||
import path from "path";
|
||||
|
||||
const SAMPLE_PDF = path.join(__dirname, "../test-fixtures/sample.pdf");
|
||||
const SAMPLE_PDF = path.join(
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/sample.pdf",
|
||||
);
|
||||
|
||||
/**
|
||||
* AddStamp loads, accepts a PDF upload, and remains interactive.
|
||||
|
||||
@@ -3,7 +3,7 @@ import { uploadFiles } from "@app/tests/helpers/ui-helpers";
|
||||
import type { Page, Route } from "@playwright/test";
|
||||
import path from "path";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const SAMPLE_PDF = path.join(FIXTURES_DIR, "sample.pdf");
|
||||
|
||||
// app-config the desktop bundle would return: hardware signing is offered only there.
|
||||
|
||||
@@ -5,7 +5,7 @@ import { suppressNativeFilePicker } from "@app/tests/helpers/ui-helpers";
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test fixtures — pre-generated keystores in test-fixtures/certs/
|
||||
// ---------------------------------------------------------------------------
|
||||
const CERTS_DIR = path.join(__dirname, "../test-fixtures/certs");
|
||||
const CERTS_DIR = path.join(import.meta.dirname, "../test-fixtures/certs");
|
||||
const VALID_P12 = path.join(CERTS_DIR, "valid-test.p12");
|
||||
const EXPIRED_P12 = path.join(CERTS_DIR, "expired-test.p12");
|
||||
const NOT_YET_VALID_P12 = path.join(CERTS_DIR, "not-yet-valid-test.p12");
|
||||
|
||||
@@ -2,7 +2,7 @@ import { test, expect } from "@app/tests/helpers/stub-test-base";
|
||||
import path from "path";
|
||||
|
||||
const ANNOTATED_PDF = path.join(
|
||||
__dirname,
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/annotations_out_of_order.pdf",
|
||||
);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { test, expect, type Page } from "@playwright/test";
|
||||
import path from "path";
|
||||
import { mockAppApis } from "@app/tests/helpers/api-stubs";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const PDF_A = path.join(FIXTURES_DIR, "compare_sample_a.pdf");
|
||||
const PDF_B = path.join(FIXTURES_DIR, "compare_sample_b.pdf");
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import path from "path";
|
||||
import { mockAppApis } from "@app/tests/helpers/api-stubs";
|
||||
import { suppressNativeFilePicker } from "@app/tests/helpers/ui-helpers";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const SAMPLE_PDF = path.join(FIXTURES_DIR, "sample.pdf");
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -23,7 +23,7 @@ import fs from "fs";
|
||||
import { mockAppApis } from "@app/tests/helpers/api-stubs";
|
||||
import { suppressNativeFilePicker } from "@app/tests/helpers/ui-helpers";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const ENCRYPTED_PDF = path.join(FIXTURES_DIR, "encrypted.pdf");
|
||||
|
||||
const FAKE_UNLOCKED_PDF = Buffer.from(
|
||||
|
||||
@@ -2,7 +2,7 @@ import { test, expect } from "@app/tests/helpers/stub-test-base";
|
||||
import { uploadFiles } from "@app/tests/helpers/ui-helpers";
|
||||
import path from "path";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const SAMPLE_PDF = path.join(FIXTURES_DIR, "sample.pdf");
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,7 @@ import fs from "fs";
|
||||
// `result.zip` instead of the merged file. The UI fix uses signature-based
|
||||
// detection - %PDF wins regardless of Content-Type.
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const SAMPLE_PDF = path.join(FIXTURES_DIR, "sample.pdf");
|
||||
const SAMPLE_PDF_BYTES = fs.readFileSync(SAMPLE_PDF);
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ import { uploadFiles, dismissTourTooltip } from "@app/tests/helpers/ui-helpers";
|
||||
// Fixture: 4 portrait pages whose intrinsic /Rotate is 0, 90, 270, 180.
|
||||
// Page 3 (index 2) is 270 so a single rotate-right lands on a net-0 target -
|
||||
// the exact case the export used to drop, leaving the source rotation behind.
|
||||
const ROTATED_PDF = path.join(__dirname, "../test-fixtures/rotated-pages.pdf");
|
||||
const ROTATED_PDF = path.join(
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/rotated-pages.pdf",
|
||||
);
|
||||
const SOURCE_ROTATIONS = [0, 90, 270, 180];
|
||||
|
||||
/** Read the rotation each thumbnail is currently displaying (= page.rotation). */
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { test, expect } from "@app/tests/helpers/stub-test-base";
|
||||
import path from "path";
|
||||
|
||||
const SAMPLE_PDF = path.join(__dirname, "../test-fixtures/sample.pdf");
|
||||
const SAMPLE_PDF = path.join(
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/sample.pdf",
|
||||
);
|
||||
|
||||
/**
|
||||
* The reader/viewer exposes an in-PDF text search via CustomSearchLayer.
|
||||
|
||||
@@ -22,7 +22,14 @@ function resolveFixturePath(filename: string): string {
|
||||
filename,
|
||||
),
|
||||
path.join(process.cwd(), "src", "core", "tests", "test-fixtures", filename),
|
||||
path.join(__dirname, "..", "core", "tests", "test-fixtures", filename),
|
||||
path.join(
|
||||
import.meta.dirname,
|
||||
"..",
|
||||
"core",
|
||||
"tests",
|
||||
"test-fixtures",
|
||||
filename,
|
||||
),
|
||||
];
|
||||
for (const p of candidates) {
|
||||
if (fs.existsSync(p)) return p;
|
||||
|
||||
@@ -17,7 +17,10 @@ import { uploadFiles, openSettings } from "@app/tests/helpers/ui-helpers";
|
||||
* - whatsNewStepsConfig.ts
|
||||
*/
|
||||
|
||||
const SAMPLE_PDF = path.join(__dirname, "../test-fixtures/sample.pdf");
|
||||
const SAMPLE_PDF = path.join(
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/sample.pdf",
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 15.1 Static layout - always visible on the main page
|
||||
|
||||
@@ -3,7 +3,7 @@ import { uploadFiles } from "@app/tests/helpers/ui-helpers";
|
||||
import type { Page, Route } from "@playwright/test";
|
||||
import path from "path";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const SAMPLE_PDF = path.join(FIXTURES_DIR, "sample.pdf");
|
||||
|
||||
// Base backend SignatureValidationResult; tests override the trust-related fields.
|
||||
|
||||
@@ -17,7 +17,10 @@ import path from "path";
|
||||
* Backend-free spec.
|
||||
*/
|
||||
|
||||
const SAMPLE_PDF = path.join(__dirname, "../test-fixtures/sample.pdf");
|
||||
const SAMPLE_PDF = path.join(
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/sample.pdf",
|
||||
);
|
||||
|
||||
async function openViewerWithSample(page: import("@playwright/test").Page) {
|
||||
await page.goto("/read");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "path";
|
||||
import { test, expect } from "@app/tests/helpers/stub-test-base";
|
||||
|
||||
const FIXTURES_DIR = path.join(__dirname, "../test-fixtures");
|
||||
const FIXTURES_DIR = path.join(import.meta.dirname, "../test-fixtures");
|
||||
const SAMPLE_PDF = path.join(FIXTURES_DIR, "sample.pdf");
|
||||
const MULTIPAGE_PDF = path.join(FIXTURES_DIR, "annotations_out_of_order.pdf");
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ import { test, expect } from "@app/tests/helpers/stub-test-base";
|
||||
import { uploadFiles } from "@app/tests/helpers/ui-helpers";
|
||||
import path from "path";
|
||||
|
||||
const SAMPLE_PDF = path.join(__dirname, "../test-fixtures/sample.pdf");
|
||||
const SAMPLE_PDF = path.join(
|
||||
import.meta.dirname,
|
||||
"../test-fixtures/sample.pdf",
|
||||
);
|
||||
|
||||
/**
|
||||
* Watermark has three modes — text / image / file overlay — selected via
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
export default {
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
||||
darkMode: ["class", '[data-mantine-color-scheme="dark"]'],
|
||||
theme: {
|
||||
|
||||
@@ -64,7 +64,6 @@ export default defineConfig(
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "off", // Temporarily disabled until codebase conformant
|
||||
"@typescript-eslint/no-require-imports": "off", // Temporarily disabled until codebase conformant
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"name": "frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "SEE LICENSE IN https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/proprietary/LICENSE",
|
||||
"proxy": "http://localhost:8080",
|
||||
"dependencies": {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Calculates date from 7 days ago and runs npm update/audit with that date
|
||||
*/
|
||||
|
||||
const { spawn } = require("child_process");
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
// Calculate date from 7 days ago in YYYY-MM-DD format
|
||||
const date = new Date();
|
||||
|
||||
Reference in New Issue
Block a user