From 33fc37964653585948bb021ed0cccf945972498f Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 1 Oct 2024 14:36:37 +0200 Subject: [PATCH] Deprecate --- .editorconfig | 9 - .github/workflows/bb.yml | 13 -- .github/workflows/main.yml | 21 --- .gitignore | 6 - .npmrc | 1 - .prettierignore | 3 - .remarkignore | 1 - index.js | 274 ------------------------------ license | 24 --- package.json | 77 +-------- readme.md | 18 +- test/fixtures/input.md | 1 - test/fixtures/output.after.html | 2 - test/fixtures/output.append.html | 1 - test/fixtures/output.before.html | 2 - test/fixtures/output.html | 1 - test/fixtures/output.prepend.html | 1 - test/fixtures/output.wrap.html | 1 - test/index.js | 171 ------------------- tsconfig.json | 16 -- 20 files changed, 5 insertions(+), 638 deletions(-) delete mode 100644 .editorconfig delete mode 100644 .github/workflows/bb.yml delete mode 100644 .github/workflows/main.yml delete mode 100644 .gitignore delete mode 100644 .npmrc delete mode 100644 .prettierignore delete mode 100644 .remarkignore delete mode 100644 index.js delete mode 100644 license delete mode 100644 test/fixtures/input.md delete mode 100644 test/fixtures/output.after.html delete mode 100644 test/fixtures/output.append.html delete mode 100644 test/fixtures/output.before.html delete mode 100644 test/fixtures/output.html delete mode 100644 test/fixtures/output.prepend.html delete mode 100644 test/fixtures/output.wrap.html delete mode 100644 test/index.js delete mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index c6c8b36..0000000 --- a/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true diff --git a/.github/workflows/bb.yml b/.github/workflows/bb.yml deleted file mode 100644 index 0198fc3..0000000 --- a/.github/workflows/bb.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: bb -on: - issues: - types: [opened, reopened, edited, closed, labeled, unlabeled] - pull_request_target: - types: [opened, reopened, edited, closed, labeled, unlabeled] -jobs: - main: - runs-on: ubuntu-latest - steps: - - uses: unifiedjs/beep-boop-beta@main - with: - repo-token: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index fe284ad..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: main -on: - - pull_request - - push -jobs: - main: - name: ${{matrix.node}} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: dcodeIO/setup-node-nvm@master - with: - node-version: ${{matrix.node}} - - run: npm install - - run: npm test - - uses: codecov/codecov-action@v1 - strategy: - matrix: - node: - - lts/erbium - - node diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 53a29e3..0000000 --- a/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -coverage/ -node_modules/ -.DS_Store -*.d.ts -*.log -yarn.lock diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 43c97e7..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 619aa6b..0000000 --- a/.prettierignore +++ /dev/null @@ -1,3 +0,0 @@ -coverage/ -*.html -*.md diff --git a/.remarkignore b/.remarkignore deleted file mode 100644 index c912533..0000000 --- a/.remarkignore +++ /dev/null @@ -1 +0,0 @@ -__tests__ diff --git a/index.js b/index.js deleted file mode 100644 index b1ddd90..0000000 --- a/index.js +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @typedef {import('mdast').Root} Root - * @typedef {import('mdast').Heading} Heading - * @typedef {import('mdast').Link} Link - * @typedef {import('mdast').Blockquote} Blockquote - * @typedef {import('mdast').BlockContent} BlockContent - * @typedef {import('mdast').StaticPhrasingContent} StaticPhrasingContent - * @typedef {import('mdast').PhrasingContent} PhrasingContent - * @typedef {import('hast').Element} Element - * @typedef {Element['children'][number]} ElementChild - * @typedef {import('hast').Properties} Properties - * - * @callback Build - * @param {Heading} node - * @returns {ElementChild|ElementChild[]} - * - * @callback BuildGroup - * @param {Heading} node - * @returns {Element} - * - * @typedef BaseOptions - * @property {Properties} [linkProperties] - * Extra properties to set on the link when injecting. - * Defaults to `{ariaHidden: true, tabIndex: -1}` when `'prepend'` or - * `'append'`. - * @property {ElementChild|ElementChild[]|Build} [content={type: 'element', tagName: 'span', properties: {className: ['icon', 'icon-link']}, children: []}] - * Nodes (hast) to insert in the link. - * @property {Element|BuildGroup} [group] - * Node (hast) to wrap the heading and link with, if `behavior` is `'before'` or - * `'after'`. - * There is no default. - * - * @typedef BeforeFields - * @property {'before'} behavior - * Insert link before the heading. - * - * @typedef AfterFields - * @property {'after'} behavior - * Insert link after the heading. - * - * @typedef WrapFields - * @property {'wrap'} behavior - * Wrap the whole heading text with the link. - * - * @typedef PrependFields - * @property {'prepend'} behavior - * Inject link before the heading text. - * - * @typedef AppendFields - * @property {'append'} behavior - * Inject link after the heading text. - * - * @typedef {BaseOptions & BeforeFields} BeforeOptions - * @typedef {BaseOptions & AfterFields} AfterOptions - * @typedef {Pick & WrapFields} WrapOptions - * @typedef {Pick & PrependFields} PrependOptions - * @typedef {Pick & AppendFields} AppendOptions - * - * @typedef {BaseOptions|BeforeOptions|AfterOptions|WrapOptions|PrependOptions|AppendOptions} Options - */ - -import {visit, SKIP} from 'unist-util-visit' -import extend from 'extend' - -/** @type {Element} */ -const contentDefaults = { - type: 'element', - tagName: 'span', - properties: {className: ['icon', 'icon-link']}, - children: [] -} - -/** - * Plugin to automatically add links to headings (h1-h6). - * - * @type {import('unified').Plugin<[Options?]|void[], Root>} - */ -export default function rehypeAutolinkHeadings(options = {}) { - let props = options.linkProperties - const behavior = ('behavior' in options && options.behavior) || 'prepend' - const content = ('content' in options && options.content) || contentDefaults - const group = 'group' in options ? options.group : undefined - /** @type {import('unist-util-visit').Visitor} */ - let method - - if (behavior === 'wrap') { - method = wrap - } else if (behavior === 'before' || behavior === 'after') { - method = around - } else { - if (!props) { - props = {ariaHidden: 'true', tabIndex: -1} - } - - method = inject - } - - return (tree) => { - visit(tree, 'heading', method) - } - - /** @type {import('unist-util-visit').Visitor} */ - function inject(node) { - const url = getUrl(node) - - if (url) { - const link = create(url) - - link.data = Object.assign({}, link.data, { - hProperties: extend(true, {}, props), - hChildren: toChildren(content, node) - }) - - node.children[behavior === 'prepend' ? 'unshift' : 'push'](link) - } - } - - /** @type {import('unist-util-visit').Visitor} */ - function around(node, index, parent) { - const url = getUrl(node) - - if (url && typeof index === 'number' && parent) { - const link = create(url) - const grouping = group ? toGrouping(group, node) : undefined - - link.data = Object.assign({}, link.data, { - hProperties: extend(true, {}, props), - hChildren: toChildren(content, node) - }) - - /** @type {BlockContent[]} */ - // @ts-expect-error: links are not allowed, but it works fine. - let nodes = behavior === 'before' ? [link, node] : [node, link] - - if (grouping) { - grouping.children = nodes - nodes = [grouping] - } - - parent.children.splice(index, 1, ...nodes) - - return [SKIP, index + nodes.length] - } - } - - /** @type {import('unist-util-visit').Visitor} */ - function wrap(node) { - const url = getUrl(node) - - if (url) { - const link = create(url, toStaticPhrasingContent(node.children)) - link.data = {hProperties: extend(true, {}, props)} - node.children = [link] - } - } - - /** - * @param {ElementChild|ElementChild[]|Build} value - * @param {Heading} node - * @returns {ElementChild|ElementChild[]} - */ - function toNode(value, node) { - return typeof value === 'function' ? value(node) : value - } - - /** - * @param {ElementChild|ElementChild[]|Build} value - * @param {Heading} node - * @returns {ElementChild[]} - */ - function toChildren(value, node) { - const result = toNode(value, node) - const children = Array.isArray(result) ? result : [result] - return typeof value === 'function' ? children : extend(true, [], children) - } - - /** - * @param {ElementChild|ElementChild[]|Build} value - * @param {Heading} node - * @returns {Blockquote} - */ - function toGrouping(value, node) { - const grouping = toNode(value, node) - - if (Array.isArray(grouping) || grouping.type !== 'element') { - throw new Error('Expected element as grouping') - } - - const hName = grouping.tagName - const hProperties = grouping.properties - - return { - // @ts-expect-error: custom node. - type: 'heading-group', - data: { - hName, - hProperties: - typeof value === 'function' - ? extend(true, {}, hProperties) - : hProperties - }, - children: [] - } - } - - /** - * @param {string} url - * @param {StaticPhrasingContent[]} [children] - * @returns {Link} - */ - function create(url, children) { - return { - type: 'link', - url, - title: null, - children: children || [] - } - } - - /** - * @param {Heading} node - * @returns {string|undefined} - */ - function getUrl(node) { - const data = node.data || {} - const props = /** @type {Properties} */ (data.hProperties) - const id = props && props.id - return id ? '#' + id : undefined - } - - /** - * @param {Array.} [nodes] - * @returns {Array.} - */ - function toStaticPhrasingContent(nodes) { - /** @type {Array.} */ - let result = [] - let index = -1 - - if (nodes) { - while (++index < nodes.length) { - result = result.concat(toStaticPhrasingContentOne(nodes[index])) - } - } - - return result - } - - /** - * @param {PhrasingContent} node - * @returns {StaticPhrasingContent|Array.} - */ - function toStaticPhrasingContentOne(node) { - if ( - node.type === 'link' || - node.type === 'linkReference' || - node.type === 'footnote' || - node.type === 'footnoteReference' - ) { - // @ts-expect-error Looks like a parent. - return toStaticPhrasingContent(node.children) - } - - if ('children' in node) { - const {children, position, ...copy} = node - return Object.assign(extend(true, {}, copy), { - children: toStaticPhrasingContent(node.children) - }) - } - - const {position, ...copy} = node - return extend(true, {}, copy) - } -} diff --git a/license b/license deleted file mode 100644 index 51c6289..0000000 --- a/license +++ /dev/null @@ -1,24 +0,0 @@ -(The MIT License) - -Copyright (c) 2015 Ben Briggs (http://beneb.info) - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/package.json b/package.json index eed9de4..07f4d43 100644 --- a/package.json +++ b/package.json @@ -1,79 +1,6 @@ { + "bugs": "https://github.com/remarkjs/remark-autolink-headings/issues", "name": "remark-autolink-headings", - "version": "7.0.1", - "description": "Legacy remark plugin to automatically add links to headings — please use `rehype-autolink-headings` instead", - "license": "MIT", - "keywords": [], "repository": "remarkjs/remark-autolink-headings", - "bugs": "https://github.com/remarkjs/remark-autolink-headings/issues", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "author": "Ben Briggs (http://beneb.info)", - "contributors": [ - "Ben Briggs (http://beneb.info)", - "Titus Wormer (https://wooorm.com)" - ], - "sideEffects": false, - "type": "module", - "main": "index.js", - "types": "index.d.ts", - "files": [ - "index.d.ts", - "index.js" - ], - "dependencies": { - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "extend": "^3.0.0", - "unified": "^10.0.0", - "unist-util-visit": "^4.0.0" - }, - "devDependencies": { - "@types/extend": "^3.0.0", - "@types/tape": "^4.0.0", - "c8": "^7.0.0", - "hastscript": "^7.0.0", - "prettier": "^2.0.0", - "remark": "^14.0.0", - "remark-cli": "^10.0.0", - "remark-html": "^14.0.0", - "remark-preset-wooorm": "^9.0.0", - "remark-slug": "^7.0.0", - "rimraf": "^3.0.0", - "tape": "^5.0.0", - "type-coverage": "^2.0.0", - "typescript": "^4.0.0", - "xo": "^0.44.0" - }, - "scripts": { - "build": "rimraf \"test/**/*.d.ts\" \"*.d.ts\" && tsc && type-coverage", - "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", - "test-api": "node --conditions development test/index.js", - "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api", - "test": "npm run build && npm run format && npm run test-coverage" - }, - "prettier": { - "tabWidth": 2, - "useTabs": false, - "singleQuote": true, - "bracketSpacing": false, - "semi": false, - "trailingComma": "none" - }, - "xo": { - "prettier": true - }, - "remarkConfig": { - "plugins": [ - "preset-wooorm" - ] - }, - "typeCoverage": { - "atLeast": 100, - "detail": true, - "strict": true, - "ignoreCatch": true - } + "version": "8.0.0" } diff --git a/readme.md b/readme.md index 892823c..fd43d00 100644 --- a/readme.md +++ b/readme.md @@ -1,24 +1,12 @@ # remark-autolink-headings -**Stability: Legacy**. -This package is no longer recommended for use. -It’s still covered by semantic-versioning guarantees and not yet deprecated, -but use of this package should be avoided. +Deprecated: this package is no longer maintained. Please use `remark-rehype` to move from remark (markdown) to rehype (HTML) and then replace `remark-autolink-headings` with [`rehype-autolink-headings`][rehype-autolink-headings]. -Legacy [documentation for this package](https://github.com/remarkjs/remark-autolink-headings/tree/91254a60bfe03163cb49f08ec20ca5d34f677b7c) -is still available in Git. +[Git][] is still intact and previous versions can still be used without warnings. -## License - -[MIT][license] © [Ben Briggs][author] - - - -[license]: license - -[author]: http://beneb.info +[git]: https://github.com/remarkjs/remark-autolink-headings/tree/c7dfc09 [rehype-autolink-headings]: https://github.com/rehypejs/rehype-autolink-headings diff --git a/test/fixtures/input.md b/test/fixtures/input.md deleted file mode 100644 index 2a19b74..0000000 --- a/test/fixtures/input.md +++ /dev/null @@ -1 +0,0 @@ -# Hello, world! diff --git a/test/fixtures/output.after.html b/test/fixtures/output.after.html deleted file mode 100644 index cdd3c10..0000000 --- a/test/fixtures/output.after.html +++ /dev/null @@ -1,2 +0,0 @@ -

Hello, world!

- diff --git a/test/fixtures/output.append.html b/test/fixtures/output.append.html deleted file mode 100644 index 5e205ba..0000000 --- a/test/fixtures/output.append.html +++ /dev/null @@ -1 +0,0 @@ -

Hello, world!

diff --git a/test/fixtures/output.before.html b/test/fixtures/output.before.html deleted file mode 100644 index a5bed6e..0000000 --- a/test/fixtures/output.before.html +++ /dev/null @@ -1,2 +0,0 @@ - -

Hello, world!

diff --git a/test/fixtures/output.html b/test/fixtures/output.html deleted file mode 100644 index 9f735a6..0000000 --- a/test/fixtures/output.html +++ /dev/null @@ -1 +0,0 @@ -

Hello, world!

diff --git a/test/fixtures/output.prepend.html b/test/fixtures/output.prepend.html deleted file mode 100644 index f24ad27..0000000 --- a/test/fixtures/output.prepend.html +++ /dev/null @@ -1 +0,0 @@ -

Hello, world!

diff --git a/test/fixtures/output.wrap.html b/test/fixtures/output.wrap.html deleted file mode 100644 index 885ce43..0000000 --- a/test/fixtures/output.wrap.html +++ /dev/null @@ -1 +0,0 @@ -

Hello, world!

diff --git a/test/index.js b/test/index.js deleted file mode 100644 index c4549bd..0000000 --- a/test/index.js +++ /dev/null @@ -1,171 +0,0 @@ -import assert from 'node:assert' -import fs from 'node:fs' -import path from 'node:path' -import test from 'tape' -import {remark} from 'remark' -import remarkSlug from 'remark-slug' -import remarkHtml from 'remark-html' -import remarkAutolinkHeadings from '../index.js' - -/** - * @param {string} name - */ -const base = function (name) { - return fs.readFileSync(path.join('test', 'fixtures', name), 'utf-8') -} - -/** @type {['append', 'prepend', 'after', 'before', 'wrap']} */ -const behaviors = ['append', 'prepend', 'after', 'before', 'wrap'] - -test('remarkAutolinkHeadings', (t) => { - let index = -1 - while (++index < behaviors.length) { - const b = behaviors[index] - t.is( - remark() - .use(remarkSlug) - .use(remarkHtml) - .use(remarkAutolinkHeadings, {behavior: b}) - .processSync(base('input.md')) - .toString(), - base('output.' + b + '.html'), - 'should autolink headings (' + b + ')' - ) - } - - t.is( - remark() - .use(remarkSlug) - .use(remarkHtml) - .use(remarkAutolinkHeadings, {content: {type: 'text', value: '#'}}) - .processSync('# method') - .toString(), - '

method

\n', - 'should accept custom content' - ) - - t.is( - remark() - .use(remarkSlug) - .use(remarkHtml) - .use(remarkAutolinkHeadings, {content: [{type: 'text', value: '#'}]}) - .processSync('# method') - .toString(), - '

method

\n', - 'should accept custom content as an array' - ) - - t.is( - remark() - .use(remarkSlug) - .use(remarkHtml) - .use(remarkAutolinkHeadings, { - content(node) { - const head = node.children[0] - assert(head.type === 'text') - return { - type: 'text', - value: 'Read the “' + head.value + '” section' - } - }, - linkProperties: {} - }) - .processSync('# method') - .toString(), - '

Read the “method” sectionmethod

\n', - 'should accept custom content as a function' - ) - - t.is( - remark() - .use(remarkSlug) - .use(remarkHtml) - .use(remarkAutolinkHeadings, {linkProperties: {hidden: true}}) - .processSync('# method') - .toString(), - '

method

\n', - 'should accept link properties' - ) - - t.is( - remark() - .use(remarkSlug) - .use(remarkHtml) - .use(remarkAutolinkHeadings, { - group: { - type: 'element', - tagName: 'div', - properties: {className: ['heading-group']}, - children: [] - }, - behavior: 'before' - }) - .processSync('# method') - .toString(), - '

method

\n', - 'should accept a custom group' - ) - - t.is( - remark() - .use(remarkSlug) - .use(remarkHtml) - .use(remarkAutolinkHeadings, { - group(node) { - return { - type: 'element', - tagName: 'div', - properties: {className: ['heading-' + node.depth + '-group']}, - children: [] - } - }, - behavior: 'after' - }) - .processSync('# method') - .toString(), - '

method

\n', - 'should accept a custom group as a function' - ) - - t.is( - remark() - .use(remarkAutolinkHeadings) - .use(remarkHtml) - .processSync(base('input.md')) - .toString(), - base('output.html'), - 'should do nothing if slugs are not used' - ) - - t.throws( - () => { - remark() - .use(remarkSlug) - .use(remarkHtml) - // @ts-expect-error: invalid group. - .use(remarkAutolinkHeadings, { - group() { - return {type: 'text', value: 'x'} - }, - behavior: 'after' - }) - .processSync('# method') - .toString() - }, - /Expected element as grouping/, - 'should throw when `group` is not an element' - ) - - t.is( - remark() - .use(remarkSlug) - .use(remarkAutolinkHeadings, {behavior: 'wrap'}) - .use(remarkHtml) - .processSync('# [Hello](#), **world**!') - .toString(), - '

Hello, world!

\n', - 'should unravel interactive content when wrapping' - ) - - t.end() -}) diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index a93b9f9..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "include": ["test/**/*.js", "*.js"], - "compilerOptions": { - "target": "ES2020", - "lib": ["ES2020"], - "module": "ES2020", - "moduleResolution": "node", - "allowJs": true, - "checkJs": true, - "declaration": true, - "emitDeclarationOnly": true, - "allowSyntheticDefaultImports": true, - "skipLibCheck": true, - "strict": true - } -}