harper.js 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.49.1"
9
+ }
10
+ ]
11
+ }
package/docs.sh ADDED
@@ -0,0 +1,24 @@
1
+ #! /bin/bash
2
+
3
+ set -eo pipefail
4
+
5
+ yarn run api-extractor run
6
+ yarn run api-documenter markdown -i temp
7
+
8
+ rm -r html || true
9
+ mkdir html || true
10
+
11
+ echo Rendering HTML...
12
+
13
+ for file in ./markdown/*.md
14
+ do
15
+ BASE=$(basename $file .md)
16
+ pandoc $file -o html/$BASE.html
17
+ sed -i 's/"\(.*\).md"/"\1.html"/g' html/$BASE.html
18
+
19
+ echo '<link rel="stylesheet" href="https://unpkg.com/mvp.css">' >> html/$BASE.html
20
+ done
21
+
22
+ rm -r ../web/static/docs/harperjs || true
23
+ mkdir -p ../web/static/docs/harperjs || true
24
+ mv -f html ../web/static/docs/harperjs/ref
@@ -1,4 +1,4 @@
1
- let harper = require('harper.js');
1
+ import * as harper from 'harper.js';
2
2
 
3
3
  async function main() {
4
4
  // We cannot use `WorkerLinter` on Node.js since it relies on web-specific APIs.
@@ -3,9 +3,9 @@
3
3
  "version": "0.0.1",
4
4
  "private": true,
5
5
  "scripts": {
6
- "start": "node index.cjs"
6
+ "start": "node index.js"
7
7
  },
8
8
  "dependencies": {
9
- "harper.js": "^0.13.0"
9
+ "harper.js": "^0.14.0"
10
10
  }
11
11
  }
@@ -2,13 +2,7 @@
2
2
  # yarn lockfile v1
3
3
 
4
4
 
5
- harper.js@^0.13.0:
6
- version "0.13.0"
7
- resolved "https://registry.yarnpkg.com/harper.js/-/harper.js-0.13.0.tgz#f9e945c842f4e07e1b7042e3eef00a8040b2e0dd"
8
- integrity sha512-XjiQG7kpooKCU2xp46mvNra9PUq5n3z5kXOaWvKjOBRyWIllvuEwvDv40cEUODhWD2ABVTEMea8odXRORfyruw==
9
- dependencies:
10
- wasm "link:../../../../../../.cache/yarn/v6/npm-harper-js-0.13.0-f9e945c842f4e07e1b7042e3eef00a8040b2e0dd-integrity/harper-wasm/pkg"
11
-
12
- "wasm@link:../../../../../../.cache/yarn/v6/npm-harper-js-0.13.0-f9e945c842f4e07e1b7042e3eef00a8040b2e0dd-integrity/harper-wasm/pkg":
13
- version "0.0.0"
14
- uid ""
5
+ harper.js@^0.14.0:
6
+ version "0.14.0"
7
+ resolved "https://registry.yarnpkg.com/harper.js/-/harper.js-0.14.0.tgz#16d511070d4474dca501d4de1c76f7849ec0accb"
8
+ integrity sha512-WRzop2PmFK2AZiqNMHHWDFIqFmS7DeoNVhyibyu7T6wuSe24E1Tunolz8ZzMPfcaKuBB2SY+yGbyTOyj+/QD8g==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harper.js",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Elijah Potter",
6
6
  "description": "The grammar checker for developers.",
@@ -17,17 +17,19 @@
17
17
  "scripts": {
18
18
  "dev": "vite",
19
19
  "build": "tsc && vite build",
20
- "test": "vitest run --browser firefox && vitest run --browser chromium"
20
+ "test": "vitest run --browser chromium && vitest run --browser firefox"
21
21
  },
22
22
  "devDependencies": {
23
- "wasm": "link:../../harper-wasm/pkg",
23
+ "@microsoft/api-documenter": "^7.26.5",
24
+ "@microsoft/api-extractor": "^7.49.1",
24
25
  "@vitest/browser": "^2.1.8",
25
26
  "playwright": "^1.49.1",
26
27
  "typescript": "~5.6.2",
27
28
  "vite": "^5.1.8",
28
- "vite-plugin-dts": "^4.3.0",
29
+ "vite-plugin-dts": "^4.5.0",
29
30
  "vite-plugin-virtual": "^0.3.0",
30
- "vitest": "^2.1.8"
31
+ "vitest": "^2.1.8",
32
+ "wasm": "link:../../harper-wasm/pkg"
31
33
  },
32
34
  "main": "dist/harper.js",
33
35
  "types": "dist/harper.d.ts"
package/src/Linter.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Lint, Span, Suggestion } from 'wasm';
2
- import { LintConfig } from './main';
2
+ import { LintConfig, LintOptions } from './main';
3
3
 
4
4
  /** An interface for an object that can perform linting actions. */
5
5
  export default interface Linter {
@@ -9,7 +9,7 @@ export default interface Linter {
9
9
  setup(): Promise<void>;
10
10
 
11
11
  /** Lint the provided text. */
12
- lint(text: string): Promise<Lint[]>;
12
+ lint(text: string, options?: LintOptions): Promise<Lint[]>;
13
13
 
14
14
  /** Apply a suggestion to the given text, returning the transformed result. */
15
15
  applySuggestion(text: string, suggestion: Suggestion, span: Span): Promise<string>;
@@ -1,9 +1,10 @@
1
1
  import type { Lint, Span, Suggestion, Linter as WasmLinter } from 'wasm';
2
+ import { Language } from 'wasm';
2
3
  import Linter from './Linter';
3
4
  import loadWasm from './loadWasm';
4
- import { LintConfig } from './main';
5
+ import { LintConfig, LintOptions } from './main';
5
6
 
6
- /** A Linter that runs in the current JavaScript context (meaning it is allowed to block the event loop). */
7
+ /** A Linter that runs in the current JavaScript context (meaning it is allowed to block the event loop). */
7
8
  export default class LocalLinter implements Linter {
8
9
  private inner: WasmLinter | undefined;
9
10
 
@@ -18,15 +19,15 @@ export default class LocalLinter implements Linter {
18
19
 
19
20
  async setup(): Promise<void> {
20
21
  await this.initialize();
21
- this.inner!.lint('');
22
+ this.inner!.lint('', Language.Plain);
22
23
  }
23
24
 
24
- async lint(text: string): Promise<Lint[]> {
25
+ async lint(text: string, options?: LintOptions): Promise<Lint[]> {
25
26
  await this.initialize();
26
- let lints = this.inner!.lint(text);
27
-
28
- // We only want to show fixable errors.
29
- lints = lints.filter((lint) => lint.suggestion_count() > 0);
27
+ const lints = this.inner!.lint(
28
+ text,
29
+ options?.language === 'plaintext' ? Language.Plain : Language.Markdown
30
+ );
30
31
 
31
32
  return lints;
32
33
  }
@@ -3,7 +3,7 @@ import type { Lint, Suggestion, Span } from 'wasm';
3
3
  import Linter from '../Linter';
4
4
  import Worker from './worker.js?worker&inline';
5
5
  import { getWasmUri } from '../loadWasm';
6
- import { LintConfig } from '../main';
6
+ import { LintConfig, LintOptions } from '../main';
7
7
 
8
8
  /** The data necessary to complete a request once the worker has responded. */
9
9
  type RequestItem = {
@@ -15,8 +15,7 @@ type RequestItem = {
15
15
  /** A Linter that spins up a dedicated web worker to do processing on a separate thread.
16
16
  * Main benefit: this Linter will not block the event loop for large documents.
17
17
  *
18
- * NOTE: This class will not work properly in Node. In that case, just use `LocalLinter`.
19
- * Also requires top-level await to work. */
18
+ * NOTE: This class will not work properly in Node. In that case, just use `LocalLinter`. */
20
19
  export default class WorkerLinter implements Linter {
21
20
  private worker;
22
21
  private requestQueue: RequestItem[];
@@ -62,8 +61,8 @@ export default class WorkerLinter implements Linter {
62
61
  return this.rpc('setup', []);
63
62
  }
64
63
 
65
- lint(text: string): Promise<Lint[]> {
66
- return this.rpc('lint', [text]);
64
+ lint(text: string, options?: LintOptions): Promise<Lint[]> {
65
+ return this.rpc('lint', [text, options]);
67
66
  }
68
67
 
69
68
  applySuggestion(text: string, suggestion: Suggestion, span: Span): Promise<string> {
package/src/main.ts CHANGED
@@ -1,14 +1,18 @@
1
1
  import type { Lint, Span, Suggestion } from 'wasm';
2
+ import { SuggestionKind } from 'wasm';
2
3
  import Linter from './Linter';
3
4
  import LocalLinter from './LocalLinter';
4
5
  import WorkerLinter from './WorkerLinter';
5
6
 
6
- export { LocalLinter, WorkerLinter };
7
+ export { LocalLinter, WorkerLinter, SuggestionKind };
7
8
  export type { Linter, Lint, Span, Suggestion };
8
9
 
9
- export enum SuggestionKind {
10
- Replace = 0,
11
- Remove = 1
12
- }
13
-
10
+ /** A linting rule configuration dependent on upstream Harper's available rules.
11
+ * This is a record, since you shouldn't hard-code the existence of any particular rules and should generalize based on this struct. */
14
12
  export type LintConfig = Record<string, boolean | undefined>;
13
+
14
+ /** The option used to configure the parser for an individual linting operation. */
15
+ export type LintOptions = {
16
+ /** The markup language that is being passed. Defaults to `markdown`. */
17
+ language?: 'plaintext' | 'markdown';
18
+ };
package/tsconfig.json CHANGED
@@ -16,7 +16,10 @@
16
16
  "noUnusedLocals": true,
17
17
  "noUnusedParameters": true,
18
18
  "noFallthroughCasesInSwitch": true,
19
- "types": ["vite/client"]
19
+ "types": ["vite/client"],
20
+ "paths": {
21
+ "wasm": ["../../harper-wasm/pkg"]
22
+ }
20
23
  },
21
24
  "include": ["src"]
22
25
  }
package/vite.config.js CHANGED
@@ -2,6 +2,12 @@ import { resolve } from 'path';
2
2
  import dts from 'vite-plugin-dts';
3
3
  import { defineConfig } from 'vite';
4
4
  import virtual from 'vite-plugin-virtual';
5
+ import fs from 'fs';
6
+
7
+ function fileAsObject(path) {
8
+ let content = fs.readFileSync(path);
9
+ return JSON.parse(content);
10
+ }
5
11
 
6
12
  export default defineConfig({
7
13
  build: {
@@ -19,7 +25,11 @@ export default defineConfig({
19
25
  },
20
26
  base: './',
21
27
  plugins: [
22
- dts({ rollupTypes: true, tsconfigPath: './tsconfig.json' }),
28
+ dts({
29
+ ...fileAsObject('./api-extractor.json'),
30
+ rollupTypes: true,
31
+ tsconfigPath: './tsconfig.json'
32
+ }),
23
33
  virtual({
24
34
  'virtual:wasm': `import wasmUri from 'wasm/harper_wasm_bg.wasm?inline'; export default wasmUri`
25
35
  })
package/src/main.test.ts DELETED
@@ -1,8 +0,0 @@
1
- import { expect, test } from 'vitest';
2
- import { SuggestionKind as WasmSuggestionKind } from 'wasm';
3
- import { SuggestionKind } from './main';
4
-
5
- test('Wasm and JS SuggestionKinds agree', async () => {
6
- expect(SuggestionKind.Remove).toBe(WasmSuggestionKind.Remove);
7
- expect(SuggestionKind.Replace).toBe(WasmSuggestionKind.Replace);
8
- });