Skip to content

Commit

Permalink
👈 Cross reference the subEnumerator directly. (#899)
Browse files Browse the repository at this point in the history
Also adds support in latex for `subref`, `landscape` and improves `subfigure` support for multiple captions defined in latex.
  • Loading branch information
rowanc1 authored Feb 12, 2024
1 parent 08a70ff commit d5416ff
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/real-jeans-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"myst-transforms": patch
---

Allow for {subEnumerator} to be a reference target template.
5 changes: 5 additions & 0 deletions .changeset/rich-frogs-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tex-to-myst": patch
---

Add subref, subfigure, and landscape functions for tex
5 changes: 5 additions & 0 deletions .changeset/tender-crabs-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"myst-spec-ext": patch
---

Allow the figure container to have an extensible kind
2 changes: 2 additions & 0 deletions docs/figures.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ Some pictures of fruit and beaches!
See [](#my-figure-fruit) for the fruit, and [](#my-figure) to reference both subfigures.
```

By default, when referring to subfigures, the `{number}` that is used includes the parent enumerator (that is: `1a` rather than just `a`). To specifically use the sub-enumerator only, you can use the syntax `{subEnumerator}` in your text link which will be replaced with the sub-enumerator (that is: `a` rather than `1a`).

## Supported Image Formats

MyST supports many images formats including `.png`, `.jpg`, `.gif`, `.tiff`, `.svg`, `.pdf`, and `.eps`.
Expand Down
2 changes: 1 addition & 1 deletion packages/myst-spec-ext/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export type Include = {
};

export type Container = Omit<SpecContainer, 'kind'> & {
kind?: 'figure' | 'table' | 'quote' | 'code';
kind?: 'figure' | 'table' | 'quote' | 'code' | string;
source?: Dependency;
subcontainer?: boolean;
noSubcontainers?: boolean;
Expand Down
36 changes: 19 additions & 17 deletions packages/myst-transforms/src/enumerate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,17 @@ function fillReferenceEnumerators(
'label' | 'identifier' | 'children' | 'template' | 'enumerator'
> & { type: string },
template: string,
enumerator?: string | number,
target?: TargetNodes,
title?: string | PhrasingContent[],
) {
const noNodeChildren = !node.children?.length;
if (noNodeChildren) {
setTextAsChild(node, template);
}
const num = enumerator != null ? String(enumerator) : UNKNOWN_REFERENCE_ENUMERATOR;
const num =
target?.enumerator != null
? `${target.parentEnumerator ?? ''}${target.enumerator}`
: UNKNOWN_REFERENCE_ENUMERATOR;
if (!node.template) node.template = template;
if (num && num !== UNKNOWN_REFERENCE_ENUMERATOR) node.enumerator = num;
const used = {
Expand All @@ -148,6 +151,10 @@ function fillReferenceEnumerators(
used.s = true;
return num;
},
'{subEnumerator}': () => {
used.number = true;
return target?.enumerator ?? UNKNOWN_REFERENCE_ENUMERATOR;
},
'{number}': () => {
used.number = true;
return num;
Expand Down Expand Up @@ -456,11 +463,11 @@ export class ReferenceState implements IReferenceStateResolver {
this.vfile,
node,
headingTemplate,
target.node.enumerator,
target.node,
copyNode(target.node as Heading).children as PhrasingContent[],
);
} else if (target.kind === TargetKind.equation) {
fillReferenceEnumerators(this.vfile, node, '(%s)', target.node.enumerator);
fillReferenceEnumerators(this.vfile, node, '(%s)', target.node);
} else {
// By default look into the caption or admonition title if it exists
const caption =
Expand All @@ -480,13 +487,7 @@ export class ReferenceState implements IReferenceStateResolver {
const template = target.node.enumerator
? getDefaultNumberedReferenceLabel(target.kind)
: getDefaultNamedReferenceLabel(target.kind, !!title);
fillReferenceEnumerators(
this.vfile,
node,
template,
`${target.node.parentEnumerator ?? ''}${target.node.enumerator}`,
title,
);
fillReferenceEnumerators(this.vfile, node, template, target.node, title);
}
node.resolved = true;
// The identifier may have changed in the lookup, but unlikely
Expand Down Expand Up @@ -587,8 +588,9 @@ export const enumerateTargetsPlugin: Plugin<[StateOptions], GenericParent, Gener
enumerateTargetsTransform(tree, opts);
};

function getCaptionLabel(kind?: string, subcontainer?: boolean) {
if (subcontainer) return `(%s)`;
function getCaptionLabel(kind?: Container['kind'], subcontainer?: boolean) {
if (subcontainer && (kind === 'equation' || kind === 'subequation')) return `(%s)`;
if (subcontainer) return `({subEnumerator})`;
if (!kind) return 'Figure %s:';
const template = getDefaultNumberedReferenceLabel(kind);
return `${template}:`;
Expand All @@ -610,8 +612,8 @@ export function addContainerCaptionNumbersTransform(
containers
.filter((container: Container) => container.enumerator)
.forEach((container: Container) => {
const enumerator = opts.state.getTarget(container.identifier)?.node.enumerator;
if (!enumerator) return;
const target = opts.state.getTarget(container.identifier)?.node;
if (!target?.enumerator) return;
// Only look for direct caption children
let para = select(
'paragraph',
Expand All @@ -629,13 +631,13 @@ export function addContainerCaptionNumbersTransform(
label: container.label,
identifier: container.identifier,
html_id: (container as any).html_id,
enumerator,
enumerator: target.enumerator,
};
fillReferenceEnumerators(
file,
captionNumber,
getCaptionLabel(container.kind, container.subcontainer),
enumerator,
target,
);
// The caption number is in the paragraph, it needs a link to the figure container
// This is a bit awkward, but necessary for (efficient) rendering
Expand Down
4 changes: 4 additions & 0 deletions packages/tex-to-myst/src/figures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ const FIGURE_HANDLERS: Record<string, Handler> = {
state.closeNode();
},
env_subfigure(node, state) {
state.closeParagraph();
state.openNode('container', { kind: 'figure' });
state.renderChildren(node);
state.closeParagraph();
state.closeNode();
},
env_centering(node, state) {
centering(node, state);
Expand Down
7 changes: 7 additions & 0 deletions packages/tex-to-myst/src/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ export const MISC_HANDLERS: Record<string, Handler> = {
macro_and(node, state) {
state.data.andCallback?.();
},
env_landscape(node, state) {
state.closeParagraph();
state.openBlock({ landscape: true });
state.renderChildren(node);
state.closeParagraph();
state.closeBlock();
},
macro_noindent: pass,
macro_acknowledgments: pass,
macro_def: pass,
Expand Down
5 changes: 5 additions & 0 deletions packages/tex-to-myst/src/refs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export const REF_HANDLERS: Record<string, Handler> = {
const label = texToText(getArguments(node, 'group'));
state.pushNode(u('crossReference', { label }, [u('text', '%s')]));
},
macro_subref(node, state) {
state.openParagraph();
const label = texToText(getArguments(node, 'group'));
state.pushNode(u('crossReference', { label }, [u('text', '{subEnumerator}')]));
},
macro_nameref(node, state) {
state.openParagraph();
const label = texToText(getArguments(node, 'group'));
Expand Down
1 change: 1 addition & 0 deletions packages/tex-to-myst/src/tex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const macros: Record<string, number> = {
primarypubs: 2,
eqref: 1,
nameref: 1,
subref: 1,
textsubscript: 1,
textsuperscript: 1,
adjustwidth: 2,
Expand Down
33 changes: 29 additions & 4 deletions packages/tex-to-myst/tests/figures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,45 @@ cases:
- title: subfigure
tex: |-
\begin{figure}
\begin{subfigure}{0.49\textwidth}
\includegraphics[width=\textwidth]{figures/one.jpg}
\caption{This is Fig 1a}
\end{subfigure}
\begin{subfigure}[b]{0.49\textwidth}
\centering
\includegraphics[width=\textwidth]{figures/one.jpg}
\includegraphics[width=\textwidth]{figures/two.jpg}
\end{subfigure}
\caption{This is the full figure caption.}
\end{figure}
tree:
type: root
children:
- type: container
kind: figure
children:
- type: image
url: figures/one.jpg
align: center
- type: container
kind: figure
children:
- type: image
url: figures/one.jpg
- type: caption
children:
- type: paragraph
children:
- type: text
value: This is Fig 1a
- type: container
kind: figure
align: center
children:
- type: image
url: figures/two.jpg
- type: caption
children:
- type: paragraph
children:
- type: text
value: This is the full figure caption.
- title: minipage
tex: |-
\begin{figure}
Expand Down

0 comments on commit d5416ff

Please sign in to comment.