diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4076858..b8a6e3c 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -24,6 +24,7 @@ updates:
- "@commitlint*"
eslint:
patterns:
+ - "@eslint-community*"
- "eslint*"
ignore:
# Below are dependencies that have migrated to ESM
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index fdca212..7201ad4 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -53,11 +53,11 @@ jobs:
- name: Publish to NPM
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- # Build docs and TS definitions, and remove dev values
+ # Build docs/definitions, and remove dev values
# from package.json before publishing to reduce package size
run: |
npm i --ignore-scripts
- npm run build
+ npm run build --if-present
npm pkg delete commitlint devDependencies jest scripts
npm publish --access public --ignore-scripts --provenance
@@ -66,6 +66,7 @@ jobs:
needs: release
if: needs.release.outputs.release_created == 'true'
runs-on: ubuntu-latest
+ environment: main
permissions:
contents: read
id-token: write
@@ -85,16 +86,16 @@ jobs:
- name: Scope package
run: |
- pkgName=$(npm pkg get name | tr -d '"')
+ pkgName=$(node -p "require('./package.json').name")
npm pkg set name="@fdawgs/$pkgName"
- name: Publish to GitHub Packages
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- # Build docs and TS definitions, and remove dev values
+ # Build docs/definitions, and remove dev values
# from package.json before publishing to reduce package size
run: |
npm i --ignore-scripts
- npm run build
+ npm run build --if-present
npm pkg delete commitlint devDependencies jest scripts
npm publish --access public --ignore-scripts --provenance
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9b9b527..797b6a7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -69,8 +69,8 @@ jobs:
- name: Run License Checker
run: npm run lint:licenses
- - name: Compile TypeScript Definition File
- run: npm run build
+ - name: Run Build
+ run: npm run build --if-present
commit-lint:
name: Lint Commit Messages
diff --git a/.gitignore b/.gitignore
index 2b6b96e..3199d26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -135,6 +135,9 @@ dist
# Clinic.js
.clinic
+# Auto generated files
+types/
+
# lock files
bun.lockb
package-lock.json
diff --git a/.prettierignore b/.prettierignore
index 5ee876f..159db3f 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -137,9 +137,8 @@ dist
# Auto generated files
package.json
-API.md
CHANGELOG.md
-/types/index.d.ts
+types/
# lock files
bun.lockb
diff --git a/API.md b/API.md
deleted file mode 100644
index 32dd497..0000000
--- a/API.md
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-## UnRTF
-**Kind**: global class
-
-* [UnRTF](#UnRTF)
- * [new UnRTF([binPath])](#new_UnRTF_new)
- * [.unrtfPath](#UnRTF+unrtfPath) : string
\| undefined
- * [.unrtfVersion](#UnRTF+unrtfVersion) : string
\| undefined
- * [.unrtfAcceptedOptions](#UnRTF+unrtfAcceptedOptions) : object
- * [.convert(file, [options])](#UnRTF+convert) ⇒ Promise.<string>
-
-
-
-### new UnRTF([binPath])
-
-| Param | Type | Description |
-| --- | --- | --- |
-| [binPath] | string
| Path of UnRTF binary. If not provided, the constructor will attempt to find the binary in the PATH environment variable. For `win32`, a binary is bundled with the package and will be used if a local installation is not found. |
-
-
-
-### unRTF.unrtfPath : string
\| undefined
-**Kind**: instance property of [UnRTF
](#UnRTF)
-
-
-### unRTF.unrtfVersion : string
\| undefined
-**Kind**: instance property of [UnRTF
](#UnRTF)
-
-
-### unRTF.unrtfAcceptedOptions : object
-**Kind**: instance property of [UnRTF
](#UnRTF)
-
-
-### unRTF.convert(file, [options]) ⇒ Promise.<string>
-Converts an RTF file to HTML/LaTeX/RTF/TXT.
-Defaults to HTML output if no `output*` options are provided.
-UnRTF will use the directory of the original file to store embedded pictures.
-
-**Kind**: instance method of [UnRTF
](#UnRTF)
-**Returns**: Promise.<string>
- A promise that resolves with a stdout string, or rejects with an `Error` object.
-**Author**: Frazer Smith
-
-| Param | Type | Description |
-| --- | --- | --- |
-| file | string
| Filepath of the RTF file to read. |
-| [options] | object
| Object containing options to pass to binary. |
-| [options.noPictures] | boolean
| Disable the automatic storing of embedded pictures to the directory of the original file. |
-| [options.noRemap] | boolean
| Disable charset conversion (only works for 8-bit charsets) (UnRTF v0.20.5 or later only). |
-| [options.outputHtml] | boolean
| Generate HTML output. |
-| [options.outputLatex] | boolean
| Generate LaTeX output. |
-| [options.outputPs] | boolean
| Generate PostScript (PS) output (UnRTF v0.19.4 or earlier only). |
-| [options.outputRtf] | boolean
| Generate RTF output. (UnRTF v0.21.3 or later only). |
-| [options.outputText] | boolean
| Generate ASCII text output. |
-| [options.outputVt] | boolean
| Generate text output with VT100 escape codes. |
-| [options.outputWpml] | boolean
| Generate WPML output (UnRTF v0.19.4 or earlier only). |
-| [options.printVersionInfo] | boolean
| Print copyright and version info. |
-| [options.quiet] | boolean
| Do not print any leading comments in output (UnRTF v0.21.3 or later only). |
-
diff --git a/README.md b/README.md
index 9f0fd49..252f6b2 100644
--- a/README.md
+++ b/README.md
@@ -45,15 +45,9 @@ For macOS, the binary can be installed with [Homebrew](https://brew.sh/):
brew install unrtf
```
-## API
+## Example usage
-```js
-const { UnRTF } = require("node-unrtf");
-```
-
-[**API Documentation can be found here**](https://github.com/Fdawgs/node-unrtf/blob/main/API.md)
-
-## Examples
+Please refer to the [JSDoc comments in the source code](./src/index.js) or the [generated type definitions](https://www.npmjs.com/package/node-unrtf?activeTab=code) for information on the available options.
### Async Await
diff --git a/package.json b/package.json
index a7213b0..144bc52 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
"node": ">=18.0.0"
},
"scripts": {
- "build": "tsc && jsdoc2md src/index.js > API.md",
+ "build": "tsc",
"jest": "jest",
"jest:coverage": "jest --coverage",
"lint": "eslint . --cache --ext js,jsx --ignore-path .gitignore",
@@ -74,27 +74,26 @@
"testTimeout": 10000
},
"devDependencies": {
- "@commitlint/cli": "^19.0.3",
- "@commitlint/config-conventional": "^19.0.3",
+ "@commitlint/cli": "^19.1.0",
+ "@commitlint/config-conventional": "^19.1.0",
"@eslint-community/eslint-plugin-eslint-comments": "^4.1.0",
"@types/jest": "^29.5.12",
- "eslint": "^8.56.0",
+ "eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^27.9.0",
- "eslint-plugin-jsdoc": "^48.1.0",
+ "eslint-plugin-jsdoc": "^48.2.1",
"eslint-plugin-promise": "^6.1.1",
- "eslint-plugin-regexp": "^2.2.0",
+ "eslint-plugin-regexp": "^2.3.0",
"eslint-plugin-security": "^2.1.1",
"husky": "^9.0.11",
"is-html": "^2.0.0",
"jest": "^29.7.0",
- "jsdoc-to-markdown": "^8.0.1",
"license-checker": "^25.0.1",
"prettier": "^3.2.5",
"spdx-copyleft": "^1.0.0",
- "typescript": "^5.3.3"
+ "typescript": "^5.4.2"
},
"dependencies": {
"semver": "^7.6.0",
diff --git a/src/index.js b/src/index.js
index d2629d7..68e223f 100644
--- a/src/index.js
+++ b/src/index.js
@@ -15,14 +15,16 @@ const unrtfPathRegex = /(.+)unrtf/u;
// UnRTF version output is inconsistent between versions but always starts with the semantic version number
const unrtfVersionRegex = /^(\d{1,2}\.\d{1,2}\.\d{1,2})/u;
+/** @typedef {{[key: string]: {arg: string, type: string, minVersion: string, maxVersion?: string}}} UnRTFAcceptedOptions */
+
/**
* @author Frazer Smith
* @description Checks each option provided is valid, of the correct type, and can be used by specified
* version of binary.
* @ignore
- * @param {object} acceptedOptions - Object containing accepted options.
- * @param {object} options - Object containing options to pass to binary.
- * @param {string} [version] - Semantic version of binary.
+ * @param {UnRTFAcceptedOptions} acceptedOptions - Object containing accepted options.
+ * @param {{[key: string]: any}} options - Object containing options to pass to binary.
+ * @param {string} version - Semantic version of binary.
* @returns {string[]} Array of CLI arguments.
* @throws If invalid arguments provided.
*/
@@ -48,23 +50,15 @@ function parseOptions(acceptedOptions, options, version) {
);
}
- if (
- acceptedOptions[key].minVersion &&
- version &&
- lt(version, acceptedOptions[key].minVersion)
- ) {
+ /* istanbul ignore next: unable to test due to https://github.com/jestjs/jest/pull/14297 */
+ if (lt(version, acceptedOptions[key].minVersion)) {
invalidArgs.push(
`Invalid option provided for the current version of the binary used. '${key}' was introduced in v${acceptedOptions[key].minVersion}, but received v${version}`
);
}
- /* istanbul ignore next: requires incredibly old version of UnRTF to test */
- if (
- acceptedOptions[key].maxVersion &&
- version &&
- // @ts-ignore: type checking is done above
- gt(version, acceptedOptions[key].maxVersion)
- ) {
+ /* istanbul ignore next: unable to test due to https://github.com/jestjs/jest/pull/14297 */
+ if (gt(version, acceptedOptions[key].maxVersion || version)) {
invalidArgs.push(
`Invalid option provided for the current version of the binary used. '${key}' is only present up to v${acceptedOptions[key].maxVersion}, but received v${version}`
);
@@ -80,6 +74,10 @@ function parseOptions(acceptedOptions, options, version) {
}
class UnRTF {
+ #unrtfPath;
+
+ #unrtfVersion;
+
/**
* @param {string} [binPath] - Path of UnRTF binary.
* If not provided, the constructor will attempt to find the binary
@@ -89,10 +87,12 @@ class UnRTF {
* if a local installation is not found.
*/
constructor(binPath) {
+ this.#unrtfPath = "";
+
/* istanbul ignore else: requires specific OS */
if (binPath) {
/** @type {string|undefined} */
- this.unrtfPath = binPath;
+ this.#unrtfPath = binPath;
} else {
const { platform } = process;
@@ -102,10 +102,10 @@ class UnRTF {
const unrtfPath = unrtfPathRegex.exec(which)?.[1];
if (unrtfPath) {
- this.unrtfPath = unrtfPath;
+ this.#unrtfPath = unrtfPath;
}
if (platform === "win32" && !unrtfPath) {
- this.unrtfPath = joinSafe(
+ this.#unrtfPath = joinSafe(
__dirname,
"lib",
"win32",
@@ -115,24 +115,29 @@ class UnRTF {
}
}
- if (!this.unrtfPath) {
+ /* istanbul ignore next: unable to test due to https://github.com/jestjs/jest/pull/14297 */
+ if (!this.#unrtfPath) {
throw new Error(
`Unable to find ${process.platform} UnRTF binaries, please pass the installation directory as a parameter to the UnRTF instance.`
);
}
- this.unrtfPath = normalizeTrim(this.unrtfPath);
+ this.#unrtfPath = normalizeTrim(this.#unrtfPath);
/**
* Get version of UnRTF binary for use in `convert` function.
* UnRTF outputs the version into stderr.
*/
- const version = spawnSync(joinSafe(this.unrtfPath, "unrtf"), [
+ const version = spawnSync(joinSafe(this.#unrtfPath, "unrtf"), [
"--version",
]).stderr.toString();
- /** @type {string|undefined} */
- this.unrtfVersion = unrtfVersionRegex.exec(version)?.[1];
+ this.#unrtfVersion = unrtfVersionRegex.exec(version)?.[1] || "";
- /** @type {object} */
+ /* istanbul ignore next: unable to test due to https://github.com/jestjs/jest/pull/14297 */
+ if (!this.#unrtfVersion) {
+ throw new Error("Unable to determine UnRTF version.");
+ }
+
+ /** @type {UnRTFAcceptedOptions} */
this.unrtfAcceptedOptions = {
noPictures: {
arg: "--nopict",
@@ -178,6 +183,22 @@ class UnRTF {
};
}
+ /**
+ * @description Returns the path of the UnRTF binary.
+ * @returns {string} Path of UnRTF binary.
+ */
+ get path() {
+ return this.#unrtfPath;
+ }
+
+ /**
+ * @description Returns the version of the UnRTF binary.
+ * @returns {string} Version of UnRTF binary.
+ */
+ get version() {
+ return this.#unrtfVersion;
+ }
+
/**
* @author Frazer Smith
* @description Converts an RTF file to HTML/LaTeX/RTF/TXT.
@@ -222,12 +243,12 @@ class UnRTF {
const args = parseOptions(
this.unrtfAcceptedOptions,
options,
- this.unrtfVersion
+ this.#unrtfVersion
);
args.push(normalizeTrim(file));
return new Promise((resolve, reject) => {
- const child = spawn(joinSafe(this.unrtfPath, "unrtf"), args);
+ const child = spawn(joinSafe(this.#unrtfPath, "unrtf"), args);
let stdOut = "";
let stdErr = "";
@@ -247,6 +268,7 @@ class UnRTF {
} else if (stdErr === "") {
reject(
new Error(
+ // @ts-ignore: Second operand used if code is not in errorMessages
errorMessages[code] ||
`unrtf ${args.join(
" "
@@ -261,5 +283,5 @@ class UnRTF {
}
}
-module.exports.UnRTF = UnRTF;
-module.exports.default = UnRTF;
+module.exports.default = UnRTF; // ESM default export
+module.exports.UnRTF = UnRTF; // TypeScript and named export
diff --git a/src/index.test.js b/src/index.test.js
index 11c2b14..750d49c 100644
--- a/src/index.test.js
+++ b/src/index.test.js
@@ -57,7 +57,8 @@ describe("Constructor", () => {
it("Creates a new UnRTF instance without the binary path set", () => {
const unRtf = new UnRTF();
- expect(unRtf.unrtfPath).toBe(testBinaryPath);
+ expect(unRtf.path).toBe(testBinaryPath);
+ expect(unRtf.version).toEqual(expect.any(String));
});
/**
@@ -92,6 +93,36 @@ describe("Constructor", () => {
);
}
});
+
+ /**
+ * @todo Fix this test, mocking of "node:" scheme not supported yet.
+ * @see {@link https://github.com/jestjs/jest/pull/14297 | Jest PR #14297}
+ */
+ // eslint-disable-next-line jest/no-disabled-tests -- Blocked by Jest PR #14297
+ it.skip("Throws an Error if the version of the binary cannot be determined", () => {
+ // Ensure the mock is used by the UnRTF constructor
+ jest.resetModules();
+ jest.mock("node:child_process", () => ({
+ spawnSync: jest.fn(() => ({
+ stdout: {
+ toString: () => "/usr/bin/unrtf",
+ },
+ stderr: {
+ toString: () => "",
+ },
+ })),
+ }));
+ require("node:child_process");
+ const { UnRTF: UnRTFMock } = require("./index");
+
+ expect.assertions(1);
+ try {
+ // eslint-disable-next-line no-unused-vars -- This is intentional
+ const unRtf = new UnRTFMock();
+ } catch (err) {
+ expect(err.message).toBe("mock error");
+ }
+ });
});
describe("Convert function", () => {
diff --git a/tsconfig.json b/tsconfig.json
index e73e3c3..be385e0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -8,6 +8,7 @@
"moduleResolution": "NodeNext",
"outDir": "types",
"resolveJsonModule": true,
+ "strict": true,
"target": "ES2022"
},
"include": ["src/index.js"]
diff --git a/types/index.d.ts b/types/index.d.ts
deleted file mode 100644
index 04c71fe..0000000
--- a/types/index.d.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-export default UnRTF;
-export class UnRTF {
- /**
- * @param {string} [binPath] - Path of UnRTF binary.
- * If not provided, the constructor will attempt to find the binary
- * in the PATH environment variable.
- *
- * For `win32`, a binary is bundled with the package and will be used
- * if a local installation is not found.
- */
- constructor(binPath?: string);
- /** @type {string|undefined} */
- unrtfPath: string | undefined;
- /** @type {string|undefined} */
- unrtfVersion: string | undefined;
- /** @type {object} */
- unrtfAcceptedOptions: object;
- /**
- * @author Frazer Smith
- * @description Converts an RTF file to HTML/LaTeX/RTF/TXT.
- * Defaults to HTML output if no `output*` options are provided.
- * UnRTF will use the directory of the original file to store embedded pictures.
- * @param {string} file - Filepath of the RTF file to read.
- * @param {object} [options] - Object containing options to pass to binary.
- * @param {boolean} [options.noPictures] - Disable the automatic storing of embedded
- * pictures to the directory of the original file.
- * @param {boolean} [options.noRemap] - Disable charset conversion (only works for 8-bit charsets)
- * (UnRTF v0.20.5 or later only).
- * @param {boolean} [options.outputHtml] - Generate HTML output.
- * @param {boolean} [options.outputLatex] - Generate LaTeX output.
- * @param {boolean} [options.outputPs] - Generate PostScript (PS) output (UnRTF v0.19.4 or earlier only).
- * @param {boolean} [options.outputRtf] - Generate RTF output. (UnRTF v0.21.3 or later only).
- * @param {boolean} [options.outputText] - Generate ASCII text output.
- * @param {boolean} [options.outputVt] - Generate text output with VT100 escape codes.
- * @param {boolean} [options.outputWpml] - Generate WPML output (UnRTF v0.19.4 or earlier only).
- * @param {boolean} [options.printVersionInfo] - Print copyright and version info.
- * @param {boolean} [options.quiet] - Do not print any leading comments in output (UnRTF v0.21.3 or later only).
- * @returns {Promise} A promise that resolves with a stdout string, or rejects with an `Error` object.
- */
- convert(file: string, options?: {
- noPictures?: boolean;
- noRemap?: boolean;
- outputHtml?: boolean;
- outputLatex?: boolean;
- outputPs?: boolean;
- outputRtf?: boolean;
- outputText?: boolean;
- outputVt?: boolean;
- outputWpml?: boolean;
- printVersionInfo?: boolean;
- quiet?: boolean;
- }): Promise;
-}