Skip to content

Commit 56d0824

Browse files
committed
Build some dark magics with replaceAll
1 parent e3a6d9a commit 56d0824

File tree

3 files changed

+120
-102
lines changed

3 files changed

+120
-102
lines changed

all.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'use strict';
2+
3+
const is = require('unist-util-is');
4+
5+
function replaceAllBetween(parent, start, end, func) {
6+
if (!parent || !parent.type || !parent.children) {
7+
throw new Error('Expected parent node');
8+
}
9+
10+
const {children} = parent;
11+
12+
const isStart = node => is(node, start);
13+
const isEnd = node => is(node, end);
14+
15+
/**
16+
* @type {Array<{start: number, end: number}>}
17+
*/
18+
const ranges = children.reduce((prev, child, i) => {
19+
const lastPrev = prev[prev.length - 1];
20+
if (isStart(children[i])) {
21+
if (lastPrev && !lastPrev.end) {
22+
console.error('Attempted to start a second replacement before the first one was cleaned up');
23+
return prev;
24+
}
25+
prev.push({
26+
start: i
27+
});
28+
return prev;
29+
}
30+
if (isEnd(children[i])) {
31+
lastPrev.end = i;
32+
}
33+
return prev;
34+
}, []);
35+
36+
// The function will return a different length than the original
37+
// This offset is used to correct
38+
let offset = 0;
39+
40+
return ranges.map(({start, end}) => {
41+
const offsetStart = start + offset;
42+
const offsetEnd = end + offset;
43+
44+
const replaced = children.slice(offsetStart, offsetEnd + 1);
45+
46+
const changedArray = func(replaced);
47+
48+
const diff = children.splice(offsetStart, offsetEnd - offsetStart + 1, ...changedArray);
49+
50+
offset -= diff.length - changedArray.length;
51+
52+
return changedArray;
53+
});
54+
}
55+
56+
module.exports = replaceAllBetween;

example/example.js

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {remark} from 'remark'
22
import {is} from 'unist-util-is';
3-
import replaceBetween from '../index.js';
3+
import replaceAllBetween from '../all.js';
44

55
const markdown = `
66
# Hello World!
@@ -26,8 +26,50 @@ Ciao!
2626
Testing
2727
2828
# Test
29+
30+
31+
<!-- tabs:start -->
32+
33+
#### **English**
34+
35+
Hello!
36+
37+
#### **French**
38+
39+
Bonjour!
40+
41+
Telakjdsf
42+
43+
asdf
44+
45+
<!-- tabs:end -->
46+
47+
# Testing
48+
49+
![](asdf)
2950
`;
3051

52+
/**
53+
* @typedef {Object} Section
54+
* @prop {string} header
55+
* @prop {any[]} range
56+
*/
57+
58+
/**
59+
* @returns {Section[]}
60+
*/
61+
const getSections = (allChildren, headerIndexes) =>
62+
headerIndexes.map((_, i, arr) => {
63+
let [startIndex, endIndex] = [arr[i], arr[i + 1]];
64+
const header = allChildren[startIndex];
65+
startIndex += 1;
66+
67+
return {
68+
header,
69+
range: allChildren.slice(startIndex, endIndex)
70+
};
71+
});
72+
3173
// Create a plugin for remark
3274
const plugin = () => (tree) => {
3375
// `start` and `end` nodes to look for, and find between.
@@ -42,19 +84,36 @@ const plugin = () => (tree) => {
4284
};
4385

4486
// Get lists between `start` and `end`
45-
replaceBetween(tree, start, end, list => {
87+
replaceAllBetween(tree, start, end, list => {
4688
// Remove both `tabs` mention
47-
list.shift();
48-
list.pop()
89+
// list.shift();
90+
// list.pop()
91+
92+
console.log({list});
4993

5094
const headerIndexes = list
5195
.map((node, i) => is(node, {type: 'heading'}) && i)
5296
.filter(Number.isInteger)
5397

5498
return [{
5599
type: 'html',
56-
value: headerIndexes
100+
value: headerIndexes.toString()
57101
}]
102+
103+
// const sections = getSections(list, headerIndexes);
104+
//
105+
// const tabNodes = sections.map(section => {
106+
// return {
107+
// type: 'tab',
108+
// heading: section.heading,
109+
// children: section.range
110+
// }
111+
// })
112+
//
113+
// return [{
114+
// type: 'tabList',
115+
// children: tabNodes
116+
// }]
58117
});
59118

60119
// Return new tree
@@ -65,19 +124,3 @@ remark()
65124
.use(plugin)
66125
.process(markdown)
67126
.then((result) => console.log(result.toString()), console.error);
68-
69-
/**
70-
* Outputs:
71-
*
72-
* **List one:**
73-
*
74-
* - 1
75-
* - 2
76-
*
77-
* **List two:**
78-
*
79-
* - 3
80-
* - 4
81-
* - 5
82-
*
83-
*/

test.js

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,87 +4,6 @@ const {test} = require('tap');
44
const findAllBetween = require('.');
55

66
test('unist-util-find-all-between', (test) => {
7-
test.throws(() => {
8-
findAllBetween();
9-
}, 'Should fail without parent node');
10-
11-
test.throws(() => {
12-
findAllBetween({type: 'foo'});
13-
}, 'Should fail without parent node');
14-
15-
test.doesNotThrow(() => {
16-
test.throws(() => {
17-
findAllBetween({type: 'foo', children: []});
18-
}, 'Expected positive finite index or child node');
19-
20-
test.throws(() => {
21-
findAllBetween({type: 'foo', children: []}, -1);
22-
}, 'Expected positive finite index or child node');
23-
24-
test.throws(() => {
25-
findAllBetween({type: 'foo', children: []}, {type: 'bar'});
26-
}, 'Expected positive finite index or child node');
27-
28-
test.throws(() => {
29-
findAllBetween({type: 'foo', children: []}, 1, {type: 'bar'});
30-
}, 'Expected positive finite index or child node');
31-
}, 'Should fail without index');
32-
33-
test.doesNotThrow(() => {
34-
test.ok(
35-
findAllBetween(
36-
{
37-
type: 'foo',
38-
children: [
39-
{
40-
type: 'foo'
41-
},
42-
{
43-
type: 'bar'
44-
}
45-
]
46-
},
47-
0,
48-
1,
49-
(v) => v
50-
)
51-
);
52-
}, 'Should not throw with `unist-util-is` >= 4.0.0');
53-
54-
test.doesNotThrow(() => {
55-
test.deepEqual(
56-
findAllBetween(
57-
{
58-
type: 'foo',
59-
children: [
60-
{
61-
type: 'foo'
62-
},
63-
{
64-
type: 'bar'
65-
},
66-
{
67-
type: 'baz'
68-
}
69-
]
70-
},
71-
0,
72-
2,
73-
(v) => v
74-
),
75-
[
76-
{
77-
type: 'foo'
78-
},
79-
{
80-
type: 'bar'
81-
},
82-
{
83-
type: 'baz'
84-
}
85-
]
86-
);
87-
}, 'Expects identity function to return the same');
887

898
test.doesNotThrow(() => {
909
test.deepEqual(

0 commit comments

Comments
 (0)