Skip to content

Commit

Permalink
[rebber] Avoid spoilers in spoilers (solves #280)
Browse files Browse the repository at this point in the history
  • Loading branch information
StaloneLab committed Feb 6, 2020
1 parent 45e124e commit a2d85fe
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,70 @@ secret
\\\\end{FooBar}
\\\\begin{FooBar}
imbricated spoilers
and another
and that's it
\\\\end{FooBar}
\\\\begin{FooBar}
imbricated spoilers
second level
second level too
\\\\end{FooBar}
\\\\begin{FooBar}
imbricated spoilers
second level
with text in between
second level too
\\\\end{FooBar}
\\\\begin{FooBar}
imbricated spoilers
\\\\begin{CodeBlock}{markdown}
and here is some code
\\\\end{CodeBlock}
second level
\\\\end{FooBar}
\\\\begin{FooBar}
do not over-flattenize
expected to be flattened
first level
\\\\begin{Question}
this remains a question
\\\\end{Question}
\\\\end{FooBar}
\\\\begin{FooBar}
flattenize children of children
\\\\begin{Question}
this remains a question
but the content in it is flattened to the question
\\\\end{Question}
\\\\end{FooBar}
\\\\begin{Question}
question \\\\texttt{coded}
\\\\end{Question}
Expand Down
51 changes: 51 additions & 0 deletions packages/rebber-plugins/__tests__/fixtures/blocks.fixture.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,57 @@
[[s]]
| secret

[[s]]
| imbricated spoilers
| [[s]]
| | and another
| | [[s]]
| | | and that's it

[[s]]
| imbricated spoilers
| [[s]]
| | second level
| [[s]]
| | second level too

[[s]]
| imbricated spoilers
| [[s]]
| | second level
|
| with text in between
|
| [[s]]
| | second level too

[[s]]
| imbricated spoilers
|
| ```markdown
| and here is some code
| ```
|
| [[s]]
| | second level

[[s]]
| do not over-flattenize
| [[s]]
| | expected to be flattened
|
| first level
|
| [[q]]
| | this remains a question

[[s]]
| flattenize children of children
| [[q]]
| | this remains a question
| | [[s]]
| | | but the content in it is flattened to the question

[[q]]
| question `coded`

Expand Down
3 changes: 2 additions & 1 deletion packages/rebber-plugins/__tests__/rebber.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-console */
import {readdirSync as directory, readFileSync as file, lstatSync as stat} from 'fs'
import {join} from 'path'
import unified from 'unified'
Expand Down Expand Up @@ -30,6 +29,8 @@ const integrationConfig = {
preprocessors: {
tableCell: require('../src/preprocessors/codeVisitor'),
iframe: require('../src/preprocessors/iframe'),
// eslint-disable-next-line max-len
spoilerFlatten: require('../src/preprocessors/spoilerFlatten')(['sCustomBlock', 'secretCustomBlock']),
},
overrides: {
abbr: require('../src/type/abbr'),
Expand Down
62 changes: 62 additions & 0 deletions packages/rebber-plugins/dist/preprocessors/spoilerFlatten.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"use strict";

var visit = require('unist-util-visit');

module.exports = function (elemNames) {
return function (_, tree) {
// This should contain something like ['sCustomBlockBody', 'secretCustomBlockBody']
var elemNamesBody = elemNames.map(function (v) {
return v.concat('Body');
}); // Iterate over the elements to be flattened

var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;

try {
for (var _iterator = elemNamesBody[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var elemNameBody = _step.value;
visit(tree, elemNameBody, function (node) {
// Recursive function that flattens all matching elements and keeps the others
function flattenizeTree(blockTree) {
return blockTree.map(function (v) {
if (elemNames.includes(v.type)) {
// Get sCustomBlock > sCustomBlockBody > *
var newTree = v.children.filter(function (v) {
return elemNamesBody.includes(v.type);
}).map(function (e) {
return e.children;
}).flat(1); // First level of recursion: on direct descendents

return flattenizeTree(newTree);
} else {
// Second level of recursion: on indirect descendents
if (v.children) {
v.children = flattenizeTree(v.children);
}

return v;
}
}).flat(1);
} // First round on direct children


node.children = flattenizeTree(node.children);
});
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
_iterator["return"]();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
};
};
38 changes: 38 additions & 0 deletions packages/rebber-plugins/src/preprocessors/spoilerFlatten.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const visit = require('unist-util-visit')

module.exports = (elemNames) =>
(_, tree) => {
// This should contain something like ['sCustomBlockBody', 'secretCustomBlockBody']
const elemNamesBody = elemNames.map(v => v.concat('Body'))

// Iterate over the elements to be flattened
for (const elemNameBody of elemNamesBody) {
visit(tree, elemNameBody, node => {
// Recursive function that flattens all matching elements and keeps the others
function flattenizeTree (blockTree) {
return blockTree.map(v => {
if (elemNames.includes(v.type)) {
// Get sCustomBlock > sCustomBlockBody > *
const newTree = v.children
.filter(v => elemNamesBody.includes(v.type))
.map(e => e.children)
.flat(1)

// First level of recursion: on direct descendents
return flattenizeTree(newTree)
} else {
// Second level of recursion: on indirect descendents
if (v.children) {
v.children = flattenizeTree(v.children)
}

return v
}
}).flat(1)
}

// First round on direct children
node.children = flattenizeTree(node.children)
})
}
}
64 changes: 64 additions & 0 deletions packages/zmarkdown/__tests__/__snapshots__/latex.tests.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,70 @@ secret
\\\\end{Spoiler}
\\\\begin{Spoiler}
imbricated spoilers
and another
and that's it
\\\\end{Spoiler}
\\\\begin{Spoiler}
imbricated spoilers
second level
second level too
\\\\end{Spoiler}
\\\\begin{Spoiler}
imbricated spoilers
second level
with text in between
second level too
\\\\end{Spoiler}
\\\\begin{Spoiler}
imbricated spoilers
\\\\begin{CodeBlock}{markdown}
and here is some code
\\\\end{CodeBlock}
second level
\\\\end{Spoiler}
\\\\begin{Spoiler}
do not over-flattenize
expected to be flattened
first level
\\\\begin{Question}
this remains a question
\\\\end{Question}
\\\\end{Spoiler}
\\\\begin{Spoiler}
flattenize children of children
\\\\begin{Question}
this remains a question
but the content in it is flattened to the question
\\\\end{Question}
\\\\end{Spoiler}
\\\\begin{Question}
question \\\\CodeInline{coded}
\\\\end{Question}
Expand Down
51 changes: 51 additions & 0 deletions packages/zmarkdown/__tests__/fixtures/latex/blocks.fixture.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,57 @@
[[s]]
| secret

[[s]]
| imbricated spoilers
| [[s]]
| | and another
| | [[s]]
| | | and that's it

[[s]]
| imbricated spoilers
| [[s]]
| | second level
| [[s]]
| | second level too

[[s]]
| imbricated spoilers
| [[s]]
| | second level
|
| with text in between
|
| [[s]]
| | second level too

[[s]]
| imbricated spoilers
|
| ```markdown
| and here is some code
| ```
|
| [[s]]
| | second level

[[s]]
| do not over-flattenize
| [[s]]
| | expected to be flattened
|
| first level
|
| [[q]]
| | this remains a question

[[s]]
| flattenize children of children
| [[q]]
| | this remains a question
| | [[s]]
| | | but the content in it is flattened to the question

[[q]]
| question `coded`

Expand Down
2 changes: 2 additions & 0 deletions packages/zmarkdown/config/rebber.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/* eslint-disable max-len */
const remarkConfig = require('./remark')
const escape = require('rebber/dist/escaper')

const rebberConfig = {
preprocessors: {
tableCell: require('rebber-plugins/dist/preprocessors/codeVisitor'),
spoilerFlatten: require('rebber-plugins/dist/preprocessors/spoilerFlatten')(['sCustomBlock', 'secretCustomBlock']),
},
overrides: {
abbr: require('rebber-plugins/dist/type/abbr'),
Expand Down

0 comments on commit a2d85fe

Please sign in to comment.