Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(index)!: make unrtfPath and unrtfVersion fields private #363

Merged
merged 11 commits into from Mar 12, 2024
1 change: 1 addition & 0 deletions .github/dependabot.yml
Expand Up @@ -24,6 +24,7 @@ updates:
- "@commitlint*"
eslint:
patterns:
- "@eslint-community*"
- "eslint*"
ignore:
# Below are dependencies that have migrated to ESM
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/cd.yml
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -135,6 +135,9 @@ dist
# Clinic.js
.clinic

# Auto generated files
types/

# lock files
bun.lockb
package-lock.json
Expand Down
3 changes: 1 addition & 2 deletions .prettierignore
Expand Up @@ -137,9 +137,8 @@ dist

# Auto generated files
package.json
API.md
CHANGELOG.md
/types/index.d.ts
types/

# lock files
bun.lockb
Expand Down
59 changes: 0 additions & 59 deletions API.md

This file was deleted.

10 changes: 2 additions & 8 deletions README.md
Expand Up @@ -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

Expand Down
15 changes: 7 additions & 8 deletions package.json
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
78 changes: 50 additions & 28 deletions src/index.js
Expand Up @@ -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.
*/
Expand All @@ -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}`
);
Expand All @@ -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
Expand All @@ -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;

Expand All @@ -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",
Expand All @@ -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",
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 = "";
Expand All @@ -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(
" "
Expand All @@ -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