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: convert to ESM + update all dependencies #120

Merged
merged 4 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ workflows:
jobs:
- node/test:
name: test-<< matrix.executor >>-<< matrix.node-version >>
pre-steps:
- when:
condition:
and:
- equal: [ node/macos, << matrix.executor >> ]
- equal: [ '14.16', << matrix.node-version >> ]
steps:
- node/install-rosetta
test-steps:
- run: yarn prettier:check
- run: yarn build
Expand All @@ -31,11 +23,8 @@ workflows:
- node/macos
- node/windows
node-version:
- '20.9'
- '18.17'
- '16.20'
# Stay below 14.17.0 or nvm tries to download arm64 artifacts which don't exist
- '14.16'
- '22.9'
- '20.11'
- cfa/release:
requires:
- test
Expand Down
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yarn lint-staged
19 changes: 12 additions & 7 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
const path = require('path');
import path from 'node:path';
import { createDefaultEsmPreset } from 'ts-jest';

module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testPathIgnorePatterns: ['node_modules', path.resolve(__dirname, 'dist')],
setupFiles: ['<rootDir>/jest.setup.js'],
};
/** @type {import('ts-jest').JestConfigWithTsJest} **/
export default {
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
testPathIgnorePatterns: ['node_modules', path.resolve(import.meta.dirname, 'dist')],
...createDefaultEsmPreset({
tsconfig: 'tsconfig.json',
})
};
43 changes: 24 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
"version": "0.0.0-development",
"description": "Parse Electron documentation into a machine readable JSON file",
"main": "dist/index.js",
"type": "module",
"author": "Samuel Attard",
"license": "MIT",
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
"node": "^20.11.0 || >= 21.2.0"
},
"scripts": {
"build": "tsc",
"prepublishOnly": "npx yarn build",
"prettier:check": "prettier --list-different \"src/**/*.{ts,tsx}\"",
"prettier:write": "prettier --write \"src/**/*.{ts,tsx}\"",
"test": "jest"
"test": "cross-env NODE_OPTIONS=\"--experimental-vm-modules\" jest",
"prepare": "husky"
},
"bin": {
"electron-docs-linter": "./dist/bin.js",
Expand All @@ -24,27 +26,30 @@
"!dist/__tests__"
],
"devDependencies": {
"@types/chai": "^4.2.5",
"@types/fs-extra": "^8.0.1",
"@types/jest": "^24.0.23",
"@types/lodash.camelcase": "^4.3.6",
"@types/minimist": "^1.2.0",
"@types/chai": "^4.3.19",
"@types/jest": "^29.5.13",
"@types/lodash.camelcase": "^4.3.9",
"@types/node": "^22.5.5",
"@types/pretty-ms": "^5.0.1",
"jest": "^29.3.1",
"prettier": "^1.19.1",
"ts-jest": "^29.0.3",
"typescript": "^4.9.3"
"cross-env": "^7.0.3",
"husky": "^9.1.6",
"jest": "^30.0.0-alpha.6",
"lint-staged": "^15.2.10",
"prettier": "^3.3.3",
"ts-jest": "^29.2.5",
"typescript": "^5.6.2"
},
"dependencies": {
"@types/markdown-it": "^12.0.0",
"chai": "^4.2.0",
"chalk": "^3.0.0",
"fs-extra": "^8.1.0",
"@types/markdown-it": "^14.1.2",
"chai": "^5.1.1",
"chalk": "^5.3.0",
"lodash.camelcase": "^4.3.0",
"markdown-it": "^12.0.0",
"minimist": "^1.2.0",
"ora": "^4.0.3",
"pretty-ms": "^5.1.0"
"markdown-it": "^14.1.0",
"ora": "^8.1.0",
"pretty-ms": "^9.1.0"
},
"lint-staged": {
"*.ts": "prettier --write"
},
"repository": {
"type": "git",
Expand Down
26 changes: 13 additions & 13 deletions src/DocsParser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect } from 'chai';
import * as fs from 'fs-extra';
import fs from 'node:fs';
import MarkdownIt from 'markdown-it';
import Token from 'markdown-it/lib/token';
import { Token } from 'markdown-it';
import * as path from 'path';
import toCamelCase = require('lodash.camelcase');
import toCamelCase from 'lodash.camelcase';

import {
ParsedDocumentation,
Expand All @@ -13,7 +13,7 @@ import {
ModuleDocumentationContainer,
ClassDocumentationContainer,
ElementDocumentationContainer,
} from './ParsedDocumentation';
} from './ParsedDocumentation.js';
import {
findNextList,
convertListToTypedKeys,
Expand All @@ -28,15 +28,15 @@ import {
findContentAfterHeadingClose,
HeadingContent,
getContentBeforeFirstHeadingMatching,
} from './markdown-helpers';
import { WEBSITE_BASE_DOCS_URL, REPO_BASE_DOCS_URL } from './constants';
import { extendError } from './helpers';
} from './markdown-helpers.js';
import { WEBSITE_BASE_DOCS_URL, REPO_BASE_DOCS_URL } from './constants.js';
import { extendError } from './helpers.js';
import {
parseMethodBlocks,
_headingToMethodBlock,
parsePropertyBlocks,
parseEventBlocks,
} from './block-parsers';
} from './block-parsers.js';

export class DocsParser {
constructor(
Expand Down Expand Up @@ -108,7 +108,7 @@ export class DocsParser {
groups = getContentBeforeConstructor(tokens);
} else {
// FIXME: Make it so that we don't need this magic FIXME for the electron breaking-changes document
groups = getContentBeforeFirstHeadingMatching(tokens, heading =>
groups = getContentBeforeFirstHeadingMatching(tokens, (heading) =>
['Events', 'Methods', 'Properties', '`FIXME` comments'].includes(heading.trim()),
);
}
Expand Down Expand Up @@ -156,7 +156,7 @@ export class DocsParser {
| ClassDocumentationContainer
| ElementDocumentationContainer
)[] = [];
const contents = await fs.readFile(filePath, 'utf8');
const contents = await fs.promises.readFile(filePath, 'utf8');
const md = new MarkdownIt({ html: true });

const allTokens = md.parse(contents, {});
Expand All @@ -182,7 +182,7 @@ export class DocsParser {
if (isClass) {
// Instance name will be taken either from an example in a method declaration or the camel
// case version of the class name
const levelFourHeader = headingsAndContent(tokens).find(h => h.level === 4);
const levelFourHeader = headingsAndContent(tokens).find((h) => h.level === 4);
const instanceName = levelFourHeader
? (levelFourHeader.heading.split('`')[1] || '').split('.')[0] ||
toCamelCase(container.name)
Expand Down Expand Up @@ -262,7 +262,7 @@ export class DocsParser {
}

private async parseStructure(filePath: string): Promise<StructureDocumentationContainer> {
const contents = await fs.readFile(filePath, 'utf8');
const contents = await fs.promises.readFile(filePath, 'utf8');
const md = new MarkdownIt({ html: true });

const tokens = md.parse(contents, {});
Expand All @@ -279,7 +279,7 @@ export class DocsParser {
return {
type: 'Structure',
...baseInfos[0].container,
properties: consumeTypedKeysList(convertListToTypedKeys(list!)).map(typedKey => ({
properties: consumeTypedKeysList(convertListToTypedKeys(list!)).map((typedKey) => ({
name: typedKey.key,
description: typedKey.description,
required: typedKey.required,
Expand Down
2 changes: 1 addition & 1 deletion src/ParsedDocumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class ParsedDocumentation {
}

public getJSON(): ParsedDocumentationResult {
return this.repr.filter(container => {
return this.repr.filter((container) => {
if (container.type !== 'Module') return true;

return container.events.length + container.methods.length + container.properties.length > 0;
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/markdown-helpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('markdown-helpers', () => {
});

describe('snapshots', () => {
const fixtureDir = path.resolve(__dirname, 'fixtures');
const fixtureDir = path.resolve(import.meta.dirname, 'fixtures');
for (const markdownFixture of fs.readdirSync(fixtureDir)) {
if (!markdownFixture.endsWith('.md')) continue;

Expand Down
57 changes: 40 additions & 17 deletions src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
#!/usr/bin/env node

import * as fs from 'fs-extra';
import minimist from 'minimist';
import chalk from 'chalk';
import fs from 'node:fs';
import { parseArgs } from 'node:util';
import ora from 'ora';
import * as path from 'path';
import pretty from 'pretty-ms';

import { parseDocs } from '.';
import chalk from 'chalk';
import { parseDocs } from './index.js';

const args = minimist(process.argv, {
default: {
packageMode: 'single',
const {
values: { outDir, dir, useReadme, moduleVersion, help, packageMode },
} = parseArgs({
options: {
packageMode: {
type: 'string',
default: 'single',
},
dir: {
type: 'string',
},
outDir: {
type: 'string',
},
useReadme: {
type: 'boolean',
},
moduleVersion: {
type: 'string',
},
help: {
type: 'boolean',
default: false,
},
},
});

const { dir, outDir, useReadme, packageMode, moduleVersion, help } = args;
if (!['single', 'multi'].includes(packageMode)) {
let safePackageMode = packageMode as 'single' | 'multi' | string;

if (safePackageMode !== 'single' && safePackageMode !== 'multi') {
console.error(chalk.red('packageMode must be one of "single" and "multi"'));
process.exit(1);
}
Expand All @@ -41,7 +63,7 @@ if (typeof moduleVersion !== 'string') {
}

const resolvedDir = path.isAbsolute(dir) ? dir : path.resolve(process.cwd(), dir);
if (!fs.pathExistsSync(resolvedDir)) {
if (!fs.existsSync(resolvedDir)) {
runner.fail(`${chalk.red('Resolved directory does not exist:')} ${chalk.cyan(resolvedDir)}`);
process.exit(1);
}
Expand All @@ -57,17 +79,18 @@ runner.text = chalk.cyan(`Generating API in directory: ${chalk.yellow(`"${resolv

const start = Date.now();

fs.mkdirp(resolvedOutDir).then(() =>
fs.promises.mkdir(resolvedOutDir, { recursive: true }).then(() =>
parseDocs({
useReadme: useReadme ? true : false,
baseDirectory: resolvedDir,
moduleVersion,
packageMode,
packageMode: safePackageMode,
})
.then(data =>
fs.writeJson(path.resolve(resolvedOutDir, './electron-api.json'), data, {
spaces: 2,
}),
.then((data) =>
fs.promises.writeFile(
path.resolve(resolvedOutDir, './electron-api.json'),
JSON.stringify(data, null, 2),
),
)
.then(() =>
runner.succeed(
Expand All @@ -76,7 +99,7 @@ fs.mkdirp(resolvedOutDir).then(() =>
)} took ${chalk.cyan(pretty(Date.now() - start))}`,
),
)
.catch(err => {
.catch((err) => {
runner.fail();
console.error(err);
process.exit(1);
Expand Down
16 changes: 7 additions & 9 deletions src/block-parsers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import Token from 'markdown-it/lib/token';
import { Token } from 'markdown-it';

import {
parseHeadingTags,
Expand All @@ -14,12 +14,12 @@ import {
StripReturnTypeBehavior,
consumeTypedKeysList,
slugifyHeading,
} from './markdown-helpers';
} from './markdown-helpers.js';
import {
MethodDocumentationBlock,
PropertyDocumentationBlock,
EventDocumentationBlock,
} from './ParsedDocumentation';
} from './ParsedDocumentation.js';

type GuessedParam = {
name: string;
Expand Down Expand Up @@ -110,7 +110,7 @@ export const _headingToMethodBlock = (
null,
`Method ${heading.heading} has at least one parameter but no parameter type list`,
);
parameters = consumeTypedKeysList(convertListToTypedKeys(list)).map(typedKey => ({
parameters = consumeTypedKeysList(convertListToTypedKeys(list)).map((typedKey) => ({
name: typedKey.key,
description: typedKey.description,
required: typedKey.required,
Expand Down Expand Up @@ -191,13 +191,11 @@ export const _headingToEventBlock = (heading: HeadingContent): EventDocumentatio

let parameters: EventDocumentationBlock['parameters'] = [];
if (
safelyJoinTokens(findContentAfterHeadingClose(heading.content))
.trim()
.startsWith('Returns:')
safelyJoinTokens(findContentAfterHeadingClose(heading.content)).trim().startsWith('Returns:')
) {
const list = findNextList(heading.content);
if (list) {
parameters = consumeTypedKeysList(convertListToTypedKeys(list)).map(typedKey => ({
parameters = consumeTypedKeysList(convertListToTypedKeys(list)).map((typedKey) => ({
name: typedKey.key,
description: typedKey.description,
...typedKey.type,
Expand All @@ -219,7 +217,7 @@ export const _headingToEventBlock = (heading: HeadingContent): EventDocumentatio
export const parseMethodBlocks = (tokens: Token[] | null): MethodDocumentationBlock[] => {
if (!tokens) return [];

return headingsAndContent(tokens).map(heading => _headingToMethodBlock(heading)!);
return headingsAndContent(tokens).map((heading) => _headingToMethodBlock(heading)!);
};

export const parsePropertyBlocks = (tokens: Token[] | null): PropertyDocumentationBlock[] => {
Expand Down
Loading