diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index d1d6fe6..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended" - ], - "parserOptions": { - "ecmaVersion": 2022, - "sourceType": "module", - "project": ["./tsconfig.json"] - }, - "ignorePatterns": ["/dist/", "/bin/", "/test/", "/node_modules/", "/base/", "/lib/pdfjs-code.js", "**/*.json"], - "rules": { - "@typescript-eslint/no-unused-expressions": [ - "error", - { - "allowShortCircuit": true, - "allowTernary": true, - "allowTaggedTemplates": true - } - ] - }, - "overrides": [{ - "files": ["*.js", "*.ts"], - "rules": { - "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], - "@typescript-eslint/naming-convention": [ - "error", - { - "selector": "variable", - "format": ["camelCase", "PascalCase", "UPPER_CASE"], - "filter": { - "regex": "^_", - "match": false - } - }, - { - "selector": "function", - "format": ["camelCase", "PascalCase"] - }, - { - "selector": "parameter", - "format": ["camelCase", "PascalCase"], - "filter": { - "regex": "^_", - "match": false - } - }, - { - "selector": "property", - "format": ["camelCase", "PascalCase", "UPPER_CASE"], - "filter": { - "regex": "(x-ide-git-auth|^_|^sys_*|app_id)", - "match": false - } - }, - { - "selector": "method", - "format": ["camelCase", "PascalCase"], - "filter": { - "regex": "^_", - "match": false - } - }, - { - "selector": "accessor", - "format": ["camelCase", "PascalCase"] - }, - { - "selector": "enumMember", - "format": ["camelCase", "PascalCase", "UPPER_CASE"] - }, - { - "selector": "typeLike", - "format": ["PascalCase"] - } - ], - "@typescript-eslint/no-unused-vars": [ - "error", - { - "vars": "all", - "args": "after-used", - "argsIgnorePattern": "(^_?|fs|uri|options|opts|source|signal|destination|Uri$|args)", - "ignoreRestSiblings": true, - "destructuredArrayIgnorePattern": "^_?" - } - ], - "@typescript-eslint/no-extra-semi": "off", - "@typescript-eslint/no-var-requires": "off", - "arrow-body-style": ["error", "as-needed"], - "dot-notation": ["error"], - "eqeqeq": ["error", "always"], - "no-case-declarations": "error", - "no-duplicate-imports": ["error"], - "no-else-return": [ - "error", - { - "allowElseIf": true - } - ], - "no-eval": [ - "error", - { - "allowIndirect": false - } - ], - "no-iterator": ["error"], - "no-multi-assign": ["error"], - "no-new-func": ["error"], - "no-new-wrappers": ["error"], - "no-object-constructor": ["error"], - "no-param-reassign": "off", - "no-restricted-imports": ["error", "lodash", "moment"], - "no-throw-literal": "warn", - "no-useless-call": ["error"], - "object-curly-spacing": ["error", "always"], - "object-shorthand": [ - "error", - "always", - { - "avoidExplicitReturnArrows": true - } - ], - "prefer-arrow-callback": [ - "error", - { - "allowNamedFunctions": true - } - ], - "prefer-const": ["error"], - "prefer-destructuring": [ - "error", - { - "object": true, - "array": false - } - ], - "prefer-rest-params": ["error"], - "prefer-spread": ["error"], - "prefer-template": ["error"] - } - } - ] -} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..e398f5d --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,265 @@ +import js from "@eslint/js"; +import tseslint from "@typescript-eslint/eslint-plugin"; +import tsparser from "@typescript-eslint/parser"; + +export default [ + { + ignores: [ + "dist/**", + "bin/**", + "test/**", + "node_modules/**", + "base/**", + "lib/pdfjs-code.js", + "**/*.json" + ] + }, + // Configuration for JavaScript files - basic ESLint rules only + { + files: ["**/*.js"], + languageOptions: { + ecmaVersion: 2022, + sourceType: "module", + globals: { + console: "readonly", + process: "readonly", + Buffer: "readonly", + __dirname: "readonly", + __filename: "readonly", + module: "readonly", + require: "readonly", + exports: "writable", + global: "readonly", + setImmediate: "readonly", + clearImmediate: "readonly", + setTimeout: "readonly", + clearTimeout: "readonly", + setInterval: "readonly", + clearInterval: "readonly" + } + }, + rules: { + ...js.configs.recommended.rules, + "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], + "arrow-body-style": ["error", "as-needed"], + "dot-notation": ["error"], + "eqeqeq": ["error", "always"], + "no-case-declarations": "error", + "no-duplicate-imports": ["error"], + "no-else-return": [ + "error", + { + allowElseIf: true + } + ], + "no-eval": [ + "error", + { + allowIndirect: false + } + ], + "no-iterator": ["error"], + "no-multi-assign": ["error"], + "no-new-func": ["error"], + "no-new-wrappers": ["error"], + "no-object-constructor": ["error"], + "no-param-reassign": "off", + "no-restricted-imports": ["error", "lodash", "moment"], + "no-throw-literal": "warn", + "no-unused-vars": [ + "error", + { + vars: "all", + args: "after-used", + argsIgnorePattern: "(^_?|fs|uri|options|opts|source|signal|destination|Uri$|args|jsonObj|outputPath|resolve|reject|meta|page|evtData)", + ignoreRestSiblings: true, + destructuredArrayIgnorePattern: "^_?" + } + ], + "no-useless-call": ["error"], + "object-curly-spacing": ["error", "always"], + "object-shorthand": [ + "error", + "always", + { + avoidExplicitReturnArrows: true + } + ], + "prefer-arrow-callback": [ + "error", + { + allowNamedFunctions: true + } + ], + "prefer-const": ["error"], + "prefer-destructuring": [ + "error", + { + object: true, + array: false + } + ], + "prefer-rest-params": ["error"], + "prefer-spread": ["error"], + "prefer-template": ["error"] + } + }, + // Configuration for TypeScript files - full TypeScript ESLint rules + { + files: ["**/*.ts"], + languageOptions: { + parser: tsparser, + parserOptions: { + ecmaVersion: 2022, + sourceType: "module" + }, + globals: { + console: "readonly", + process: "readonly", + Buffer: "readonly", + __dirname: "readonly", + __filename: "readonly", + module: "readonly", + require: "readonly", + exports: "writable", + global: "readonly", + setImmediate: "readonly", + clearImmediate: "readonly", + setTimeout: "readonly", + clearTimeout: "readonly", + setInterval: "readonly", + clearInterval: "readonly" + } + }, + plugins: { + "@typescript-eslint": tseslint + }, + rules: { + ...js.configs.recommended.rules, + ...tseslint.configs.recommended.rules, + "@typescript-eslint/no-unused-expressions": [ + "error", + { + allowShortCircuit: true, + allowTernary: true, + allowTaggedTemplates: true + } + ], + "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], + "@typescript-eslint/naming-convention": [ + "error", + { + selector: "variable", + format: ["camelCase", "PascalCase", "UPPER_CASE"], + filter: { + regex: "^_", + match: false + } + }, + { + selector: "function", + format: ["camelCase", "PascalCase"] + }, + { + selector: "parameter", + format: ["camelCase", "PascalCase"], + filter: { + regex: "^_", + match: false + } + }, + { + selector: "property", + format: ["camelCase", "PascalCase", "UPPER_CASE"], + filter: { + regex: "(x-ide-git-auth|^_|^sys_*|app_id)", + match: false + } + }, + { + selector: "method", + format: ["camelCase", "PascalCase"], + filter: { + regex: "^_", + match: false + } + }, + { + selector: "accessor", + format: ["camelCase", "PascalCase"] + }, + { + selector: "enumMember", + format: ["camelCase", "PascalCase", "UPPER_CASE"] + }, + { + selector: "typeLike", + format: ["PascalCase"] + } + ], + "@typescript-eslint/no-unused-vars": [ + "error", + { + vars: "all", + args: "after-used", + argsIgnorePattern: "(^_?|fs|uri|options|opts|source|signal|destination|Uri$|args)", + ignoreRestSiblings: true, + destructuredArrayIgnorePattern: "^_?" + } + ], + "@typescript-eslint/no-extra-semi": "off", + "@typescript-eslint/no-var-requires": "off", + "arrow-body-style": ["error", "as-needed"], + "dot-notation": ["error"], + "eqeqeq": ["error", "always"], + "no-case-declarations": "error", + "no-duplicate-imports": ["error"], + "no-else-return": [ + "error", + { + allowElseIf: true + } + ], + "no-eval": [ + "error", + { + allowIndirect: false + } + ], + "no-iterator": ["error"], + "no-multi-assign": ["error"], + "no-new-func": ["error"], + "no-new-wrappers": ["error"], + "no-object-constructor": ["error"], + "no-param-reassign": "off", + "no-restricted-imports": ["error", "lodash", "moment"], + "no-throw-literal": "warn", + "no-useless-call": ["error"], + "object-curly-spacing": ["error", "always"], + "object-shorthand": [ + "error", + "always", + { + avoidExplicitReturnArrows: true + } + ], + "prefer-arrow-callback": [ + "error", + { + allowNamedFunctions: true + } + ], + "prefer-const": ["error"], + "prefer-destructuring": [ + "error", + { + object: true, + array: false + } + ], + "prefer-rest-params": ["error"], + "prefer-spread": ["error"], + "prefer-template": ["error"] + } + } +]; diff --git a/lib/pdf.js b/lib/pdf.js index 6c769ec..c2cf4ea 100644 --- a/lib/pdf.js +++ b/lib/pdf.js @@ -3,7 +3,13 @@ import console from "node:console"; import fs from "node:fs"; import { EventEmitter } from "node:events"; -import { PDFJS } from "./pdfjs-code.js"; // created via `npm run build` +import { PDFJS } from "./pdfjs-code.js"; +import { initLogger } from "./pdfjs-logger.js"; + +// Initialize the logger with the actual PDFJS instance +initLogger(PDFJS); + +// Create typed wrapper for internal use const PJS = /** @type {import("../src/types/pdfjs").PDFJSAPI} */ ( /** @type {any} */ (PDFJS) ); @@ -471,4 +477,5 @@ export default class PDFJSClass extends EventEmitter { } } +// Export typed PJS for backward compatibility export { PJS }; diff --git a/lib/pdfanno.js b/lib/pdfanno.js index 7669aa6..2d1dfdb 100644 --- a/lib/pdfanno.js +++ b/lib/pdfanno.js @@ -1,4 +1,4 @@ -import { PJS } from "./pdf.js"; +import { PJS } from "./pdfjs-logger.js"; //BEGIN - MQZ 9/19/2012. Helper functions to parse acroForm elements function setupRadioButton(annotation, item) { diff --git a/lib/pdfcanvas.js b/lib/pdfcanvas.js index c1d9f66..70fe1bf 100644 --- a/lib/pdfcanvas.js +++ b/lib/pdfcanvas.js @@ -1,10 +1,10 @@ -import { PJS } from "./pdf.js"; +import { PJS } from "./pdfjs-logger.js"; import PDFLine from "./pdfline.js"; import PDFFill from "./pdffill.js"; import PDFFont from "./pdffont.js"; // alias some functions to make (compiled) code shorter -// eslint-disable-next-line @typescript-eslint/no-unused-vars +// eslint-disable-next-line no-unused-vars const { round: mr, sin: ms, cos: mc, abs, sqrt } = Math; // precompute "00" to "FF" @@ -83,7 +83,7 @@ function processStyle(styleString) { return { color: str, alpha }; } -// eslint-disable-next-line @typescript-eslint/no-unused-vars +// eslint-disable-next-line no-unused-vars function processLineCap(lineCap) { switch (lineCap) { case "butt": @@ -138,13 +138,13 @@ function setM(ctx, m, updateLineScale) { } } -// eslint-disable-next-line @typescript-eslint/naming-convention +// Legacy naming convention from original PDF.js implementation class CanvasPattern_ { constructor() {} } // Gradient / Pattern Stubs -// eslint-disable-next-line @typescript-eslint/naming-convention +// Legacy naming convention from original PDF.js implementation class CanvasGradient_ { constructor(aType) { this.type_ = aType; @@ -172,7 +172,7 @@ class CanvasGradient_ { * @param {HTMLElement} surfaceElement The element that the 2D context should * be associated with */ -// eslint-disable-next-line @typescript-eslint/naming-convention +// Legacy naming convention from original PDF.js implementation export default class CanvasRenderingContext2D_ { constructor(canvasTarget, scaledWidth, scaledHeight) { this.m_ = createMatrixIdentity(); @@ -435,7 +435,7 @@ export default class CanvasRenderingContext2D_ { return gradient; } - // eslint-disable-next-line @typescript-eslint/naming-convention + // Method signature matches Canvas API drawImage(image, var_args) { //MQZ. no image drawing support for now } @@ -531,7 +531,7 @@ export default class CanvasRenderingContext2D_ { /** * @private */ - // eslint-disable-next-line @typescript-eslint/naming-convention + // Legacy naming convention from original PDF.js implementation getCoords_(aX, aY) { const m = this.m_; return { diff --git a/lib/pdffield.js b/lib/pdffield.js index 78ddc0c..4ed7d33 100644 --- a/lib/pdffield.js +++ b/lib/pdffield.js @@ -1,4 +1,4 @@ -import { PJS } from "./pdf.js"; +import { PJS } from "./pdfjs-logger.js"; import PDFUnit from "./pdfunit.js"; const kFBANotOverridable = 0x00000400; // indicates the field is read only by the user diff --git a/lib/pdffill.js b/lib/pdffill.js index d1edef1..18f7634 100644 --- a/lib/pdffill.js +++ b/lib/pdffill.js @@ -1,4 +1,4 @@ -import { PJS } from "./pdf.js"; +import { PJS } from "./pdfjs-logger.js"; import PDFUnit from "./pdfunit.js"; export default class PDFFill{ diff --git a/lib/pdffont.js b/lib/pdffont.js index dfa4ecb..0c7ff37 100644 --- a/lib/pdffont.js +++ b/lib/pdffont.js @@ -1,4 +1,4 @@ -import { PJS } from "./pdf.js"; +import { PJS } from "./pdfjs-logger.js"; import PDFUnit from './pdfunit.js'; import { kFontFaces, kFontStyles } from './pdfconst.js'; diff --git a/lib/pdfjs-logger.js b/lib/pdfjs-logger.js new file mode 100644 index 0000000..226e18d --- /dev/null +++ b/lib/pdfjs-logger.js @@ -0,0 +1,56 @@ +/** + * PDF.js Logger Module + * + * Provides logging functionality for all PDF processing modules. + * This module has no dependencies and can be imported by any module + * that needs logging without creating circular dependencies. + * + * The actual implementation lives in base/shared/util.js and is injected + * via initLogger() when pdf.js loads. Fallback implementations are provided + * for use before initialization. + */ + +import console from "node:console"; + +/** + * Logger instance that modules import + * Delegates to PDFJS implementation from base/shared/util.js after initLogger() is called + */ +export const PJS = { + log: console.log.bind(console), + info: console.info.bind(console), + warn: console.warn.bind(console), + error(msg) { throw new Error(msg); }, + verbosity() {}, + LogManager: { + addLogger() {}, + notify() {}, + }, + // Verbosity constants (matching base/shared/util.js lines 26-28) + ERRORS: 0, + WARNINGS: 1, + INFOS: 5, +}; + +/** + * Initialize the logger with the actual PDFJS implementation from base/shared/util.js + * This is called by pdf.js after pdfjs-code.js is loaded + * + * Delegates all methods to the pdfjsInstance which has the full implementation + */ +export function initLogger(pdfjsInstance) { + if (pdfjsInstance) { + // Delegate all methods to the actual PDFJS implementation + PJS.log = pdfjsInstance.log; + PJS.info = pdfjsInstance.info; + PJS.warn = pdfjsInstance.warn; + PJS.error = pdfjsInstance.error; + PJS.verbosity = pdfjsInstance.verbosity; + PJS.LogManager = pdfjsInstance.LogManager; + + // Initialize default verbosity + if (typeof pdfjsInstance.verbosity === 'function') { + pdfjsInstance.verbosity(); + } + } +} diff --git a/lib/pdfline.js b/lib/pdfline.js index 0e3a1b7..a3ad459 100644 --- a/lib/pdfline.js +++ b/lib/pdfline.js @@ -1,4 +1,4 @@ -import { PJS } from "./pdf.js"; +import { PJS } from "./pdfjs-logger.js"; import PDFUnit from "./pdfunit.js"; export default class PDFLine { diff --git a/package.json b/package.json index 1c3c47f..b3b562d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pdf2json", - "version": "4.0.0", + "version": "4.0.1", "description": "PDF file parser that converts PDF binaries to JSON and text, powered by porting a fork of PDF.JS to Node.js", "keywords": [ "pdf", @@ -72,6 +72,7 @@ }, "bundleDependencies": [], "devDependencies": { + "@eslint/js": "^9.37.0", "@rollup/plugin-commonjs": "^28.0.6", "@rollup/plugin-eslint": "^9.1.0", "@rollup/plugin-json": "^6.1.0", diff --git a/pdfparser.js b/pdfparser.js index 20c46d3..e287adb 100644 --- a/pdfparser.js +++ b/pdfparser.js @@ -2,7 +2,7 @@ import fs from "node:fs"; import { readFile } from "node:fs/promises"; import { EventEmitter } from "node:events"; import { Buffer } from "node:buffer"; -// eslint-disable-next-line @typescript-eslint/no-unused-vars +// eslint-disable-next-line no-unused-vars import { Readable } from "node:stream"; import PDFJS, { PJS } from "./lib/pdf.js"; @@ -73,7 +73,7 @@ export default class PDFParser extends EventEmitter { /** * static property to expose _PARSER_SIG string */ - // eslint-disable-next-line @typescript-eslint/naming-convention + // Underscore prefix convention for internal constants static get _PARSER_SIG() { return _PARSER_SIG; } diff --git a/tsconfig.json b/tsconfig.json index 9642ccf..8649e67 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,7 +22,7 @@ "esModuleInterop": true, "resolveJsonModule": true, "allowJs": true, - "checkJs": true, + "checkJs": false, }, "include": [ "./src/**/*.ts",