Skip to content

Commit

Permalink
prefer rehype-sanitize to hast-util-sanitize
Browse files Browse the repository at this point in the history
  • Loading branch information
rhysd committed May 19, 2024
1 parent 83a00f9 commit c2ba53e
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 45 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,18 @@ Note:

Setting to `true` makes the converted emoji text accessible with `role` and `aria-label` attributes. Each emoji
text is wrapped with `<span>` element. The `role` and `aria-label` attribute are not allowed by default. Please
add them to the sanitization schema used by remark's HTML transformer. The default sanitization schema is defined
in [hast-util-sanitize](https://www.npmjs.com/package/hast-util-sanitize) package.
add them to the sanitization schema used by remark's HTML transformer. The default sanitization schema is exported
from [rehype-sanitize](https://www.npmjs.com/package/rehype-sanitize) package.

For example,

```javascript
import remarkParse from 'remark-parse';
import toHtml from 'remark-html';
import { defaultSchema } from 'hast-util-sanitize'
import toRehype from 'remark-rehype';
import sanitize, { defaultSchema } from 'rehype-sanitize';
import stringify from 'rehype-stringify';
import emoji from 'remark-emoji';
import { unified } from 'unified'
import { unified } from 'unified';

// Allow using `role` and `aria-label` attributes in transformed HTML document
const schema = structuredClone(defaultSchema);
Expand All @@ -60,10 +61,14 @@ if ('span' in schema.attributes) {
schema.attributes.span = ['role', 'ariaLabel'];
}

// Markdown text processor pipeline
const processor = unified()
.use(remarkParse)
.use(emoji, { accessible: true })
.use(toHtml, { sanitize: schema });
.use(toRehype)
.use(sanitize, schema)
.use(stringify);

const file = await processor.process('Hello :dog:!');
console.log(String(file));
```
Expand Down
35 changes: 16 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@
"url": "https://github.com/rhysd/remark-emoji/issues"
},
"homepage": "https://github.com/rhysd/remark-emoji#readme",
"dependencies": {
"@types/mdast": "^4.0.4",
"emoticon": "^4.0.1",
"mdast-util-find-and-replace": "^3.0.1",
"node-emoji": "^2.1.3",
"unified": "^11.0.4"
},
"devDependencies": {
"@eslint/js": "^9.2.0",
"@types/eslint__js": "^8.42.3",
Expand All @@ -62,25 +69,18 @@
"eslint-plugin-mocha": "^10.4.3",
"eslint-plugin-n": "^17.7.0",
"eslint-plugin-security": "^3.0.0",
"hast-util-sanitize": "^5.0.1",
"mocha": "^10.4.0",
"prettier": "^3.2.5",
"rehype-autolink-headings": "^7.1.0",
"rehype-sanitize": "^6.0.0",
"rehype-slug": "^6.0.0",
"rehype-stringify": "^10.0.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.0",
"remark-github": "^12.0.0",
"remark-html": "^16.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.0",
"typescript": "^5.4.5",
"typescript-eslint": "^7.9.0"
},
"dependencies": {
"@types/mdast": "^4.0.4",
"emoticon": "^4.0.1",
"mdast-util-find-and-replace": "^3.0.1",
"node-emoji": "^2.1.3",
"unified": "^11.0.4"
}
}
28 changes: 17 additions & 11 deletions test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import assert from 'assert';
import { remark } from 'remark';
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import gfm from 'remark-gfm';
import github from 'remark-github';
import rehype from 'remark-rehype';
import remarkRehype from 'remark-rehype';
import headings from 'rehype-autolink-headings';
import slug from 'rehype-slug';
import remarkHtml from 'remark-html';
import emoji from './index.js';
import rehypeStringify from 'rehype-stringify';
import { defaultSchema } from 'hast-util-sanitize';
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';

const schema = structuredClone(defaultSchema);
assert.ok(schema.attributes);
Expand All @@ -22,9 +23,14 @@ const compiler = remark().use(emoji);
const padded = remark().use(emoji, { padSpaceAfter: true });
const emoticon = remark().use(emoji, { emoticon: true });
const padAndEmoticon = remark().use(emoji, { padSpaceAfter: true, emoticon: true });
const ariaHtml = remark().use(emoji, { emoticon: true, accessible: true }).use(remarkHtml, { sanitize: schema });
const ariaHtml = unified()
.use(remarkParse)
.use(emoji, { emoticon: true, accessible: true })
.use(remarkRehype)
.use(rehypeSanitize, schema)
.use(rehypeStringify);
const githubFlavor = remark().use(gfm).use(github).use(emoji);
const toRehype = remark().use(emoji).use(rehype).use(slug).use(headings).use(rehypeStringify);
const toRehype = unified().use(remarkParse).use(emoji).use(remarkRehype).use(slug).use(headings).use(rehypeStringify);

describe('remark-emoji', function () {
describe('minimal compiler', function () {
Expand Down Expand Up @@ -219,14 +225,14 @@ describe('remark-emoji', function () {
describe('accessibility support', function () {
it('wraps emoji with span', async function () {
const tests: Record<string, string> = {
':dog:': '<p><span role="img" aria-label="dog emoji">🐶</span></p>\n',
':dog:': '<p><span role="img" aria-label="dog emoji">🐶</span></p>',
':dog: :cat:':
'<p><span role="img" aria-label="dog emoji">🐶</span> <span role="img" aria-label="cat emoji">🐱</span></p>\n',
':-)': '<p><span role="img" aria-label="smiley emoticon">😃</span></p>\n',
':+1:': '<p><span role="img" aria-label="+1 emoji">👍</span></p>\n',
':-1:': '<p><span role="img" aria-label="-1 emoji">👎</span></p>\n',
'<p><span role="img" aria-label="dog emoji">🐶</span> <span role="img" aria-label="cat emoji">🐱</span></p>',
':-)': '<p><span role="img" aria-label="smiley emoticon">😃</span></p>',
':+1:': '<p><span role="img" aria-label="+1 emoji">👍</span></p>',
':-1:': '<p><span role="img" aria-label="-1 emoji">👎</span></p>',
':stuck_out_tongue_winking_eye:':
'<p><span role="img" aria-label="stuck out tongue winking eye emoji">😜</span></p>\n',
'<p><span role="img" aria-label="stuck out tongue winking eye emoji">😜</span></p>',
};

for (const [input, expected] of Object.entries(tests)) {
Expand Down

0 comments on commit c2ba53e

Please sign in to comment.