New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mdast-util-split: start of work #315
Conversation
961dfef
to
6ea2466
Compare
Nice! I'll do a few rounds of reviews, the first one will only be obvious things, later on I might PR against your branch to fix trickier things. [edit]cf. artragis#7 [/edit] I'm not sure about the naming of this package. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add tests for other depths and test a file with no heading.
packages/mdast-util-split/README.md
Outdated
# mdast-util-split [![Build Status][build-badge]][build-status] [![Coverage Status][coverage-badge]][coverage-status] | ||
|
||
|
||
**rebber** is a LaTeX stringifier for [remark][] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
**rebber** is a LaTeX stringifier for [remark][] |
module.exports = split | ||
import visit from 'unist-util-visit' | ||
|
||
function split (tree, {splitDepth = 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
splitDepth
is not used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not yet implemented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it's implemented, but I'm not happy at all with my namings, I always mix "trees" and "children" and it's quite complex when splitDepth is greater than 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's confusing I agree. I think this.subTrees
actually refers to new root trees, not subtrees?
Try drawing a simple schema of the output for a simple md doc at various splitDepth
, it should make it easier to see what is a root tree, what is a subtree (i.e. a subpart of mdast root tree)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the introduction
# chapter 1
a paragraph
> a quote to *ensure this is parsed*
## section 1.1
content 1.1
## subsection 1.1.1
content 1.1.1
## section 1.2
content 1.2
# chapter 2
## subsection 2.1.1
content 2.1.1
# the conclusion
paragraph
For instance what is expected here with splitDepth 1 and splitDepth 2?
My guess for splitDepth 1:
{
introduction: {type: root, children: [/* from doc root to `chapter 1` (not included) */]},
trees: [
{type: root, children: [/* from `chapter 1` to `chapter 2` (not included) */]},
{type: root, children: [/* from `chapter 2` to `conclusion` (not included) */]},
],
conclusion: {type: root, children: [/* from `chapter 2` (not included) to document end */]},
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this one, it is what I want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, not, the conclusion
must be from "conclusion" (not included)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is what you mean:
{
introduction: {type: root, children: [/* from doc root to `chapter 1` (not included) */]},
trees: [
{type: root, children: [/* from `chapter 1` to `chapter 2` (not included) */]},
{type: root, children: [/* from `chapter 2` to `conclusion` (not included) */]},
],
conclusion: {type: root, children: [/* from `conclusion` (not included) to document end */]},
}
What about splitDepth 2 for this document?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is what I mean. For splitDepth 2 here it what i would like :
{
introduction: {type: root, children: [/* from doc root to `chapter 1` (not included) */]},
title: { type: root, children: [/*the heading node*/],
trees: [
{type: root, title: {type: 'root', children:[/*chapter 1 heading*/]},
trees: [/** trees for section1.1=>section 1.2],
conclusion: {type: root, children:[/* content of section 1.2, but heading discarded*/]},
{type: root, children: [/* from `chapter 2` to `conclusion` (not included) */]},
],
conclusion: {type: root, children: [/* from `conclusion` (not included) to document end */]},
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does chapter 1 have a conclusion but no introduction? Could you please explain how all of this works in the README?
}) | ||
} | ||
extractIntroductions () { | ||
const self = this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this trick
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can I do it then? if I use this in the lambda, this is undifined
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this
will be the object, not undefined
.
packages/mdast-util-split/README.md
Outdated
A boolean driving the way we want to process introduction : | ||
- if `true`, all MDAST elements between the split header and the first sub header will be extracted and put in the `introduction` property of the result | ||
property of the returned object | ||
- if `false` they will just be added as MDAST elements of the `children` property. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this line, could you please clarify?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the property set to false, we do not extract the introduction from the tree. In though I had changed like for the conclusion in if false, the part tree will not be changed
property of the returned object | ||
- if `false` they will just be added as MDAST elements of the `children` property. | ||
|
||
#### `options.conclusionAsProperty` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#### `options.conclusionAsProperty` | |
#### `options.conclusionAsProperty = false` |
|
||
A boolean driving the way we want to process the last sub header if there are more than one. | ||
- if `true`, the last sub header is removed from tree and all following elements are stored in the `conclusion` property of the result | ||
- if `false` (default), nothing is changed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- if `false` (default), nothing is changed. | |
- if `false`, nothing is changed. |
this.depth = depth | ||
this._introduction = newRootTree() | ||
} | ||
set introduction (nodes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a getter/setter here makes it harder to understand IMO but I might be failing to see the benefits it brings.
_introduction
is already initialized in the constructor, and later on (for instance l.120) when we assign to introduction
it's hard to tell whether it enter the setter or not. I would refactor to not use these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I wanted to use a "simple" get/set at the beginning, failed and instead of reworking the whole code kept the get/set. if you want to remove this, you clearly can, it's an antipattern now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good, go ahead then
} | ||
extractConclusions () { | ||
this.subTrees.forEach(splittedPart => { | ||
const firstHeading = find(splittedPart.children, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
splitPart
, not splitted
splittedPart.conclusion = newRootTree(rootContent) | ||
}) | ||
} | ||
extractIntroductions () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In which cases do we have several introductions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when all chapters have introductions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still extract it when only one chapter has one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we extract it for every chapter that has one introduction.
Thanks to your first review and PR I could have a better view on my work and I was wondering if I was not trying to create a too complex thing. An idea that showed up was to say : just extract one level with two parametters :
the result would just be :
thanks to that we can use all the existing utils on subtrees if we want a deeper splitting or a specific treatment. |
Nice! I agree, the initial code was quite complicated and the purpose unclear, it's good we now see things more clearly.
If I understand correctly, when Other than that I like the new idea. Mapping the splitter to its result (with depth+1) is good enough when a deeper split is required. |
in fact I would say
perhaps you were rephrasing my message but I do not get it here. What do you mean by "mapping the splitter to its result"? |
const splitAtDepth = (depth) => (tree) => split(tree, { depth })
const level1 = splitAtDepth(1)(doc)
const level2 = level1.chapters.map(splitAtDepth(2)) |
beb8f63
to
1368878
Compare
11e7593
to
33c487c
Compare
What about |
About module name : I do not know what is better and having a look at unified documentation I saw you're part of the kind-of-board of unified/remark ecosystem so I think you can put the name you want without negociating it will be the best thing for remark ecosystem. |
Context
this PR aims to add a new mdast-util project to prepare some work on zmarkdown that will try to import a flat markdown text to a fully hierarchized tutorial/article.
For that I need an util to traverse all headings and extract "part" from what follow those headings.
What is done
What remains before merging
conclusion
parameter)unist-util-find
but as it finds everything in depth I changed the logic to a custom function that I haven't fully tested yetmdast-util-normalize
part > subpart > chapter)
Why doing such a PR?