Socket
Socket
Sign inDemoInstall

mdast-util-gfm-autolink-literal

Package Overview
Dependencies
10
Maintainers
2
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.2 to 1.0.3

lib/index.d.ts

20

index.d.ts

@@ -1,16 +0,4 @@

/** @type {FromMarkdownExtension} */
export const gfmAutolinkLiteralFromMarkdown: FromMarkdownExtension
/** @type {ToMarkdownExtension} */
export const gfmAutolinkLiteralToMarkdown: ToMarkdownExtension
export type Link = import('mdast').Link
export type FromMarkdownExtension = import('mdast-util-from-markdown').Extension
export type FromMarkdownTransform = import('mdast-util-from-markdown').Transform
export type FromMarkdownHandle = import('mdast-util-from-markdown').Handle
export type ToMarkdownExtension =
import('mdast-util-to-markdown/lib/types.js').Options
export type ReplaceFunction =
import('mdast-util-find-and-replace').ReplaceFunction
export type RegExpMatchObject =
import('mdast-util-find-and-replace').RegExpMatchObject
export type PhrasingContent =
import('mdast-util-find-and-replace').PhrasingContent
export {
gfmAutolinkLiteralFromMarkdown,
gfmAutolinkLiteralToMarkdown
} from './lib/index.js'

246

index.js

@@ -1,242 +0,4 @@

/**
* @typedef {import('mdast').Link} Link
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
* @typedef {import('mdast-util-from-markdown').Transform} FromMarkdownTransform
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
* @typedef {import('mdast-util-to-markdown/lib/types.js').Options} ToMarkdownExtension
* @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction
* @typedef {import('mdast-util-find-and-replace').RegExpMatchObject} RegExpMatchObject
* @typedef {import('mdast-util-find-and-replace').PhrasingContent} PhrasingContent
*/
import {ccount} from 'ccount'
import {findAndReplace} from 'mdast-util-find-and-replace'
import {unicodePunctuation, unicodeWhitespace} from 'micromark-util-character'
const inConstruct = 'phrasing'
const notInConstruct = ['autolink', 'link', 'image', 'label']
/** @type {FromMarkdownExtension} */
export const gfmAutolinkLiteralFromMarkdown = {
transforms: [transformGfmAutolinkLiterals],
enter: {
literalAutolink: enterLiteralAutolink,
literalAutolinkEmail: enterLiteralAutolinkValue,
literalAutolinkHttp: enterLiteralAutolinkValue,
literalAutolinkWww: enterLiteralAutolinkValue
},
exit: {
literalAutolink: exitLiteralAutolink,
literalAutolinkEmail: exitLiteralAutolinkEmail,
literalAutolinkHttp: exitLiteralAutolinkHttp,
literalAutolinkWww: exitLiteralAutolinkWww
}
}
/** @type {ToMarkdownExtension} */
export const gfmAutolinkLiteralToMarkdown = {
unsafe: [
{
character: '@',
before: '[+\\-.\\w]',
after: '[\\-.\\w]',
inConstruct,
notInConstruct
},
{
character: '.',
before: '[Ww]',
after: '[\\-.\\w]',
inConstruct,
notInConstruct
},
{character: ':', before: '[ps]', after: '\\/', inConstruct, notInConstruct}
]
}
/** @type {FromMarkdownHandle} */
function enterLiteralAutolink(token) {
this.enter({type: 'link', title: null, url: '', children: []}, token)
}
/** @type {FromMarkdownHandle} */
function enterLiteralAutolinkValue(token) {
this.config.enter.autolinkProtocol.call(this, token)
}
/** @type {FromMarkdownHandle} */
function exitLiteralAutolinkHttp(token) {
this.config.exit.autolinkProtocol.call(this, token)
}
/** @type {FromMarkdownHandle} */
function exitLiteralAutolinkWww(token) {
this.config.exit.data.call(this, token)
const node = /** @type {Link} */ (this.stack[this.stack.length - 1])
node.url = 'http://' + this.sliceSerialize(token)
}
/** @type {FromMarkdownHandle} */
function exitLiteralAutolinkEmail(token) {
this.config.exit.autolinkEmail.call(this, token)
}
/** @type {FromMarkdownHandle} */
function exitLiteralAutolink(token) {
this.exit(token)
}
/** @type {FromMarkdownTransform} */
function transformGfmAutolinkLiterals(tree) {
findAndReplace(
tree,
[
[/(https?:\/\/|www(?=\.))([-.\w]+)([^ \t\r\n]*)/gi, findUrl],
[/([-.\w+]+)@([-\w]+(?:\.[-\w]+)+)/g, findEmail]
],
{ignore: ['link', 'linkReference']}
)
}
/**
* @type {ReplaceFunction}
* @param {string} _
* @param {string} protocol
* @param {string} domain
* @param {string} path
* @param {RegExpMatchObject} match
*/
// eslint-disable-next-line max-params
function findUrl(_, protocol, domain, path, match) {
let prefix = ''
// Not an expected previous character.
if (!previous(match)) {
return false
}
// Treat `www` as part of the domain.
if (/^w/i.test(protocol)) {
domain = protocol + domain
protocol = ''
prefix = 'http://'
}
if (!isCorrectDomain(domain)) {
return false
}
const parts = splitUrl(domain + path)
if (!parts[0]) return false
/** @type {PhrasingContent} */
const result = {
type: 'link',
title: null,
url: prefix + protocol + parts[0],
children: [{type: 'text', value: protocol + parts[0]}]
}
if (parts[1]) {
return [result, {type: 'text', value: parts[1]}]
}
return result
}
/**
* @type {ReplaceFunction}
* @param {string} _
* @param {string} atext
* @param {string} label
* @param {RegExpMatchObject} match
*/
function findEmail(_, atext, label, match) {
if (
// Not an expected previous character.
!previous(match, true) ||
// Label ends in not allowed character.
/[_-\d]$/.test(label)
) {
return false
}
return {
type: 'link',
title: null,
url: 'mailto:' + atext + '@' + label,
children: [{type: 'text', value: atext + '@' + label}]
}
}
/**
* @param {string} domain
* @returns {boolean}
*/
function isCorrectDomain(domain) {
const parts = domain.split('.')
if (
parts.length < 2 ||
(parts[parts.length - 1] &&
(/_/.test(parts[parts.length - 1]) ||
!/[a-zA-Z\d]/.test(parts[parts.length - 1]))) ||
(parts[parts.length - 2] &&
(/_/.test(parts[parts.length - 2]) ||
!/[a-zA-Z\d]/.test(parts[parts.length - 2])))
) {
return false
}
return true
}
/**
* @param {string} url
* @returns {[string, string|undefined]}
*/
function splitUrl(url) {
const trailExec = /[!"&'),.:;<>?\]}]+$/.exec(url)
/** @type {number} */
let closingParenIndex
/** @type {number} */
let openingParens
/** @type {number} */
let closingParens
/** @type {string|undefined} */
let trail
if (trailExec) {
url = url.slice(0, trailExec.index)
trail = trailExec[0]
closingParenIndex = trail.indexOf(')')
openingParens = ccount(url, '(')
closingParens = ccount(url, ')')
while (closingParenIndex !== -1 && openingParens > closingParens) {
url += trail.slice(0, closingParenIndex + 1)
trail = trail.slice(closingParenIndex + 1)
closingParenIndex = trail.indexOf(')')
closingParens++
}
}
return [url, trail]
}
/**
* @param {RegExpMatchObject} match
* @param {boolean} [email=false]
* @returns {boolean}
*/
function previous(match, email) {
const code = match.input.charCodeAt(match.index - 1)
return (
(match.index === 0 ||
unicodeWhitespace(code) ||
unicodePunctuation(code)) &&
(!email || code !== 47)
)
}
export {
gfmAutolinkLiteralFromMarkdown,
gfmAutolinkLiteralToMarkdown
} from './lib/index.js'
{
"name": "mdast-util-gfm-autolink-literal",
"version": "1.0.2",
"version": "1.0.3",
"description": "mdast extension to parse and serialize GFM autolink literals",

@@ -37,2 +37,3 @@ "license": "MIT",

"files": [
"lib/",
"index.d.ts",

@@ -48,23 +49,22 @@ "index.js"

"devDependencies": {
"@types/tape": "^4.0.0",
"@types/node": "^18.0.0",
"c8": "^7.0.0",
"hast-util-to-html": "^8.0.0",
"mdast-util-from-markdown": "^1.0.0",
"mdast-util-to-hast": "^11.0.0",
"mdast-util-to-hast": "^12.0.0",
"mdast-util-to-markdown": "^1.0.0",
"micromark-extension-gfm-autolink-literal": "^1.0.0",
"prettier": "^2.0.0",
"remark-cli": "^10.0.0",
"remark-cli": "^11.0.0",
"remark-preset-wooorm": "^9.0.0",
"rimraf": "^3.0.0",
"tape": "^5.0.0",
"type-coverage": "^2.0.0",
"typescript": "^4.0.0",
"xo": "^0.44.0"
"xo": "^0.53.0"
},
"scripts": {
"build": "rimraf \"*.d.ts\" && tsc && type-coverage",
"prepack": "npm run build && npm run format",
"build": "tsc --build --clean && tsc --build && 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 node --conditions development test/index.js",
"test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"

@@ -81,7 +81,18 @@ },

"xo": {
"prettier": true
"prettier": true,
"rules": {
"unicorn/prefer-code-point": "off"
},
"overrides": [
{
"files": "test/**/*.js",
"rules": {
"no-await-in-loop": "off"
}
}
]
},
"remarkConfig": {
"plugins": [
"preset-wooorm"
"remark-preset-wooorm"
]

@@ -88,0 +99,0 @@ },

@@ -11,20 +11,72 @@ # mdast-util-gfm-autolink-literal

Extension for [`mdast-util-from-markdown`][from-markdown] and/or
[`mdast-util-to-markdown`][to-markdown] to support GitHub flavored markdown
autolink literals in **[mdast][]**.
When parsing (`from-markdown`), must be combined with
[`micromark-extension-gfm-autolink-literal`][extension].
[mdast][] extensions to parse and serialize [GFM][] autolink literals.
## Contents
* [What is this?](#what-is-this)
* [When to use this](#when-to-use-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [`gfmAutolinkLiteralFromMarkdown`](#gfmautolinkliteralfrommarkdown)
* [`gfmAutolinkLiteralToMarkdown`](#gfmautolinkliteraltomarkdown)
* [HTML](#html)
* [Syntax](#syntax)
* [Syntax tree](#syntax-tree)
* [Types](#types)
* [Compatibility](#compatibility)
* [Related](#related)
* [Contribute](#contribute)
* [License](#license)
## What is this?
This package contains two extensions that add support for GFM autolink literals
syntax in markdown to [mdast][].
These extensions plug into
[`mdast-util-from-markdown`][mdast-util-from-markdown] (to support parsing
GFM autolinks in markdown into a syntax tree) and
[`mdast-util-to-markdown`][mdast-util-to-markdown] (to support serializing
GFM autolinks in syntax trees to markdown).
GitHub employs different algorithms to autolink: one at parse time and one at
transform time (similar to how `@mentions` are done at transform time).
This difference can be observed because character references and escapes are
handled differently.
But also because issues/PRs/comments omit (perhaps by accident?) the second
algorithm for `www.`, `http://`, and `https://` links (but not for email links).
As the corresponding micromark extension
[`micromark-extension-gfm-autolink-literal`][extension] is a syntax extension,
it can only perform the first algorithm.
The tree extension `gfmAutolinkLiteralFromMarkdown` from this package can
perform the second algorithm, and as they are combined, both are done.
## When to use this
Use [`mdast-util-gfm`][mdast-util-gfm] if you want all of GFM.
Use this otherwise.
You can use these extensions when you are working with
`mdast-util-from-markdown` and `mdast-util-to-markdown` already.
When working with `mdast-util-from-markdown`, you must combine this package
with
[`micromark-extension-gfm-autolink-literal`][extension].
When you don’t need a syntax tree, you can use [`micromark`][micromark]
directly with `micromark-extension-gfm-autolink-literal`.
When you are working with syntax trees and want all of GFM, use
[`mdast-util-gfm`][mdast-util-gfm] instead.
All these packages are used [`remark-gfm`][remark-gfm], which
focusses on making it easier to transform content by abstracting these
internals away.
This utility does not handle how markdown is turned to HTML.
That’s done by [`mdast-util-to-hast`][mdast-util-to-hast].
## Install
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

@@ -34,7 +86,28 @@ npm install mdast-util-gfm-autolink-literal

In Deno with [`esm.sh`][esmsh]:
```js
import {gfmAutolinkLiteralFromMarkdown, gfmAutolinkLiteralToMarkdown} from 'https://esm.sh/mdast-util-gfm-autolink-literal@1'
```
In browsers with [`esm.sh`][esmsh]:
```html
<script type="module">
import {gfmAutolinkLiteralFromMarkdown, gfmAutolinkLiteralToMarkdown} from 'https://esm.sh/mdast-util-gfm-autolink-literal@1?bundle'
</script>
```
## Use
Say our module, `example.js`, looks as follows:
Say our document `example.md` contains:
```markdown
www.example.com, https://example.com, and contact@example.com.
```
…and our module `example.js` looks as follows:
```js
import fs from 'node:fs/promises'
import {fromMarkdown} from 'mdast-util-from-markdown'

@@ -45,3 +118,3 @@ import {toMarkdown} from 'mdast-util-to-markdown'

const doc = 'www.example.com, https://example.com, and contact@example.com.'
const doc = await fs.readFile('example.md')

@@ -60,3 +133,3 @@ const tree = fromMarkdown(doc, {

Now, running `node example` yields:
…now running `node example.js` yields (positional info removed for brevity):

@@ -103,30 +176,62 @@ ```js

This package exports the identifiers
[`gfmAutolinkLiteralFromMarkdown`][api-gfmautolinkliteralfrommarkdown] and
[`gfmAutolinkLiteralToMarkdown`][api-gfmautolinkliteraltomarkdown].
There is no default export.
### `gfmAutolinkLiteralFromMarkdown`
Extension for [`mdast-util-from-markdown`][mdast-util-from-markdown] to enable
GFM autolink literals ([`FromMarkdownExtension`][frommarkdownextension]).
### `gfmAutolinkLiteralToMarkdown`
Support literal autolinks.
The exports are extensions, respectively
for [`mdast-util-from-markdown`][from-markdown] and
[`mdast-util-to-markdown`][to-markdown].
Extension for [`mdast-util-to-markdown`][mdast-util-to-markdown] to enable
GFM autolink literals ([`ToMarkdownExtension`][tomarkdownextension]).
## HTML
This utility does not handle how markdown is turned to HTML.
That’s done by [`mdast-util-to-hast`][mdast-util-to-hast].
## Syntax
See [Syntax in `micromark-extension-gfm-autolink-literal`][syntax].
## Syntax tree
There are no interfaces added to **[mdast][]** by this utility, as it reuses
the existing **[Link][dfn-link]** interface.
## Types
This package is fully typed with [TypeScript][].
It does not export additional types.
The `Link` type of the mdast nodes is exposed from `@types/mdast`.
## 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.
This plugin works with `mdast-util-from-markdown` version 1+ and
`mdast-util-to-markdown` version 1+.
## Related
* [`remarkjs/remark`][remark]
— markdown processor powered by plugins
* [`remarkjs/remark-gfm`][remark-gfm]
— remark plugin to support GFM
* [`micromark/micromark`][micromark]
— the smallest commonmark-compliant markdown parser that exists
* [`syntax-tree/mdast-util-gfm`][mdast-util-gfm]
— same but all of GFM (autolink literals, footnotes, strikethrough, tables,
tasklists)
* [`micromark/micromark-extension-gfm-autolink-literal`][extension]
— micromark extension to parse GFM autolink literals
* [`syntax-tree/mdast-util-from-markdown`][from-markdown]
— mdast parser using `micromark` to create mdast from markdown
* [`syntax-tree/mdast-util-to-markdown`][to-markdown]
— mdast serializer to create markdown from mdast
## 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.

@@ -172,2 +277,8 @@

[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[esmsh]: https://esm.sh
[typescript]: https://www.typescriptlang.org
[license]: license

@@ -177,2 +288,4 @@

[health]: https://github.com/syntax-tree/.github
[contributing]: https://github.com/syntax-tree/.github/blob/HEAD/contributing.md

@@ -188,9 +301,9 @@

[remark]: https://github.com/remarkjs/remark
[mdast-util-from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown
[remark-gfm]: https://github.com/remarkjs/remark-gfm
[mdast-util-to-markdown]: https://github.com/syntax-tree/mdast-util-to-markdown
[from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown
[mdast-util-to-hast]: https://github.com/syntax-tree/mdast-util-to-hast
[to-markdown]: https://github.com/syntax-tree/mdast-util-to-markdown
[remark-gfm]: https://github.com/remarkjs/remark-gfm

@@ -200,1 +313,15 @@ [micromark]: https://github.com/micromark/micromark

[extension]: https://github.com/micromark/micromark-extension-gfm-autolink-literal
[syntax]: https://github.com/micromark/micromark-extension-gfm-autolink-literal#syntax
[gfm]: https://github.github.com/gfm/
[dfn-link]: https://github.com/syntax-tree/mdast#link
[frommarkdownextension]: https://github.com/syntax-tree/mdast-util-from-markdown#extension
[tomarkdownextension]: https://github.com/syntax-tree/mdast-util-to-markdown#options
[api-gfmautolinkliteralfrommarkdown]: #gfmautolinkliteralfrommarkdown
[api-gfmautolinkliteraltomarkdown]: #gfmautolinkliteraltomarkdown
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc