Skip to content

Commit

Permalink
Refactor code-style
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Sep 10, 2023
1 parent e2fe800 commit b49984f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 94 deletions.
123 changes: 58 additions & 65 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,64 @@
/**
* @typedef {import('nlcst').Root} Root
*
* @typedef {0|1|2|'newline'|'space'|'double-space'|null|undefined} Preferred
*
* @typedef {import('vfile').VFile} VFile
*/

/**
* @typedef Options
* Configuration.
* @property {Preferred} [preferred=1]
* Spaces between sentences.
* Use `0` for line endings.
* @property {'double-space' | 'newline' | 'space' | 0 | 1 | 2 | null | undefined} [preferred='space']
* Spaces between sentences (default: `'space'`).
*/

import {toString} from 'nlcst-to-string'
import {visit} from 'unist-util-visit'
import {convert} from 'unist-util-is'

const sentence = convert('SentenceNode')
const whiteSpace = convert('WhiteSpaceNode')

const source = 'retext-sentence-spacing'
const url = 'https://github.com/retextjs/retext-sentence-spacing#readme'
/** @type {Readonly<Options>} */
const emptyOptions = {}

/**
* Plugin to check spacing between sentences.
* Emit warnings when the spacing does not adhere to the preferred style.
* Ccheck spacing between sentences.
*
* @type {import('unified').Plugin<[Options?], Root>}
* @param {Readonly<Options> | null | undefined} [options]
* Configuration (optional).
* @returns
* Transform.
*/
export default function retextSentenceSpacing(options = {}) {
let preferred = options.preferred

if (preferred === 'newline') {
preferred = 0
}

if (preferred === null || preferred === undefined || preferred === 'space') {
preferred = 1
}

if (preferred === 'double-space') {
preferred = 2
}

if (typeof preferred !== 'number') {
throw new TypeError(
"Expected `options.preferred` to be `'space'`, `'newline'`, or a `number`"
)
}

if (preferred < 0 || preferred > 2) {
throw new Error(
"Expected `options.preferred` to be `'space'`, `'newline'`, or a `number` between (including) `0` and `2`"
)
}

return (tree, file) => {
visit(tree, 'ParagraphNode', (node) => {
export default function retextSentenceSpacing(options) {
const settings = options || emptyOptions
const preferred =
settings.preferred === 'double-space' || settings.preferred === 2
? 2
: settings.preferred === 'newline' || settings.preferred === 0
? 0
: 1

/**
* Transform.
*
* @param {Root} tree
* Tree.
* @param {VFile} file
* File.
* @returns {undefined}
* Nothing.
*/
return function (tree, file) {
visit(tree, 'ParagraphNode', function (node) {
let index = -1

while (++index < node.children.length) {
const previous = node.children[index - 1]
const child = node.children[index]
const next = node.children[index + 1]

if (
!sentence(node.children[index - 1]) ||
!whiteSpace(child) ||
!sentence(node.children[index + 1])
!previous ||
previous.type !== 'SentenceNode' ||
child.type !== 'WhiteSpaceNode' ||
!next ||
next.type !== 'SentenceNode'
) {
continue
}
Expand Down Expand Up @@ -100,25 +95,23 @@ export default function retextSentenceSpacing(options = {}) {
'`'
}

Object.assign(
file.message(
reason,
child,
[
source,
preferred === 0
? 'newline'
: preferred === 1
? 'space'
: 'double-space'
].join(':')
),
{
actual,
expected: [preferred === 0 ? '\n' : preferred === 1 ? ' ' : ' '],
url
}
)
const message = file.message(reason, {
place: child.position,
ruleId:
preferred === 0
? 'newline'
: preferred === 1
? 'space'
: 'double-space',
source: 'retext-sentence-spacing'
})

message.actual = actual
message.expected = [
preferred === 0 ? '\n' : preferred === 1 ? ' ' : ' '
]
message.url =
'https://github.com/retextjs/retext-sentence-spacing#readme'
}
})
}
Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,9 @@
],
"dependencies": {
"@types/nlcst": "^2.0.0",
"@types/unist": "^3.0.0",
"nlcst-to-string": "^4.0.0",
"unified": "^11.0.0",
"unist-util-is": "^6.0.0",
"unist-util-visit": "^5.0.0"
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
Expand Down
31 changes: 6 additions & 25 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/**
* @typedef {import('./lib/index.js').Preferred} Preferred
*/

import assert from 'node:assert/strict'
import test from 'node:test'
import {retext} from 'retext'
Expand All @@ -16,6 +12,12 @@ const mixed = [
].join('\n')

test('retextSentenceSpacing', async function (t) {
await t.test('should expose the public api', async function () {
assert.deepEqual(Object.keys(await import('./index.js')).sort(), [
'default'
])
})

await t.test('should emit a message w/ metadata', async function () {
const file = await retext()
.use(retextSentenceSpacing, {preferred: 1})
Expand Down Expand Up @@ -120,25 +122,4 @@ test('retextSentenceSpacing', async function (t) {
assert.deepEqual(file.messages.map(String), [])
}
)

await t.test('should throw for preferred lower than 1', async function () {
assert.throws(() => {
// @ts-expect-error: runtime.
retext().use(retextSentenceSpacing, {preferred: -1}).freeze()
}, /Error: Expected `options.preferred` to be `'space'`, `'newline'`, or a `number` between \(including\) `0` and `2`/)
})

await t.test('should throw for preferred higher than 2', async function () {
assert.throws(() => {
// @ts-expect-error: runtime.
retext().use(retextSentenceSpacing, {preferred: 3}).freeze()
}, /Error: Expected `options.preferred` to be `'space'`, `'newline'`, or a `number` between \(including\) `0` and `2`/)
})

await t.test('should throw for non-numbers', async function () {
assert.throws(() => {
// @ts-expect-error: runtime.
retext().use(retextSentenceSpacing, {preferred: 'foo'}).freeze()
}, /Error: Expected `options.preferred` to be `'space'`, `'newline'`, or a `number`/)
})
})

0 comments on commit b49984f

Please sign in to comment.