Skip to content

Commit

Permalink
Require Node.js 12.20 and move to ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Oct 18, 2021
1 parent e0cf2a2 commit 4b35bd5
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 104 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@ jobs:
fail-fast: false
matrix:
node-version:
- 14
- 12
- 10
- 8
- 16
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
75 changes: 36 additions & 39 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,51 @@
/// <reference lib="dom"/>
import {HTMLAttributes} from 'create-html-element';

declare namespace linkifyUrls {
interface Options {
/**
HTML attributes to add to the link.
*/
readonly attributes?: {
[attributeName: string]: string | number | boolean | readonly string[];
};
export interface Options {
/**
HTML attributes to add to the link.
*/
readonly attributes?: HTMLAttributes;

/**
Format of the generated content.
/**
The format of the generated content.
`'string'` will return it as a flat string like `'Visit <a href="https://example.com">https://example.com</a>'`.
`'string'` will return it as a flat string like `'Visit <a href="https://example.com">https://example.com</a>'`.
`'dom'` will return it as a `DocumentFragment` ready to be appended in a DOM safely, like `DocumentFragment(TextNode('Visit '), HTMLAnchorElement('https://example.com'))`. This type only works in the browser.
*/
readonly type?: 'string' | 'dom';
`'dom'` will return it as a `DocumentFragment` ready to be appended in a DOM safely, like `DocumentFragment(TextNode('Visit '), HTMLAnchorElement('https://example.com'))`. This type only works in the browser.
*/
readonly type?: 'string' | 'dom';

/**
Set a custom HTML value for the link.
/**
Set a custom HTML value for the link.
Default: The URL.
Default: The URL.
@example
```
linkifyUrls('See https://sindresorhus.com/foo', {
value: url => new URL(url).pathname
});
//=> 'See <a href="https://sindresorhus.com/foo">/foo</a>'
```
*/
readonly value?: string | ((url: string) => string);
@example
```
import linkifyUrls from 'linkify-urls';
}
linkifyUrls('See https://sindresorhus.com/foo', {
value: url => new URL(url).pathname
});
//=> 'See <a href="https://sindresorhus.com/foo">/foo</a>'
```
*/
readonly value?: string | ((url: string) => string);

interface TypeDomOptions extends Options {
readonly type: 'dom';
}
}

export interface TypeDomOptions extends Options {
readonly type: 'dom';
}

/**
Linkify URLs in a string.
@param string - String with URLs to linkify.
@param string - A string with URLs to linkify.
@example
```
import linkifyUrls = require('linkify-urls');
import linkifyUrls from 'linkify-urls';
linkifyUrls('See https://sindresorhus.com', {
attributes: {
Expand All @@ -59,7 +57,6 @@ linkifyUrls('See https://sindresorhus.com', {
});
//=> 'See <a href="https://sindresorhus.com" class="unicorn" one="1" foo multiple="a b">https://sindresorhus.com</a>'
// In the browser
const fragment = linkifyUrls('See https://sindresorhus.com', {
type: 'dom',
Expand All @@ -70,13 +67,13 @@ const fragment = linkifyUrls('See https://sindresorhus.com', {
document.body.appendChild(fragment);
```
*/
declare function linkifyUrls(
export default function linkifyUrls(
string: string,
options: linkifyUrls.TypeDomOptions
options: TypeDomOptions
): DocumentFragment;
declare function linkifyUrls(
export default function linkifyUrls(
string: string,
options?: linkifyUrls.Options
options?: Options
): string;

export = linkifyUrls;
export {HTMLAttributes} from 'create-html-element';
23 changes: 10 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
'use strict';
const createHtmlElement = require('create-html-element');
import createHtmlElement from 'create-html-element';

// Capture the whole URL in group 1 to keep `String#split()` support
const urlRegex = () => (/((?<!\+)(?:https?(?::\/\/))(?:www\.)?(?:[a-zA-Z\d-_.]+(?:(?:\.|@)[a-zA-Z\d]{2,})|localhost)(?:(?:[-a-zA-Z\d:%_+.~#*$!?&//=@]*)(?:[,](?![\s]))*)*)/g);
const urlRegex = () => (/((?<!\+)https?:\/\/(?:www\.)?(?:[-\w.]+?[.@][a-zA-Z\d]{2,}|localhost)(?:[-\w.:%+~#*$!?&/=@]*?(?:,(?!\s))*?)*)/g);

// Get `<a>` element as string
const linkify = (href, options) => createHtmlElement({
name: 'a',
attributes: {
href: '',
...options.attributes,
href // eslint-disable-line no-dupe-keys
href, // eslint-disable-line no-dupe-keys
},
text: typeof options.value === 'undefined' ? href : undefined,
html: typeof options.value === 'undefined' ? undefined :
(typeof options.value === 'function' ? options.value(href) : options.value)
html: typeof options.value === 'undefined' ? undefined
: (typeof options.value === 'function' ? options.value(href) : options.value),
});

// Get DOM node from HTML
const domify = html => document.createRange().createContextualFragment(html);

const getAsString = (string, options) => {
return string.replace(urlRegex(), match => linkify(match, options));
};
const getAsString = (string, options) => string.replace(urlRegex(), match => linkify(match, options));

const getAsDocumentFragment = (string, options) => {
const fragment = document.createDocumentFragment();
Expand All @@ -37,11 +34,11 @@ const getAsDocumentFragment = (string, options) => {
return fragment;
};

module.exports = (string, options) => {
export default function linkifyUrls(string, options) {
options = {
attributes: {},
type: 'string',
...options
...options,
};

if (options.type === 'string') {
Expand All @@ -52,5 +49,5 @@ module.exports = (string, options) => {
return getAsDocumentFragment(string, options);
}

throw new Error('The type option must be either `dom` or `string`');
};
throw new TypeError('The type option must be either `dom` or `string`');
}
26 changes: 13 additions & 13 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import {expectType} from 'tsd';
import linkifyUrls = require('.');
import linkifyUrls from './index.js';

expectType<string>(
linkifyUrls('See https://sindresorhus.com', {
attributes: {
class: 'unicorn',
one: 1,
foo: true,
multiple: ['a', 'b']
}
})
multiple: ['a', 'b'],
},
}),
);
expectType<string>(
linkifyUrls('See https://sindresorhus.com', {
value: 'foo'
})
value: 'foo',
}),
);
expectType<string>(
linkifyUrls('See https://sindresorhus.com/foo', {
value: url => {
expectType<string>(url);
return url;
}
})
},
}),
);
expectType<string>(
linkifyUrls('See https://sindresorhus.com/foo', {
type: 'string'
})
type: 'string',
}),
);

const fragment = linkifyUrls('See https://sindresorhus.com', {
type: 'dom',
attributes: {
class: 'unicorn'
}
class: 'unicorn',
},
});

expectType<DocumentFragment>(fragment);

document.body.appendChild(fragment);
document.body.append(fragment);
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=8"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"scripts": {
"test": "xo && ava && tsd"
Expand All @@ -34,13 +36,13 @@
"dom"
],
"dependencies": {
"create-html-element": "^2.1.0"
"create-html-element": "^4.0.1"
},
"devDependencies": {
"ava": "^1.4.1",
"jsdom": "^14.0.0",
"tsd": "^0.7.2",
"xo": "^0.24.0"
"ava": "^3.15.0",
"jsdom": "^18.0.0",
"tsd": "^0.18.0",
"xo": "^0.45.0"
},
"xo": {
"envs": [
Expand Down
15 changes: 9 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@
## Install

```
$ npm install linkify-urls
```sh
npm install linkify-urls
```

## Usage

```js
const linkifyUrls = require('linkify-urls');
import linkifyUrls from 'linkify-urls';

linkifyUrls('See https://sindresorhus.com', {
attributes: {
class: 'unicorn',
one: 1,
foo: true,
multiple: ['a', 'b']
multiple: [
'a',
'b'
]
}
});
//=> 'See <a href="https://sindresorhus.com" class="unicorn" one="1" foo multiple="a b">https://sindresorhus.com</a>'
Expand All @@ -42,7 +45,7 @@ document.body.appendChild(fragment);

Type: `string`

String with URLs to linkify.
A string with URLs to linkify.

#### options

Expand All @@ -60,7 +63,7 @@ Type: `string`\
Values: `'string' | 'dom'`\
Default: `'string'`

Format of the generated content.
The format of the generated content.

`'string'` will return it as a flat string like `'Visit <a href="https://example.com">https://example.com</a>'`.

Expand Down
Loading

0 comments on commit 4b35bd5

Please sign in to comment.