@sanity/block-content-to-html
Advanced tools
Comparing version 0.4.0 to 1.3.0
{ | ||
"name": "@sanity/block-content-to-html", | ||
"description": "Customizable HTML parser for block editor output", | ||
"version": "0.4.0", | ||
"main": "lib/index.js", | ||
"umd": "umd/index.min.js", | ||
"description": "Function for transforming Sanity block content to HTML", | ||
"version": "1.3.0", | ||
"main": "lib/blocksToHtml.js", | ||
"umd": "umd/blocksToHtml.min.js", | ||
"scripts": { | ||
"browserify": "NODE_ENV=production BROWSERIFY_ENV=build DEBUG='' browserify -t envify -g uglifyify lib/index.js -o umd/index.js --standalone=BlockContentAdapter", | ||
"build": "npm run clean && npm run compile && npm run browserify && npm run minify && npm run size", | ||
"size": "node -r babel-register src/scripts/print-bundle-size", | ||
"browserify": "NODE_ENV=production BROWSERIFY_ENV=build DEBUG='' browserify -t envify -g uglifyify lib/blocksToHtml.js -o umd/blocksToHtml.js --standalone=blocksToHtml", | ||
"build": "npm run clean && npm run compile && npm run browserify && npm run minify", | ||
"watch": "npm run compile -- --watch", | ||
"clean": "rimraf lib coverage .nyc_output umd/*.js", | ||
"compile": "babel --source-maps --copy-files -d lib/ src/", | ||
"coverage": "DEBUG=sanity NODE_ENV=test nyc --reporter=html --reporter=lcov --reporter=text npm test", | ||
"minify": "uglifyjs -c -m -- umd/index.js > umd/index.min.js", | ||
"coverage": "npm test -- --coverage", | ||
"minify": "uglifyjs -c -m -- umd/blocksToHtml.js > umd/blocksToHtml.min.js", | ||
"postpublish": "npm run clean", | ||
"posttest": "eslint .", | ||
"prepublish": "in-publish && npm run build || not-in-publish", | ||
"test": "tap --node-arg=--require --node-arg=babel-register test/*.test.js" | ||
"prepublishOnly": "npm run build", | ||
"test": "jest" | ||
}, | ||
@@ -25,24 +24,18 @@ "keywords": [], | ||
"dependencies": { | ||
"@sanity/block-content-to-tree": "^0.3.0", | ||
"in-publish": "^2.0.0" | ||
"@sanity/block-content-to-hyperscript": "^1.2.0" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.22.2", | ||
"@sanity/block-content-tests": "^0.0.3", | ||
"babel-cli": "^6.26.0", | ||
"babel-eslint": "^7.1.1", | ||
"babel-plugin-syntax-object-rest-spread": "^6.13.0", | ||
"babel-plugin-transform-object-rest-spread": "^6.23.0", | ||
"babel-preset-es2015": "^6.22.0", | ||
"babel-register": "^6.22.0", | ||
"boxen": "^1.2.1", | ||
"babel-preset-env": "^1.6.0", | ||
"browserify": "^14.4.0", | ||
"chalk": "^2.1.0", | ||
"envify": "^4.0.0", | ||
"envify": "^4.1.0", | ||
"eslint": "^4.6.1", | ||
"eslint-config-prettier": "^2.4.0", | ||
"eslint-config-sanity": "^3.0.1", | ||
"eslint-plugin-import": "^2.2.0", | ||
"gzip-size": "^4.0.0", | ||
"nyc": "^11.2.1", | ||
"pretty-bytes": "^4.0.2", | ||
"rimraf": "^2.5.4", | ||
"tap": "^10.7.2", | ||
"eslint-plugin-import": "^2.7.0", | ||
"jest": "^21.0.2", | ||
"prettier": "^1.7.0", | ||
"rimraf": "^2.6.2", | ||
"uglify-js": "^3.1.0", | ||
@@ -53,8 +46,13 @@ "uglifyify": "^4.0.3" | ||
"type": "git", | ||
"url": "git+https://github.com/sanity-io/block-content-to-html-js.git" | ||
"url": "git+https://github.com/sanity-io/block-content-to-html.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/sanity-io/block-content-to-html-js/issues" | ||
"url": "https://github.com/sanity-io/block-content-to-html/issues" | ||
}, | ||
"homepage": "https://github.com/sanity-io/block-content-to-html-js#readme" | ||
"homepage": "https://github.com/sanity-io/block-content-to-html#readme", | ||
"jest": { | ||
"collectCoverageFrom": [ | ||
"src/**/*.js" | ||
] | ||
} | ||
} |
307
README.md
@@ -1,259 +0,126 @@ | ||
# block-content-to-html-js | ||
# block-content-to-html | ||
Converts the flat Sanity block content structure into HTML. | ||
Render an array of [block text](https://sanity.io/docs/schema-types/block-text-type) from Sanity to HTML. | ||
## Installation | ||
## Installing | ||
``npm install --save @sanity/block-content-to-html`` | ||
``` | ||
npm install --save @sanity/block-content-to-html | ||
``` | ||
## Quick example | ||
## Usage | ||
```js | ||
const blocksToHtml = require('@sanity/block-content-to-html') | ||
const client = require('@sanity/client')({ | ||
projectId: '<your project id>', | ||
dataset: '<some dataset>', | ||
useCdn: true | ||
}) | ||
// The flat block content structure | ||
const data = { | ||
"_type": "block", | ||
"style": "normal", | ||
"spans": [ | ||
{ | ||
"_type": "span", | ||
"text": "String with an ", | ||
"marks": [] | ||
}, | ||
{ | ||
"_type": "span", | ||
"text": "italicized", | ||
"marks": [ | ||
"em" | ||
] | ||
}, | ||
{ | ||
"_type": "span", | ||
"text": " word.", | ||
"marks": [] | ||
} | ||
] | ||
// `h` is a way to build HTML known as hyperscript | ||
// See https://github.com/hyperhype/hyperscript for more info | ||
const h = blocksToHtml.h | ||
const serializers = { | ||
types: { | ||
code: props => ( | ||
h('pre', {className: props.node.language}, | ||
h('code', props.node.code) | ||
) | ||
) | ||
} | ||
} | ||
client.fetch('*[_type == "article"][0]').then(article => { | ||
const el = blocksToHtml({ | ||
blocks: article.body, | ||
serializers: serializers | ||
}) | ||
// Now convert it with block-content-to-html | ||
const BlockContentToHtml = require('@sanity/block-content-to-html') | ||
const toHtml = new BlockContentToHtml() | ||
const html = toHtml.convert(data) | ||
document.getElementById('root').appendChild(el) | ||
}) | ||
``` | ||
This will result in ``html`` being: | ||
## Options | ||
```html | ||
<p>String with an <em>italicized</em> word.</p> | ||
``` | ||
- `className` - When more than one block is given, a container node has to be created. Passing a `className` will pass it on to the container. Note that if only a single block is given as input, the container node will be skipped. | ||
- `serializers` - Specifies the functions to use for rendering content. Merged with default serializers. | ||
- `serializers.types` - Serializers for block types, see example above | ||
- `serializers.marks` - Serializers for marks - data that annotates a text child of a block. See example usage below. | ||
- `serializers.list` - Function to use when rendering a list node | ||
- `serializers.listItem` - Function to use when rendering a list item node | ||
- `serializers.hardBreak` - Function to use when transforming newline characters to a hard break (`<br/>` by default, pass `false` to render newline character) | ||
- `imageOptions` - When encountering image blocks, this defines which query parameters to apply in order to control size/crop mode etc. | ||
In addition, in order to render images without materializing the asset documents, you should also specify: | ||
## Interface | ||
- `projectId` - The ID of your Sanity project. | ||
- `dataset` - Name of the Sanity dataset containing the document that is being rendered. | ||
The constructor will take an object for options: | ||
## Examples | ||
```js | ||
const toHtml = new BlockContentToHtml(options: Object) | ||
``` | ||
### Rendering custom marks | ||
Converting the block content is done by calling ``.convert``: | ||
```js | ||
toHtml.convert(data: Array|Object) | ||
``` | ||
const input = [{ | ||
_type: 'block', | ||
children: [{ | ||
_key: 'a1ph4', | ||
_type: 'span', | ||
marks: ['s0m3k3y'], | ||
text: 'Sanity' | ||
}], | ||
markDefs: [{ | ||
_key: 's0m3k3y', | ||
_type: 'highlight', | ||
color: '#E4FC5B' | ||
}] | ||
}] | ||
### Constructor options | ||
const highlight = props => ( | ||
h('span', {style: {backgroundColor: props.mark.color}}, props.children) | ||
) | ||
Options is an object with any of the following keys: | ||
```js | ||
{ | ||
customTypeHandlers: { | ||
... | ||
}, | ||
blockTypeHandlers: { | ||
textBlock: { | ||
... | ||
}, | ||
listBlock: { | ||
... | ||
}, | ||
span: { | ||
... | ||
} | ||
marks: { | ||
... | ||
} | ||
} | ||
} | ||
const content = blocksToHtml({ | ||
blocks: input, | ||
serializers: {marks: {highlight}} | ||
}) | ||
``` | ||
Read below for a closer description of each option. | ||
### Specifying image options | ||
#### ``customTypeHandlers: Object`` | ||
An object with keys for your custom block types (which is not of type ``block``). | ||
Each key is mapped to a type, and their value is a function which will get the node as input. | ||
It returns HTML. | ||
```js | ||
customTypeHandlers: { | ||
author: node => { | ||
return `<div>${node.attributes.name}</div>` | ||
} | ||
} | ||
blocksToHtml({ | ||
blocks: input, | ||
imageOptions: {w: 320, h: 240, fit: 'max'}, | ||
projectId: 'myprojectid', | ||
dataset: 'mydataset', | ||
}) | ||
``` | ||
The ``node`` in this example has the following structure: | ||
### Customizing default serializer for `block`-type | ||
```js | ||
{ type: 'author', attributes: { name: 'Test Person' } } | ||
``` | ||
const BlockRenderer = props => { | ||
const style = props.node.style || 'normal' | ||
#### ``blockTypeHandlers: Object`` | ||
Handlers for manipulating the output of the default, built in, block types. | ||
The default block type holds either a block of text or a list. | ||
A text block is built up of spans (with marks), where a list block is built up of list items, | ||
which can contain a text block. | ||
The ``blockTypeHandlers`` object can contain the follow keys: | ||
* ##### ``textBlock: Object`` | ||
Each text block has a ``style``. With this option you can manipulate how each style is rendered. | ||
By default the style ``normal`` is wrapped in a ``<p>``, | ||
where other default styles are mapped 1:1 (style ``h2`` produces ``<h2>``). | ||
The option works in a similar way as ``customTypeHandlers`` described above, | ||
with the distinction that is has a ``children`` property, and the key is the style name: | ||
```js | ||
textBlock: { | ||
normal: node => { | ||
return `<p class="funky-paragraph">${node.children}</p>` | ||
}, | ||
h2: node => { | ||
return `<div class="big-heading">${node.children}</div>` | ||
} | ||
if (/^h\d/.test(style)) { | ||
const level = style.replace(/[^\d]/g, '') | ||
return h('h2', {className: `my-heading level-${level}`}, props.children) | ||
} | ||
``` | ||
* ##### ``listBlock: Object`` | ||
By default lists are rendered with plain ``<ol>``, ``<ul>``and ``<li>`` tags. | ||
With this option you can tweak them into your own liking. | ||
The object takes the following keys: | ||
```js | ||
listBlock: { | ||
number: node => { | ||
return `<ol class="article-list">${node.children}</ol>` | ||
}, | ||
bullet: node => { | ||
return `<ul class="article-list">${node.children}</ul>` | ||
}, | ||
listItem: node => { | ||
return `<li class="article-list-item">${node.children}</li>` | ||
} | ||
} | ||
``` | ||
* ##### ``span: Object`` | ||
Let you tweak how spans within blocks are rendered. By default the spans are | ||
just text and marks. As spans may have attributes with data, you can | ||
make your own render which manipulates the output based on their attributes: | ||
```js | ||
span: node => { | ||
let result = '' | ||
if (node.attributes.author) { | ||
result = ` | ||
<div class="author-bio"> | ||
<img src="${node.attributes.author.image.url}" /> | ||
${node.attributes.author.name} | ||
</div>` | ||
} | ||
if (node.attributes.link) { | ||
result += `<a href="${node.attributes.link.href}">${node.children}</a>` | ||
} | ||
if (Object.keys(node.attributes).length === 0) { | ||
result = node.children | ||
} | ||
return result | ||
} | ||
``` | ||
* ##### ``marks: Object`` | ||
Marks are by default mapped 1:1. If the mark is 'em' the output will be ``<em>``. | ||
With this option you can map marks to other tags, or just ignore them: | ||
```js | ||
marks: { | ||
em: null // Just igonore 'em' marks. | ||
code: 'pre' // Render 'code' marks as 'pre' tags | ||
} | ||
``` | ||
## Custom data on the block content | ||
``block-content-to-html`` supports setting custom data on the original block content | ||
through setting a ``.extra`` property on a block element. This is handy if you want | ||
to generate and keep track of a HTML id attribute, or other arbitrary data related to rendering. | ||
The value can be anything you like. | ||
Example: | ||
```js | ||
const blockContent = { | ||
"_type": "block", | ||
"style": "h2", | ||
"extra": "header_1234", // Our extra property added to the original content. | ||
"spans": [ | ||
{ | ||
"_type": "span", | ||
"text": "Such h2 header, much amaze", | ||
"marks": [] | ||
} | ||
] | ||
return style === 'blockquote' | ||
? h('blockquote', {className: 'my-block-quote'}, props.children) | ||
: h('p', {className: 'my-paragraph'}, props.children) | ||
} | ||
const toHtml = new BlockContentToHtml({ | ||
blockTypeHandlers: { | ||
textBlock: { | ||
h2: node => { | ||
const htmlId = node.extra // Here it is available for us | ||
return `<h2 id="${htmlId}">${node.children}</h2>` | ||
} | ||
} | ||
} | ||
blocksToHtml({ | ||
blocks: input, | ||
serializers: {types: {block: BlockRenderer}} | ||
}) | ||
const html = toHtml.convert(blockContentdata) | ||
``` | ||
Resulting in ``html`` being: | ||
```html | ||
<h2 id="header_1234">Such h2 header, much amaze</h2> | ||
``` | ||
## Utility function | ||
```js | ||
BlockContentToHtml.escapeHtml(unsafe: string) | ||
``` | ||
Escape unsafe text to HTML safe text. To be used with your own handler functions. | ||
## More information / examples | ||
Please see the tests. | ||
## License | ||
MIT-licensed | ||
MIT-licensed. See LICENSE. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
15
2
4
184581
11
154
127
1
+ Added@sanity/block-content-to-hyperscript@1.3.7(transitive)
+ Added@sanity/generate-help-url@0.132.10(transitive)
+ Added@sanity/image-url@0.132.8(transitive)
+ Addedbrowser-split@0.0.0(transitive)
+ Addedclass-list@0.1.1(transitive)
+ Addedhtml-element@2.3.1(transitive)
+ Addedhyperscript@2.0.2(transitive)
+ Addedindexof@0.0.1(transitive)
- Removed@sanity/block-content-to-tree@^0.3.0
- Removedin-publish@^2.0.0
- Removed@sanity/block-content-to-tree@0.3.0(transitive)
- Removedin-publish@2.0.1(transitive)