Skip to content

Commit

Permalink
fix(performance): #201 spawn hunspell and use pipe to get results fro…
Browse files Browse the repository at this point in the history
…m hunspell
  • Loading branch information
rainer-exxcellent committed Feb 7, 2025
1 parent 5ed7383 commit ccd35cc
Showing 1 changed file with 54 additions and 9 deletions.
63 changes: 54 additions & 9 deletions lib/informativeTests/informativeTest_6_3_8.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import Ajv from 'ajv/dist/jtd.js'
import { execFile } from 'node:child_process'
import bcp47 from 'bcp47'
import { spawn } from 'child_process'
import { createInterface } from 'node:readline/promises'
import { EOL } from 'node:os'

const ajv = new Ajv()
// cache results of spell to improve perfromance
const spellCheckedWords2Result = new Map()
/**
* @type {import("child_process").ChildProcessWithoutNullStreams}
*/
let hunspellSpawn
/**
* @type {import("readline/promises").Interface}
*/
let hunspellInterface

const inputSchema = /** @type {const} */ ({
additionalProperties: true,
Expand Down Expand Up @@ -250,7 +260,9 @@ export default async function informativeTest_6_3_8(
typeof lang.langtag.region === 'string' ? `_${lang.langtag.region}` : ''
}`
// @ts-ignore
const segmenter = new Intl.Segmenter([dictionary], { granularity: 'word' })
const segmenter = new Intl.Segmenter(lang.langtag.language, {
granularity: 'word',
})
const urlPattern = /(https?|ftp):\/\/[^\s/$.?#].[^\s]*/i

for (const path of [
Expand Down Expand Up @@ -404,6 +416,10 @@ export default async function informativeTest_6_3_8(
}
}

if (hunspellSpawn) {
hunspellInterface.close()
hunspellSpawn.kill('SIGINT')
}
return ctx
}

Expand All @@ -416,7 +432,8 @@ export default async function informativeTest_6_3_8(
async function spellCheckString({ text, dictionary, hunspell }) {
/** @type {string} */
const result = await hunspell({ dictionary, input: text })
const lines = result.split('\n').slice(1)

const lines = result.split('\n')
const errors = lines
.filter((l) => l.startsWith('# ') || l.startsWith('& '))
.map((l) => {
Expand All @@ -442,13 +459,41 @@ async function spellCheckString({ text, dictionary, hunspell }) {
* @returns
*/
async function runHunspell({ dictionary, input }) {
/** @type {string} */
const result = await new Promise((resolve, reject) => {
const child = execFile('hunspell', ['-d', dictionary], (err, stdout) => {
if (err) return reject(err)
resolve(stdout)
// lacy initialize hunspellSpawn
if (!hunspellSpawn) {
hunspellSpawn = spawn('hunspell', ['-d', dictionary], {
stdio: 'pipe',
shell: true,
})
child.stdin?.end(input)
hunspellInterface = createInterface(hunspellSpawn.stdout)
}

// @ts-ignore
const result = await new Promise((resolve) => {
/** @type {string[]} */
const buffer = []
/** @param {string} line */
const handler = (line) => {
if (line !== '') buffer.push(line)
else {
hunspellInterface.off('line', handler)
resolve(buffer.join(EOL))
}
}
hunspellInterface.on('line', handler)
hunspellSpawn.stdin.write(input + EOL)
})

/** @type {string} */
return result
}

/**
* @param {object} params
* @param {string} params.dictionary
* @param {string} params.input
* @returns
*/
async function runHunspellMock({ dictionary, input }) {
return ''
}

0 comments on commit ccd35cc

Please sign in to comment.