Skip to content

Commit 497c289

Browse files
committed
Initial commit
0 parents  commit 497c289

File tree

10 files changed

+386
-0
lines changed

10 files changed

+386
-0
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
*.log
3+
.nyc_output/
4+
coverage/
5+
node_modules/
6+
hast-util-shift-heading.js
7+
hast-util-shift-heading.min.js
8+
yarn.lock

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
coverage/
2+
hast-util-shift-heading.js
3+
hast-util-shift-heading.min.js

.travis.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
language: node_js
2+
node_js:
3+
- lts/boron
4+
- node
5+
after_script: bash <(curl -s https://codecov.io/bash)
6+
deploy:
7+
provider: releases
8+
skip_cleanup: true
9+
api_key:
10+
secure: IYXY7MBbagEO51JWNlHHZxkP+AE5TqCx3wx4Yw4Rjz0Pqp7QvsprdSNwYgqpIeMcnA/N1RwsMq+UhCCphpzI8MSS0AKsR786ndJd4T4e6MdbQ1DIAAI4e/29De6KbW4ca130Ez5eepUdQl1i6+CL26fKg/4tMdfWQdL+7IlcfZDUdDqHmv3X6OKtISNUeMnU6i4tZuaQHHWbkRWyvkbQK4SISPIrxWOlAE5zZSv+mnBFJKnwxo8CDKCCQidbUlHvPYx71tZbtm2oEaUb8RKjbWb3Da170E3VbulyeCaASQVfPkyseo1eK+bS+SCVYd7jtjofFwTDoHjhxEgsya0FaivSRsxs9iSUO6z4nk0O2T/7F5UkKbgndFqMVRwbvKeklFYN9SMNzEMoEB6lSgjrUwH5WvjyrAuhyfpoXu2sdTMSo/mahcgVyoAQTGsk+i3YWxQbLrwrR1DAbWDZX6/TkEp8cupofDxXI+UcvLO+pBsPlnwMS3k/anJeelVhcJrTnsRTwiJ8H6UL0HGpQ98bOyoPobPFlQq0+T8dZdnyblGQcHDPqOZ6od7TlO9ce3qt+xOiQOtAqqRjnXGasaeIScYnsiz0qhl4yglUS3BdUUG/MybUAJadEjkxkauS5iuPU5X+5wito9E2+gLsqu8Ejv8nHv7TG1k6Bf6y+IHu0JU=
11+
file:
12+
- 'hast-util-shift-heading.js'
13+
- 'hast-util-shift-heading.min.js'
14+
on:
15+
tags: true

index.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict'
2+
3+
var visit = require('unist-util-visit')
4+
5+
module.exports = shiftHeading
6+
7+
var floor = Math.floor
8+
var min = 1
9+
var max = 6
10+
var offset = 48 // '0'.charCodeAt(0)
11+
12+
function shiftHeading(tree, shift) {
13+
if (
14+
typeof shift !== 'number' ||
15+
!shift ||
16+
!isFinite(shift) ||
17+
floor(shift) !== shift
18+
) {
19+
throw new Error('Expected a non-null finite integer, not `' + shift + '`')
20+
}
21+
22+
visit(tree, visitor)
23+
24+
return tree
25+
26+
function visitor(node) {
27+
var name = node.tagName
28+
var rank
29+
30+
if (
31+
name === 'h1' ||
32+
name === 'h2' ||
33+
name === 'h3' ||
34+
name === 'h4' ||
35+
name === 'h5' ||
36+
name === 'h6'
37+
) {
38+
rank = name.charCodeAt(1) - offset + shift
39+
node.tagName = 'h' + (rank > max ? max : rank < min ? min : rank)
40+
}
41+
}
42+
}

license

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
(The MIT License)
2+
3+
Copyright (c) 2019 Titus Wormer <tituswormer@gmail.com>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining
6+
a copy of this software and associated documentation files (the
7+
'Software'), to deal in the Software without restriction, including
8+
without limitation the rights to use, copy, modify, merge, publish,
9+
distribute, sublicense, and/or sell copies of the Software, and to
10+
permit persons to whom the Software is furnished to do so, subject to
11+
the following conditions:
12+
13+
The above copyright notice and this permission notice shall be
14+
included in all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package.json

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"name": "hast-util-shift-heading",
3+
"version": "0.0.0",
4+
"description": "Change heading rank (or depth, level) in hast",
5+
"license": "MIT",
6+
"keywords": [
7+
"heading",
8+
"rank",
9+
"depth",
10+
"level",
11+
"shift",
12+
"change",
13+
"hast",
14+
"html",
15+
"util",
16+
"utility"
17+
],
18+
"repository": "syntax-tree/hast-util-shift-heading",
19+
"bugs": "https://github.com/syntax-tree/hast-util-shift-heading/issues",
20+
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
21+
"contributors": [
22+
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
23+
],
24+
"files": [
25+
"index.js"
26+
],
27+
"dependencies": {
28+
"unist-util-visit": "^1.4.0"
29+
},
30+
"devDependencies": {
31+
"browserify": "^16.0.0",
32+
"hastscript": "^5.0.0",
33+
"nyc": "^13.0.0",
34+
"prettier": "^1.13.5",
35+
"remark-cli": "^6.0.0",
36+
"remark-preset-wooorm": "^4.0.0",
37+
"tape": "^4.4.0",
38+
"tinyify": "^2.4.3",
39+
"xo": "^0.24.0"
40+
},
41+
"scripts": {
42+
"format": "remark . -qfo && prettier --write \"**/*.js\" && xo --fix",
43+
"build-bundle": "browserify . -s hastUtilShiftHeading > hast-util-shift-heading.js",
44+
"build-mangle": "browserify . -s hastUtilShiftHeading -p tinyify > hast-util-shift-heading.min.js",
45+
"build": "npm run build-bundle && npm run build-mangle",
46+
"test-api": "node test",
47+
"test-coverage": "nyc --reporter lcov tape test.js",
48+
"test": "npm run format && npm run build && npm run test-coverage"
49+
},
50+
"prettier": {
51+
"tabWidth": 2,
52+
"useTabs": false,
53+
"singleQuote": true,
54+
"bracketSpacing": false,
55+
"semi": false,
56+
"trailingComma": "none"
57+
},
58+
"xo": {
59+
"prettier": true,
60+
"esnext": false,
61+
"ignores": [
62+
"hast-util-shift-heading.js"
63+
]
64+
},
65+
"nyc": {
66+
"check-coverage": true,
67+
"lines": 100,
68+
"functions": 100,
69+
"branches": 100
70+
},
71+
"remarkConfig": {
72+
"plugins": [
73+
"preset-wooorm"
74+
]
75+
}
76+
}

readme.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# hast-util-shift-heading [![Build][build-badge]][build] [![Coverage][coverage-badge]][coverage] [![Chat][chat-badge]][chat]
2+
3+
Change heading rank (or depth, level) in **[hast][]**.
4+
5+
## Installation
6+
7+
[npm][]:
8+
9+
```bash
10+
npm install hast-util-shift-heading
11+
```
12+
13+
## Usage
14+
15+
```javascript
16+
var h = require('hastscript')
17+
var shift = require('hast-util-shift-heading')
18+
19+
var tree = h('main', [
20+
h('h1', 'Alpha'),
21+
h('p', 'Bravo'),
22+
h('h2', 'Charlie'),
23+
h('p', 'Delta'),
24+
h('h5', 'Echo'),
25+
h('p', 'Foxtrot'),
26+
h('h6', 'Golf')
27+
])
28+
29+
shift(tree, -1)
30+
31+
console.log(tree)
32+
```
33+
34+
Yields:
35+
36+
```js
37+
{ type: 'element',
38+
tagName: 'main',
39+
properties: {},
40+
children:
41+
[ { type: 'element',
42+
tagName: 'h1',
43+
properties: {},
44+
children: [Array] },
45+
{ type: 'element',
46+
tagName: 'p',
47+
properties: {},
48+
children: [Array] },
49+
{ type: 'element',
50+
tagName: 'h1',
51+
properties: {},
52+
children: [Array] },
53+
{ type: 'element',
54+
tagName: 'p',
55+
properties: {},
56+
children: [Array] },
57+
{ type: 'element',
58+
tagName: 'h4',
59+
properties: {},
60+
children: [Array] },
61+
{ type: 'element',
62+
tagName: 'p',
63+
properties: {},
64+
children: [Array] },
65+
{ type: 'element',
66+
tagName: 'h5',
67+
properties: {},
68+
children: [Array] } ] }
69+
```
70+
71+
## API
72+
73+
### `shiftHeading(tree, shift)`
74+
75+
Change the rank of all headings (`h1` to `h6`) in `tree`.
76+
Mutates the tree.
77+
Caps the rank so that shifting would not create invalid headings (such as `h0`
78+
or `h7`).
79+
80+
###### Parameters
81+
82+
* `tree` ([`Node`][node]) — Tree to walk
83+
* `shift` (`number`) — Non-null finite integer to use to shift ranks
84+
85+
###### Returns
86+
87+
`tree` ([`Node`][node]) — The given, mutated, tree.
88+
89+
###### Throws
90+
91+
`Error` — When `shift` is not a valid non-null finite integer.
92+
93+
## Contribute
94+
95+
See [`contributing.md` in `syntax-tree/hast`][contributing] for ways to get
96+
started.
97+
98+
This organisation has a [Code of Conduct][coc]. By interacting with this
99+
repository, organisation, or community you agree to abide by its terms.
100+
101+
## License
102+
103+
[MIT][license] © [Titus Wormer][author]
104+
105+
<!-- Definition -->
106+
107+
[build-badge]: https://img.shields.io/travis/syntax-tree/hast-util-shift-heading.svg
108+
109+
[build]: https://travis-ci.org/syntax-tree/hast-util-shift-heading
110+
111+
[coverage-badge]: https://img.shields.io/codecov/c/github/syntax-tree/hast-util-shift-heading.svg
112+
113+
[coverage]: https://codecov.io/github/syntax-tree/hast-util-shift-heading
114+
115+
[chat-badge]: https://img.shields.io/badge/join%20the%20community-on%20spectrum-7b16ff.svg
116+
117+
[chat]: https://spectrum.chat/unified/rehype
118+
119+
[npm]: https://docs.npmjs.com/cli/install
120+
121+
[license]: license
122+
123+
[author]: https://wooorm.com
124+
125+
[hast]: https://github.com/syntax-tree/hast
126+
127+
[node]: https://github.com/syntax-tree/unist#node
128+
129+
[contributing]: https://github.com/syntax-tree/hast/blob/master/contributing.md
130+
131+
[coc]: https://github.com/syntax-tree/hast/blob/master/code-of-conduct.md

test.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
'use strict'
2+
3+
var test = require('tape')
4+
var h = require('hastscript')
5+
var shift = require('.')
6+
7+
test('shiftHeading', function(t) {
8+
t.throws(
9+
function() {
10+
shift(h())
11+
},
12+
/^Error: Expected a non-null finite integer, not `undefined`$/,
13+
'should throw when not given a number'
14+
)
15+
16+
t.throws(
17+
function() {
18+
shift(h(), NaN)
19+
},
20+
/^Error: Expected a non-null finite integer, not `NaN`$/,
21+
'should throw when given not a number'
22+
)
23+
24+
t.throws(
25+
function() {
26+
shift(h(), 0.1)
27+
},
28+
/^Error: Expected a non-null finite integer, not `0.1`$/,
29+
'should throw when not given an integer'
30+
)
31+
32+
t.throws(
33+
function() {
34+
shift(h(), Infinity)
35+
},
36+
/^Error: Expected a non-null finite integer, not `Infinity`$/,
37+
'should throw when not given a finite number'
38+
)
39+
40+
t.throws(
41+
function() {
42+
shift(h(), 0)
43+
},
44+
/^Error: Expected a non-null finite integer, not `0`$/,
45+
'should throw when not given a non-null number'
46+
)
47+
48+
t.deepEqual(
49+
shift(h('h1', 'Alpha'), 1),
50+
h('h2', 'Alpha'),
51+
'should shift nodes upwards'
52+
)
53+
54+
t.deepEqual(
55+
shift(h('h2', 'Bravo'), -1),
56+
h('h1', 'Bravo'),
57+
'should shift nodes downwards'
58+
)
59+
60+
t.deepEqual(
61+
shift(h('h2', 'Charlie'), -2),
62+
h('h1', 'Charlie'),
63+
'should not shift upwards past h1'
64+
)
65+
66+
t.deepEqual(
67+
shift(h('h5', 'Delta'), 2),
68+
h('h6', 'Delta'),
69+
'should not shift downwards past h6'
70+
)
71+
72+
t.deepEqual(
73+
shift(h('main', [h('h1', 'Echo'), h('p', 'Foxtrot'), h('h5', 'Golf')]), 2),
74+
h('main', [h('h3', 'Echo'), h('p', 'Foxtrot'), h('h6', 'Golf')]),
75+
'should change a tree'
76+
)
77+
78+
t.end()
79+
})

0 commit comments

Comments
 (0)