nlcst-is-literal
Advanced tools
Comparing version 2.1.0 to 2.1.1
@@ -1,14 +0,1 @@ | ||
/** | ||
* Check if the node in `parent` at `position` is enclosed by matching | ||
* delimiters. | ||
* | ||
* @param {Parent} parent | ||
* @param {number} index | ||
* @returns {boolean} | ||
*/ | ||
export function isLiteral(parent: Parent, index: number): boolean | ||
export type UnistParent = import('unist').Parent | ||
export type Root = import('nlcst').Root | ||
export type Content = import('nlcst').Content | ||
export type Node = Root | Content | ||
export type Parent = Extract<Node, UnistParent> | ||
export {isLiteral} from './lib/index.js' |
144
index.js
@@ -1,143 +0,1 @@ | ||
/** | ||
* @typedef {import('unist').Parent} UnistParent | ||
* @typedef {import('nlcst').Root} Root | ||
* @typedef {import('nlcst').Content} Content | ||
* @typedef {Root|Content} Node | ||
* @typedef {Extract<Node, UnistParent>} Parent | ||
*/ | ||
import {toString} from 'nlcst-to-string' | ||
const single = [ | ||
'-', // Hyphen-minus | ||
'–', // En dash | ||
'—', // Em dash | ||
':', // Colon | ||
';' // Semi-colon | ||
] | ||
/** | ||
* Pair delimiters. | ||
* From common sense, and WikiPedia: | ||
* <https://en.wikipedia.org/wiki/Quotation_mark>. | ||
* | ||
* @type {Record<string, string[]>} | ||
*/ | ||
const pairs = { | ||
',': [','], | ||
'-': ['-'], | ||
'–': ['–'], | ||
'—': ['—'], | ||
'"': ['"'], | ||
"'": ["'"], | ||
'‘': ['’'], | ||
'‚': ['’'], | ||
'’': ['’', '‚'], | ||
'“': ['”'], | ||
'”': ['”'], | ||
'„': ['”', '“'], | ||
'«': ['»'], | ||
'»': ['«'], | ||
'‹': ['›'], | ||
'›': ['‹'], | ||
'(': [')'], | ||
'[': [']'], | ||
'{': ['}'], | ||
'⟨': ['⟩'], | ||
'「': ['」'] | ||
} | ||
const open = Object.keys(pairs) | ||
/** | ||
* Check if the node in `parent` at `position` is enclosed by matching | ||
* delimiters. | ||
* | ||
* @param {Parent} parent | ||
* @param {number} index | ||
* @returns {boolean} | ||
*/ | ||
export function isLiteral(parent, index) { | ||
if (!(parent && parent.children)) { | ||
throw new Error('Parent must be a node') | ||
} | ||
if (index !== null && typeof index === 'object' && 'type' in index) { | ||
index = parent.children.indexOf(index) | ||
if (index === -1) { | ||
throw new Error('Node must be a child of `parent`') | ||
} | ||
} | ||
if (typeof index !== 'number' || Number.isNaN(index)) { | ||
throw new TypeError('Index must be a number') | ||
} | ||
return Boolean( | ||
(!containsWord(parent, -1, index) && | ||
siblingDelimiter(parent, index, 1, single)) || | ||
(!containsWord(parent, index, parent.children.length) && | ||
siblingDelimiter(parent, index, -1, single)) || | ||
isWrapped(parent, index) | ||
) | ||
} | ||
/** | ||
* Check if the node in `parent` at `position` is enclosed by matching | ||
* delimiters. | ||
* @param {Parent} parent | ||
* @param {number} position | ||
* @returns {Node|void} | ||
*/ | ||
function isWrapped(parent, position) { | ||
const previous = siblingDelimiter(parent, position, -1, open) | ||
if (previous) { | ||
return siblingDelimiter(parent, position, 1, pairs[toString(previous)]) | ||
} | ||
} | ||
/** | ||
* Find the previous or next delimiter before or after `position` in `parent`. | ||
* Returns the delimiter node when found. | ||
* | ||
* @param {Parent} parent | ||
* @param {number} position | ||
* @param {number} step | ||
* @param {Array.<string>} delimiters | ||
* @returns {Node|void} | ||
*/ | ||
function siblingDelimiter(parent, position, step, delimiters) { | ||
let index = position + step | ||
while (index > -1 && index < parent.children.length) { | ||
const sibling = parent.children[index] | ||
if (sibling.type === 'WordNode' || sibling.type === 'SourceNode') { | ||
return | ||
} | ||
if (sibling.type !== 'WhiteSpaceNode') { | ||
return delimiters.includes(toString(sibling)) ? sibling : undefined | ||
} | ||
index += step | ||
} | ||
} | ||
/** | ||
* Check if parent contains word-nodes between `start` and `end` (both | ||
* excluding). | ||
* @param {Parent} parent | ||
* @param {number} start | ||
* @param {number} end | ||
* @returns {boolean|void} | ||
*/ | ||
function containsWord(parent, start, end) { | ||
while (++start < end) { | ||
if (parent.children[start].type === 'WordNode') { | ||
return true | ||
} | ||
} | ||
} | ||
export {isLiteral} from './lib/index.js' |
{ | ||
"name": "nlcst-is-literal", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "nlcst utility to check whether a node is meant literally", | ||
@@ -30,2 +30,3 @@ "license": "MIT", | ||
"files": [ | ||
"lib/", | ||
"index.d.ts", | ||
@@ -40,21 +41,19 @@ "index.js" | ||
"devDependencies": { | ||
"@types/tape": "^4.0.0", | ||
"@types/node": "^18.0.0", | ||
"c8": "^7.0.0", | ||
"parse-english": "^6.0.0", | ||
"prettier": "^2.0.0", | ||
"remark-cli": "^10.0.0", | ||
"remark-cli": "^11.0.0", | ||
"remark-preset-wooorm": "^9.0.0", | ||
"retext": "^8.0.0", | ||
"rimraf": "^3.0.0", | ||
"tape": "^5.0.0", | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^4.0.0", | ||
"unist-util-visit": "^4.0.0", | ||
"xo": "^0.44.0" | ||
"xo": "^0.53.0" | ||
}, | ||
"scripts": { | ||
"prepack": "npm run build && npm run format", | ||
"build": "rimraf \"*.d.ts\" && tsc && type-coverage", | ||
"build": "tsc --build --clean && tsc --build && type-coverage", | ||
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", | ||
"test-api": "node test.js", | ||
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test.js", | ||
"test-api": "node --conditions development test.js", | ||
"test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
@@ -61,0 +60,0 @@ }, |
124
readme.md
@@ -11,5 +11,27 @@ # nlcst-is-literal | ||
[**nlcst**][nlcst] utility to check if a node is meant literally. | ||
[nlcst][] utility to check if a node is meant literally. | ||
Useful if a tool wants to exclude values that are possibly void of meaning. | ||
## Contents | ||
* [What is this?](#what-is-this) | ||
* [When should I use this?](#when-should-i-use-this) | ||
* [Install](#install) | ||
* [Use](#use) | ||
* [API](#api) | ||
* [`isLiteral(parent, index|child)`](#isliteralparent-indexchild) | ||
* [Types](#types) | ||
* [Compatibility](#compatibility) | ||
* [Related](#related) | ||
* [Contribute](#contribute) | ||
* [License](#license) | ||
## What is this? | ||
This utility can check if a node is meant literally. | ||
## When should I use this? | ||
This package is a tiny utility that helps when dealing with words. | ||
It’s useful if a tool wants to exclude values that are possibly void of | ||
meaning. | ||
For example, a spell-checker could exclude these literal words, thus not warning | ||
@@ -20,7 +42,5 @@ about “monsieur”. | ||
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): | ||
Node 12+ is needed to use it and it must be `import`ed instead of `require`d. | ||
This package is [ESM only][esm]. | ||
In Node.js (version 14.14+ and 16.0+), install with [npm][]: | ||
[npm][]: | ||
```sh | ||
@@ -30,5 +50,19 @@ npm install nlcst-is-literal | ||
In Deno with [`esm.sh`][esmsh]: | ||
```js | ||
import {isLiteral} from 'https://esm.sh/nlcst-is-literal@2' | ||
``` | ||
In browsers with [`esm.sh`][esmsh]: | ||
```html | ||
<script type="module"> | ||
import {isLiteral} from 'https://esm.sh/nlcst-is-literal@2?bundle' | ||
</script> | ||
``` | ||
## Use | ||
Say we have the following file, `example.txt`: | ||
Say our document `example.txt` contains: | ||
@@ -47,8 +81,7 @@ ```txt | ||
And our script, `example.js`, looks as follows: | ||
…and our module `example.js` looks as follows: | ||
```js | ||
import {readSync} from 'to-vfile' | ||
import {unified} from 'unified' | ||
import retextEnglish from 'retext-english' | ||
import {read} from 'to-vfile' | ||
import {ParseEnglish} from 'parse-english' | ||
import {visit} from 'unist-util-visit' | ||
@@ -58,16 +91,13 @@ import {toString} from 'nlcst-to-string' | ||
const file = readSync('example.txt') | ||
const file = await read('example.txt') | ||
const tree = new ParseEnglish().parse(String(file)) | ||
const tree = unified().use(retextEnglish).parse(file) | ||
visit(tree, 'WordNode', visitor) | ||
function visitor(node, index, parent) { | ||
visit(tree, 'WordNode', function (node, index, parent) { | ||
if (isLiteral(parent, index)) { | ||
console.log(toString(node)) | ||
} | ||
} | ||
}) | ||
``` | ||
Now, running `node example` yields: | ||
…now running `node example.js` yields: | ||
@@ -84,3 +114,3 @@ ```txt | ||
This package exports the following identifiers: `isLiteral`. | ||
This package exports the identifier [`isLiteral`][isliteral]. | ||
There is no default export. | ||
@@ -90,4 +120,3 @@ | ||
Check if the `child` in `parent` is enclosed by matching delimiters. | ||
If `index` is given, the [child][] of `parent` at that [index][] is checked. | ||
Check if the child in `parent` at `index` is enclosed by matching delimiters. | ||
@@ -100,13 +129,38 @@ For example, `foo` is literal in the following samples: | ||
###### Parameters | ||
* `parent` ([`Node`][node]) | ||
— parent node | ||
* `index` (`number`) | ||
— index of child in parent | ||
* `child` ([`Node`][node]) | ||
— child node of parent | ||
###### Returns | ||
Whether the child is a literal (`boolean`). | ||
## Types | ||
This package is fully typed with [TypeScript][]. | ||
It exports no additional types. | ||
## Compatibility | ||
Projects maintained by the unified collective are compatible with all maintained | ||
versions of Node.js. | ||
As of now, that is Node.js 14.14+ and 16.0+. | ||
Our projects sometimes work with older versions, but this is not guaranteed. | ||
## Related | ||
* [`nlcst-normalize`](https://github.com/syntax-tree/nlcst-normalize) | ||
— Normalize a word for easier comparison | ||
— normalize a word for easier comparison | ||
* [`nlcst-search`](https://github.com/syntax-tree/nlcst-search) | ||
— Search for patterns | ||
— search for patterns | ||
## Contribute | ||
See [`contributing.md` in `syntax-tree/.github`][contributing] for ways to get | ||
started. | ||
See [`contributing.md`][contributing] in [`syntax-tree/.github`][health] for | ||
ways to get started. | ||
See [`support.md`][support] for ways to get help. | ||
@@ -152,2 +206,8 @@ | ||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c | ||
[esmsh]: https://esm.sh | ||
[typescript]: https://www.typescriptlang.org | ||
[license]: license | ||
@@ -157,12 +217,14 @@ | ||
[contributing]: https://github.com/syntax-tree/.github/blob/HEAD/contributing.md | ||
[health]: https://github.com/syntax-tree/.github | ||
[support]: https://github.com/syntax-tree/.github/blob/HEAD/support.md | ||
[contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md | ||
[coc]: https://github.com/syntax-tree/.github/blob/HEAD/code-of-conduct.md | ||
[support]: https://github.com/syntax-tree/.github/blob/main/support.md | ||
[coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md | ||
[nlcst]: https://github.com/syntax-tree/nlcst | ||
[index]: https://github.com/syntax-tree/unist#index | ||
[node]: https://github.com/syntax-tree/nlcst#nodes | ||
[child]: https://github.com/syntax-tree/unist#child | ||
[isliteral]: #isliteralparent-indexchild |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13709
10
7
189
221
1