Skip to content

Commit

Permalink
Fix font commands extending to all binary and ternary operants
Browse files Browse the repository at this point in the history
**Output Changes**

* When writing something like `bf A_(ij)` previously the boldface was
  incorrectly applied to the indices (ij) as well as the intended
  matrix (A). Now the boldface will only be applied to the matrix
  unless everything is put in a group `bf (A_(ij))`.

Fixes: #97
  • Loading branch information
runarberg committed Nov 24, 2023
1 parent 90740a3 commit 8af250a
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 32 deletions.
88 changes: 62 additions & 26 deletions src/compiler/parser/handlers/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,54 @@ import expr from "./expr.js";
* @typedef {import("../../tokenizer/index.js").Token} Token
* @typedef {import("../index.js").Node} Node
* @typedef {import("../index.js").UnaryOperation} UnaryOperation
* @typedef {import("../index.js").BinaryOperation} BinaryOperation
* @typedef {import("../index.js").TernaryOperation} TernaryOperation
* @typedef {UnaryOperation | BinaryOperation | TernaryOperation} Operation
* @typedef {import("../index.js").Term} Term
*/

/**
* @param {Node} node
* @param {string[]} transforms
* @returns {Operation | Term}
*/
function insertTransformNode(node, transforms) {
if (node.type === "Term" && node.items.length > 0) {
// Only apply transform to first node.
const [first, ...rest] = node.items;
return {
...node,
items: [insertTransformNode(first, transforms), ...rest],
};
}

if (node.type === "BinaryOperation") {
const [left, right] = node.items;
return {
...node,
items: [insertTransformNode(left, transforms), right],
};
}

if (node.type === "TernaryOperation") {
const [a, b, c] = node.items;
return {
...node,
items: [insertTransformNode(a, transforms), b, c],
};
}

return {
type: "UnaryOperation",
name: "command",
transforms,
items: [node],
};
}

/**
* @param {import("../parse.js").State} State
* @returns {{ node: UnaryOperation | Term; end: number }}
* @returns {{ node: Operation | Term; end: number }}
*/
export default function command({ start, tokens }) {
const token = tokens[start];
Expand Down Expand Up @@ -58,41 +100,35 @@ export default function command({ start, tokens }) {

const next = expr({ stack: [], start: pos, tokens });

if (next.node.type === "Term") {
// Only apply command to the first item in the term
const [first, ...rest] = next.node.items;

/** @type {Node[]} */
const items = first
? [
{
type: "UnaryOperation",
name: "command",
transforms: textTransforms,
items: [first],
},
...rest,
]
: [];
if (textTransforms.length === 0) {
// Only apply styles.
return {
node: {
type: "UnaryOperation",
name: "command",
styles,
items: [next.node],
},
end: next.end,
};
}

const node = insertTransformNode(next.node, textTransforms);

if (styles.size > 0) {
return {
node: {
type: "Term",
type: "UnaryOperation",
name: "command",
styles,
items,
items: [node],
},
end: next.end,
};
}

return {
node: {
type: "UnaryOperation",
name: "command",
transforms: textTransforms,
styles,
items: [next.node],
},
node,
end: next.end,
};
}
51 changes: 45 additions & 6 deletions src/compiler/parser/handlers/command.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ test("no opperant", (t) => {
const { end, node } = command({ start: 0, tokens });

t.true(end >= tokens.length);
t.is(node.type, "Term");
t.deepEqual(node.items, []);
t.is(node.type, "UnaryOperation");
t.is(node.name, "command");
t.deepEqual(node.items, [{ type: "Term", items: [] }]);
});

test("unknown command", (t) => {
Expand All @@ -19,12 +20,11 @@ test("unknown command", (t) => {
const { end, node } = command({ start: 0, tokens });

t.is(end, tokens.length);
t.is(node.type, "Term");
t.is(node.type, "UnaryOperation");
t.is(node.name, "command");
t.deepEqual(node.items, [
{
type: "UnaryOperation",
name: "command",
transforms: [],
type: "Term",
items: [
{
type: "IdentLiteral",
Expand Down Expand Up @@ -178,6 +178,45 @@ test("multiple text-transform with following term", (t) => {
]);
});

test("text and style command with following term", (t) => {
const tokens = [
{ type: "command", name: "color", value: "red" },
{ type: "command", name: "text-transform", value: "bf" },
{ type: "ident", value: "A" },
{ type: "ident", value: "b" },
];

const { end, node } = command({ start: 0, tokens });

t.is(end, tokens.length);
t.is(node.type, "UnaryOperation");
t.deepEqual(node.styles, new Map([["color", "red"]]));
t.deepEqual(node.items, [
{
type: "Term",
items: [
{
type: "UnaryOperation",
name: "command",
transforms: ["bf"],
items: [
{
type: "IdentLiteral",
value: "A",
attrs: undefined,
},
],
},
{
type: "IdentLiteral",
value: "b",
attrs: undefined,
},
],
},
]);
});

test("text-transform on a group", (t) => {
const tokens = [
{ type: "command", name: "text-transform", value: "bf" },
Expand Down
12 changes: 12 additions & 0 deletions test/fonts.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,15 @@ test("Mathvariants for fenced groups", (t) => {
test("Mathvariants for matrices", (t) => {
t.snapshot(render("bf [a; b]"));
});

test("Mathvariants for subscripts", (t) => {
t.snapshot(render("bf a_i"));
});

test("Mathvariants for superscripts", (t) => {
t.snapshot(render("bf a^2"));
});

test("Mathvariants for sub-superscripts", (t) => {
t.snapshot(render("bf a_i^2"));
});
18 changes: 18 additions & 0 deletions test/snapshots/fonts.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,21 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1
'<math><mrow><mo fence="true">[</mo><mtable><mtr><mtd><mi>𝐚</mi></mtd></mtr><mtr><mtd><mi>𝐛</mi></mtd></mtr></mtable><mo fence="true">]</mo></mrow></math>'

## Mathvariants for subscripts

> Snapshot 1
'<math><msub><mi>𝐚</mi><mi>i</mi></msub></math>'

## Mathvariants for superscripts

> Snapshot 1
'<math><msup><mi>𝐚</mi><mn>2</mn></msup></math>'

## Mathvariants for sub-superscripts

> Snapshot 1
'<math><msubsup><mi>𝐚</mi><mi>i</mi><mn>2</mn></msubsup></math>'
Binary file modified test/snapshots/fonts.js.snap
Binary file not shown.

0 comments on commit 8af250a

Please sign in to comment.