Skip to content

Refactor buildExpression to depth-first traverse groups (nodes), fix spacings and \begingroup...\endgroup#1706

Merged
k4b7 merged 8 commits intoKaTeX:masterfrom
ylemkimon:build-expression
Oct 29, 2018
Merged

Refactor buildExpression to depth-first traverse groups (nodes), fix spacings and \begingroup...\endgroup#1706
k4b7 merged 8 commits intoKaTeX:masterfrom
ylemkimon:build-expression

Conversation

@ylemkimon
Copy link
Member

@ylemkimon ylemkimon commented Sep 7, 2018

Fixes #1108 and fixes #1679. This also allows the implementation of semi-simple (partial, transparent, i.e., doesn't affect spacing around) groups like \class and \cssId in #1437.

This PR refactors buildExpression to depth-first traverse (DFS) groups (nodes), going into Anchor and possibly other nodes in the future.

Also, this PR fixes \begingroup...\endgroup, which only can be ended by \endgroup and is semi-simple group.

export const getTypeOfDomTree = function(
node: ?HtmlDomNode,
side: Side,
side: ?Side,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment makes it sound kind of hacky. Is this how LaTeX resets text-align? Any thoughts on a better way to do this?

@codecov
Copy link

codecov bot commented Sep 7, 2018

Codecov Report

Merging #1706 into master will decrease coverage by 0.09%.
The diff coverage is 95.89%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master    #1706     +/-   ##
=========================================
- Coverage   94.01%   93.91%   -0.1%     
=========================================
  Files          78       78             
  Lines        4558     4570     +12     
  Branches      792      796      +4     
=========================================
+ Hits         4285     4292      +7     
- Misses        242      246      +4     
- Partials       31       32      +1
Flag Coverage Δ
#screenshotter 88.55% <91.78%> (-0.11%) ⬇️
#test 85.29% <95.89%> (-0.1%) ⬇️
Impacted Files Coverage Δ
src/functions/delimsizing.js 97.64% <ø> (ø) ⬆️
src/parseNode.js 84.21% <ø> (ø) ⬆️
src/macros.js 97.05% <ø> (-0.02%) ⬇️
src/Parser.js 97.2% <100%> (ø) ⬆️
src/functions/ordgroup.js 100% <100%> (ø) ⬆️
src/buildHTML.js 95.77% <95.38%> (-3.46%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5f3ab13...2f5c72b. Read the comment docs.

@ylemkimon ylemkimon added this to the Version 0.10.0 milestone Sep 8, 2018
src/buildHTML.js Outdated
right.classes[0] = "mord";
}, {node: dummyPrev}, dummyNext);

traverseNodes(groups, (node, prev) => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible to traverse only once, but it's more complicated since it needs to retain previous spacing information. I'm not sure which is more optimal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My preference is for multiple passes with simpler code.

@ylemkimon ylemkimon changed the title Refactor buildExpression to depth-first traverse groups (nodes), fix spacings Refactor buildExpression to depth-first traverse groups (nodes), fix spacings and \begingroup...\endgroup Sep 16, 2018
src/Parser.js Outdated
} else if (!optional && this.nextToken.text === "\\begingroup") {
// A group formed by /begingroup...\endgroup is a semi-simple group,
// which doesn't affect spacing in math mode, i.e., is transparent
semisimple = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a reference to the TeXBook or similar resource?

Copy link
Member Author

@ylemkimon ylemkimon Sep 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinbarabash Semi-simple group is mentioned in TeX: The Program, but I really cannot find a reference regarding its spacing or the fact that it doesn't create a mathord.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you determine the behavior by seeing what LaTeX does for different test cases?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this behavior matches my experience testing with LaTeX. I don't see it documented in The TeXbook. But the TeX source code definitely calls groups started with \begingroup "semi-simple groups" (search for begin_group), and it definitely does something special with them (search for semi_simple_group). But I'm no expert at that code...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinbarabash I've added a link to stack exchange answer, as it has enough up-votes.

src/buildHTML.js Outdated

return groups;
// Check if given node is a partial group, i.e., does not affect spacing around,
// like fragment.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mis-parsed this comment on the first read. The intent is that partial groups behave the same as fragment, i.e. they don't affect the spacing around it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinbarabash I've removed like fragment.

// like fragment.
const checkPartialGroup = function(
node: HtmlDomNode,
): ?(DocumentFragment<HtmlDomNode> | Anchor) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should define type PartialGroup = DocumentFragment<HtmlDomNode> | Anchor.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinbarabash I think it's better to have it close to instanceof checks.


traverseNodes(groups, (node, prev) => {
const prevType = getTypeOfDomTree(prev);
const type = getTypeOfDomTree(node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we need the side argument here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinbarabash The callback function will be only called on non-partial groups.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, but it's not obvious. Could you add a comment here before merging this?

src/buildHTML.js Outdated
// previous node as arguments, optionally returning a node to insert after the
// previous node. `prev` is an object with the previous node and `insertAfter`
// function to insert after it. `next` is a node that will be added to the right.
const traverseNodes = function(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth unit testing this. Also the name is very general but it some logic that's super specific to modifying spacing. Can you change the name and update the comment to reflect this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinbarabash I've renamed the function to traverseNonSpaceNodes and added comments about its usage. We really need a way to unit-test functions.


it("should not affect spacing in math mode", function() {
const built = getBuilt`\begingroup x+ \endgroup y`;
expect(built).toMatchSnapshot();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe compare this build tree with that of x + y,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinbarabash Fixed.


it("should not affect spacing around", function() {
const built = getBuilt`a\href{http://example.com/}{+b}`;
expect(built).toMatchSnapshot();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snapshot looks good.

@edemaine edemaine mentioned this pull request Oct 13, 2018
Copy link
Member

@k4b7 k4b7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Requesting one additional comment about why we don't need to pass the side argument to getTypeOfDomTree on lines 120-121 of buildHTML.js.

@k4b7 k4b7 merged commit a3215b2 into KaTeX:master Oct 29, 2018
@k4b7
Copy link
Member

k4b7 commented Oct 29, 2018

LGTM. Requesting one additional comment about why we don't need to pass the side argument to getTypeOfDomTree on lines 120-121 of buildHTML.js.

I forgot about this. I guess it wasn't that important.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

\begingroup messes up spacing Spacing inside \href is wrong

3 participants