diff --git a/packages/@textlint/compiler/package.json b/packages/@textlint/compiler/package.json index 11e102d..f327138 100644 --- a/packages/@textlint/compiler/package.json +++ b/packages/@textlint/compiler/package.json @@ -52,6 +52,7 @@ "dependencies": { "@textlint/config-loader": "^0.3.0", "@textlint/kernel": "^3.3.6", + "@textlint/types": "^1.4.5", "@textlint/runtime-helper": "^0.3.0", "meow": "^7.0.1", "rimraf": "^3.0.2", diff --git a/packages/@textlint/compiler/src/CodeGenerator/API.ts b/packages/@textlint/compiler/src/CodeGenerator/API.ts new file mode 100644 index 0000000..0702d63 --- /dev/null +++ b/packages/@textlint/compiler/src/CodeGenerator/API.ts @@ -0,0 +1,14 @@ +import type { TextlintFixResult, TextlintMessage, TextlintResult } from "@textlint/types"; + +/** + * textlint Server API + */ +export type API = { + lint({ text, ext }: { text: string; ext: string }): TextlintResult[]; + // fix all text with all rule + fixAll({ text, ext }: { text: string; ext: string }): TextlintFixResult; + // fix all with with a rule + fixRule({ text, ext, message }: { text: string; ext: string; message: TextlintMessage }): TextlintFixResult; + // fix the text + fixText({ text, ext, message }: { text: string; ext: string; message: TextlintMessage }): { output: string }; +}; diff --git a/packages/textchecker-element/public/index.ts b/packages/textchecker-element/public/index.ts index 3967bec..f296a03 100644 --- a/packages/textchecker-element/public/index.ts +++ b/packages/textchecker-element/public/index.ts @@ -1,10 +1,11 @@ -import { attachToTextArea, AttachTextAreaParams } from "../src/index"; +import { attachToTextArea } from "../src/index"; import type { TextlintFixResult, TextlintMessage, TextlintResult } from "@textlint/types"; import type { TextlintWorkerCommandFix, TextlintWorkerCommandLint, TextlintWorkerCommandResponse } from "@textlint/compiler"; +import { LintEngineAPI } from "../src/attach-to-text-area"; const statusElement = document.querySelector("#js-status"); const updateStatus = (status: string) => { @@ -42,7 +43,7 @@ const waiterForInit = (worker: Worker) => { const workerStatus = waiterForInit(worker); const createTextlint = ({ ext }: { ext: string }) => { - const lintText: AttachTextAreaParams["lintText"] = async ({ text }: { text: string }): Promise => { + const lintText: LintEngineAPI["lintText"] = async ({ text }: { text: string }): Promise => { updateStatus("linting..."); return new Promise((resolve, _reject) => { worker.addEventListener( @@ -50,7 +51,7 @@ const createTextlint = ({ ext }: { ext: string }) => { function (event) { const data: TextlintWorkerCommandResponse = event.data; if (data.command === "lint:result") { - resolve(data.result); + resolve([data.result]); } updateStatus("linted"); }, @@ -65,12 +66,12 @@ const createTextlint = ({ ext }: { ext: string }) => { } as TextlintWorkerCommandLint); }); }; - const fixText: AttachTextAreaParams["fixText"] = async ({ + const fixText = async ({ text, message }: { text: string; - message: TextlintMessage; + message?: TextlintMessage; }): Promise => { updateStatus("fixing..."); return new Promise((resolve, _reject) => { @@ -90,7 +91,7 @@ const createTextlint = ({ ext }: { ext: string }) => { return worker.postMessage({ command: "fix", text, - ruleId: message.ruleId, + ruleId: message?.ruleId, ext: ext } as TextlintWorkerCommandFix); }); @@ -106,6 +107,24 @@ const createTextlint = ({ ext }: { ext: string }) => { const targetElement = document.querySelectorAll("textarea"); const textlint = createTextlint({ ext: ".md" }); await workerStatus.ready(); + const lintEngine: LintEngineAPI = { + lintText: textlint.lintText, + fixText: async ({ text, message }): Promise<{ output: string }> => { + if (!message.fix || !message.fix.range) { + return { output: text }; + } + // replace fix.range[0, 1] with fix.text + return { + output: text.slice(0, message.fix.range[0]) + message.fix.text + text.slice(message.fix.range[1]) + }; + }, + fixAll({ text }: { text: string }): Promise { + return textlint.fixText({ text }); + }, + fixRule({ text, message }: { text: string; message: TextlintMessage }): Promise { + return textlint.fixText({ text, message }); + } + }; targetElement.forEach((element) => { if (text) { element.value = text; @@ -113,8 +132,7 @@ const createTextlint = ({ ext }: { ext: string }) => { attachToTextArea({ textAreaElement: element, lintingDebounceMs: 200, - lintText: textlint.lintText, - fixText: textlint.fixText + lintEngine }); }); })(); diff --git a/packages/textchecker-element/src/attach-to-text-area.ts b/packages/textchecker-element/src/attach-to-text-area.ts index 9b053c4..f48819b 100644 --- a/packages/textchecker-element/src/attach-to-text-area.ts +++ b/packages/textchecker-element/src/attach-to-text-area.ts @@ -18,6 +18,19 @@ const createCompositionHandler = () => { }; }; +/** + * Lint Server API + */ +export type LintEngineAPI = { + lintText({ text }: { text: string }): Promise; + // fix all text with all rule + fixAll({ text }: { text: string }): Promise; + // fix all with with a rule + fixRule({ text, message }: { text: string; message: TextlintMessage }): Promise; + // fix the text + fixText({ text, message }: { text: string; message: TextlintMessage }): Promise<{ output: string }>; +}; + export type AttachTextAreaParams = { /** * target textarea element @@ -28,15 +41,14 @@ export type AttachTextAreaParams = { * default: 200ms */ lintingDebounceMs: number; - // process - lintText: ({ text }: { text: string }) => Promise; - fixText: ({ text, message }: { text: string; message: TextlintMessage }) => Promise; + // user should implement LintEngineAPI and pass it + lintEngine: LintEngineAPI; }; /** * Attach text-checker component to `