Skip to content

Commit 36dcddd

Browse files
authored
Add types
Closes GH-44. Reviewed-by: Dan Flettre <[email protected]>
1 parent b9f19db commit 36dcddd

7 files changed

+79
-15
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ build/Release
2929
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
3030
node_modules
3131
package-lock.json
32+
33+
*.d.ts

index.js

+26-4
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,19 @@ export default class BananaSlug {
1010
* Create a new slug class.
1111
*/
1212
constructor () {
13+
/** @type {Record<string, number>} */
14+
// eslint-disable-next-line no-unused-expressions
15+
this.occurrences
16+
1317
this.reset()
1418
}
1519

1620
/**
1721
* Generate a unique slug.
22+
*
23+
* Track previously generated slugs: repeated calls with the same value
24+
* will result in different slugs.
25+
* Use the `slug` function to get same slugs.
1826
*
1927
* @param {string} value
2028
* String of text to slugify
@@ -48,8 +56,22 @@ export default class BananaSlug {
4856
}
4957
}
5058

51-
export function slug (string, maintainCase) {
52-
if (typeof string !== 'string') return ''
53-
if (!maintainCase) string = string.toLowerCase()
54-
return string.replace(regex, '').replace(/ /g, '-')
59+
/**
60+
* Generate a slug.
61+
*
62+
* Does not track previously generated slugs: repeated calls with the same value
63+
* will result in the exact same slug.
64+
* Use the `GithubSlugger` class to get unique slugs.
65+
*
66+
* @param {string} value
67+
* String of text to slugify
68+
* @param {boolean} [maintainCase=false]
69+
* Keep the current case, otherwise make all lowercase
70+
* @return {string}
71+
* A unique slug string
72+
*/
73+
export function slug (value, maintainCase) {
74+
if (typeof value !== 'string') return ''
75+
if (!maintainCase) value = value.toLowerCase()
76+
return value.replace(regex, '').replace(/ /g, '-')
5577
}

package.json

+16-7
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@
1111
"url": "https://github.com/Flet/github-slugger/issues"
1212
},
1313
"type": "module",
14+
"main": "index.js",
15+
"types": "index.d.ts",
1416
"files": [
17+
"index.d.ts",
1518
"index.js",
19+
"regex.d.ts",
1620
"regex.js"
1721
],
1822
"devDependencies": {
1923
"@octokit/rest": "^19.0.0",
24+
"@types/regenerate": "^1.0.0",
25+
"@types/tape": "^4.0.0",
2026
"@unicode/unicode-13.0.0": "^1.0.0",
2127
"c8": "^7.0.0",
2228
"hast-util-select": "^5.0.0",
@@ -25,9 +31,12 @@
2531
"node-fetch": "^3.0.0",
2632
"regenerate": "^1.0.0",
2733
"rehype-parse": "^8.0.0",
34+
"rimraf": "^3.0.0",
2835
"standard": "*",
2936
"tap-spec": "^5.0.0",
3037
"tape": "^5.0.0",
38+
"type-coverage": "^2.0.0",
39+
"typescript": "^4.0.0",
3140
"unified": "^10.0.0"
3241
},
3342
"homepage": "https://github.com/Flet/github-slugger",
@@ -42,21 +51,21 @@
4251
"url"
4352
],
4453
"license": "ISC",
45-
"main": "index.js",
4654
"repository": {
4755
"type": "git",
4856
"url": "https://github.com/Flet/github-slugger.git"
4957
},
5058
"scripts": {
59+
"prepack": "npm run build && npm run format",
60+
"build": "rimraf \"{script,test}/**/*.d.ts\" \"*.d.ts\" && tsc && type-coverage",
5161
"format": "standard --fix",
5262
"test-api": "tape test | tap-spec",
5363
"test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api",
54-
"test": "npm run format && npm run test-coverage"
64+
"test": "npm run build && npm run format && npm run test-coverage"
5565
},
56-
"nyc": {
57-
"check-coverage": true,
58-
"lines": 100,
59-
"functions": 100,
60-
"branches": 100
66+
"typeCoverage": {
67+
"atLeast": 100,
68+
"detail": true,
69+
"strict": true
6170
}
6271
}

script/generate-fixtures.js

+14-3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ main()
7070

7171
async function main () {
7272
const files = await fs.readdir(categoryBase)
73+
/** @type {Array<{name: string, input: string, markdownOverwrite?: string, expected?: string}>} */
7374
const tests = [...otherTests]
7475
let index = -1
7576

@@ -86,7 +87,10 @@ async function main () {
8687
if (name === 'Other') continue
8788

8889
const fp = `./${name}/code-points.js`
89-
const { default: codePoints } = await import(new URL(fp, categoryBase))
90+
91+
/** @type {{default: Array<number>}} */
92+
const { default: codePoints } = await import(new URL(fp, categoryBase).href)
93+
/** @type {Array<number>} */
9094
const subs = []
9195

9296
let n = -1
@@ -112,7 +116,11 @@ async function main () {
112116
}
113117
})
114118

115-
const file = gistResult.data.files[filename]
119+
const file = (gistResult.data.files || {})[filename]
120+
121+
if (!file || !gistResult.data.html_url || !gistResult.data.id) {
122+
throw new Error('Something weird happened contacting GitHub')
123+
}
116124

117125
if (!file.language) {
118126
throw new Error('The generated markdown was seen as binary data instead of text by GitHub. This is likely because there are weird characters (such as control characters or lone surrogates) in it')
@@ -138,7 +146,10 @@ async function main () {
138146
const anchors = selectAll('h1 .anchor', markdownBody)
139147

140148
anchors.forEach((node, i) => {
141-
tests[i].expected = node.properties.href.slice(1)
149+
const href = (node.properties || {}).href
150+
if (typeof href === 'string') {
151+
tests[i].expected = href.slice(1)
152+
}
142153
})
143154

144155
await fs.writeFile(new URL('../test/fixtures.json', import.meta.url), JSON.stringify(tests, null, 2) + '\n')

script/generate-regex.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { promises as fs } from 'node:fs'
22
import regenerate from 'regenerate'
3+
// @ts-expect-error: untyped
34
import alphabetics from '@unicode/unicode-13.0.0/Binary_Property/Alphabetic/code-points.js'
45

56
const categoryBase = new URL('../node_modules/@unicode/unicode-13.0.0/General_Category/', import.meta.url)
@@ -40,7 +41,8 @@ async function main () {
4041
while (++index < ranges.length) {
4142
const name = ranges[index]
4243
const fp = `./${name}/code-points.js`
43-
const { default: codePoints } = await import(new URL(fp, categoryBase))
44+
/** @type {{default: Array<number>}} */
45+
const { default: codePoints } = await import(new URL(fp, categoryBase).href)
4446

4547
generator.add(codePoints)
4648
}

test/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from 'node:fs'
22
import test from 'tape'
33
import GithubSlugger, { slug } from '../index.js'
44

5+
/** @type {Array<{name: string, input: string, markdownOverwrite?: string, expected: string}>} */
56
const fixtures = JSON.parse(
67
String(fs.readFileSync(
78
new URL('fixtures.json', import.meta.url)
@@ -11,6 +12,7 @@ const fixtures = JSON.parse(
1112
test('simple stuff', function (t) {
1213
const slugger = new GithubSlugger()
1314

15+
// @ts-expect-error: not allowed by types but handled gracefully in the code.
1416
t.equals(slugger.slug(1), '', 'should return empty string for non-strings')
1517

1618
// Note: GH doesn’t support `maintaincase`, so the actual values are commented below.

tsconfig.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"include": ["script/**/*.js", "test/**/*.js", "*.js"],
3+
"compilerOptions": {
4+
"target": "es2022",
5+
"lib": ["es2022"],
6+
"module": "esnext",
7+
"moduleResolution": "node",
8+
"allowJs": true,
9+
"checkJs": true,
10+
"declaration": true,
11+
"emitDeclarationOnly": true,
12+
"allowSyntheticDefaultImports": true,
13+
"skipLibCheck": true,
14+
"strict": true
15+
}
16+
}

0 commit comments

Comments
 (0)