From 169177c2bdf18cc996e5f6ca941f10ca42896b92 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 19 Sep 2023 08:31:59 +0200 Subject: [PATCH 01/13] Add support for the basic proof envs. However cross references to theorems are not working --- packages/jtex/src/jtex.ts | 5 +- packages/myst-cli/src/build/tex/single.ts | 1 + packages/myst-common/src/index.ts | 1 + packages/myst-common/src/utils.ts | 9 ++ packages/myst-ext-proof/package.json | 1 + packages/myst-ext-proof/src/index.ts | 2 +- packages/myst-ext-proof/src/types.ts | 43 +++++---- packages/myst-to-tex/package.json | 1 + packages/myst-to-tex/src/index.ts | 9 ++ packages/myst-to-tex/src/proof.ts | 101 ++++++++++++++++++++++ packages/myst-to-tex/src/types.ts | 2 + 11 files changed, 156 insertions(+), 19 deletions(-) create mode 100644 packages/myst-to-tex/src/proof.ts diff --git a/packages/jtex/src/jtex.ts b/packages/jtex/src/jtex.ts index af0b4552c..ad111d35d 100644 --- a/packages/jtex/src/jtex.ts +++ b/packages/jtex/src/jtex.ts @@ -40,6 +40,7 @@ export function renderTex( bibliography?: string[]; sourceFile?: string; imports?: string | TemplateImports; + preamble?: string; force?: boolean; packages?: string[]; filesPath?: string; @@ -56,12 +57,14 @@ export function renderTex( content = opts.contentOrPath; } const { options, parts, doc } = template.prepare(opts); + let importsContent = renderImports(opts.imports, opts.packages); + importsContent += '\n' + (opts.preamble || ''); const renderer: TexRenderer = { CONTENT: content, doc, parts, options, - IMPORTS: renderImports(opts.imports, opts?.packages), + IMPORTS: importsContent, }; const env = getDefaultEnv(template); const rendered = env.render(TEMPLATE_FILENAME, renderer); diff --git a/packages/myst-cli/src/build/tex/single.ts b/packages/myst-cli/src/build/tex/single.ts index 98149b7a5..1feded538 100644 --- a/packages/myst-cli/src/build/tex/single.ts +++ b/packages/myst-cli/src/build/tex/single.ts @@ -175,6 +175,7 @@ export async function localArticleToTexTemplated( bibliography: [DEFAULT_BIB_FILENAME], sourceFile: file, imports: mergeTemplateImports(collectedImports, result), + preamble: result.preamble.join('\n\n'), force, packages: templateYml.packages, filesPath, diff --git a/packages/myst-common/src/index.ts b/packages/myst-common/src/index.ts index 1c633c1ff..9576b25f1 100644 --- a/packages/myst-common/src/index.ts +++ b/packages/myst-common/src/index.ts @@ -11,6 +11,7 @@ export { setTextAsChild, copyNode, mergeTextNodes, + writeTexLabelledComment, } from './utils.js'; export { selectBlockParts, extractPart } from './extractParts.js'; export { TemplateKind, TemplateOptionType } from './templates.js'; diff --git a/packages/myst-common/src/utils.ts b/packages/myst-common/src/utils.ts index ba0917eb4..4eca58850 100644 --- a/packages/myst-common/src/utils.ts +++ b/packages/myst-common/src/utils.ts @@ -146,3 +146,12 @@ export function admonitionKindToTitle(kind: AdmonitionKind | string) { }; return transform[kind] || `Unknown Admonition "${kind}"`; } + +export function writeTexLabelledComment(title: string, commands: string[], commentLenth: number) { + if (!commands || commands?.length === 0) return ''; + const len = (commentLenth - title.length - 4) / 2; + const start = ''.padEnd(Math.ceil(len), '%'); + const end = ''.padEnd(Math.floor(len), '%'); + const titleBlock = `${start} ${title} ${end}\n`; + return `${titleBlock}${commands.join('\n')}\n`; +} diff --git a/packages/myst-ext-proof/package.json b/packages/myst-ext-proof/package.json index eb79af26d..3b9850b30 100644 --- a/packages/myst-ext-proof/package.json +++ b/packages/myst-ext-proof/package.json @@ -32,6 +32,7 @@ "url": "https://github.com/executablebooks/mystmd/issues" }, "dependencies": { + "myst-spec": "^0.0.4", "myst-common": "^1.1.5" }, "devDependencies": { diff --git a/packages/myst-ext-proof/src/index.ts b/packages/myst-ext-proof/src/index.ts index 14b7cd30f..59d6723fa 100644 --- a/packages/myst-ext-proof/src/index.ts +++ b/packages/myst-ext-proof/src/index.ts @@ -1,2 +1,2 @@ export { proofDirective } from './proof.js'; -export { ProofKind } from './types.js'; +export type { ProofKind, ProofContainer } from './types.js'; diff --git a/packages/myst-ext-proof/src/types.ts b/packages/myst-ext-proof/src/types.ts index d16fffdf7..3feb493c5 100644 --- a/packages/myst-ext-proof/src/types.ts +++ b/packages/myst-ext-proof/src/types.ts @@ -1,17 +1,26 @@ -export enum ProofKind { - proof = 'proof', - axiom = 'axiom', - lemma = 'lemma', - definition = 'definition', - criterion = 'criterion', - remark = 'remark', - conjecture = 'conjecture', - corollary = 'corollary', - algorithm = 'algorithm', - example = 'example', - property = 'property', - observation = 'observation', - proposition = 'proposition', - assumption = 'assumption', - theorem = 'theorem', -} +import type { Container } from 'myst-spec'; + +const PROOF_KINDS = [ + 'proof', + 'axiom', + 'lemma', + 'definition', + 'criterion', + 'remark', + 'conjecture', + 'corollary', + 'algorithm', + 'example', + 'property', + 'observation', + 'proposition', + 'assumption', + 'theorem' +] as const; +type ProofKinds = typeof PROOF_KINDS; + +export type ProofKind = ProofKinds[number]; + +export type ProofContainer = Omit & { + kind: ProofKind; +}; diff --git a/packages/myst-to-tex/package.json b/packages/myst-to-tex/package.json index 4b541c8ae..c8c96bcba 100644 --- a/packages/myst-to-tex/package.json +++ b/packages/myst-to-tex/package.json @@ -40,6 +40,7 @@ "myst-common": "^1.1.5", "myst-frontmatter": "^1.1.5", "myst-spec-ext": "^1.1.5", + "myst-ext-proof": "^1.0.3", "unist-util-select": "^4.0.3", "vfile-reporter": "^7.0.4" }, diff --git a/packages/myst-to-tex/src/index.ts b/packages/myst-to-tex/src/index.ts index 4f40c9e65..a7c32f56e 100644 --- a/packages/myst-to-tex/src/index.ts +++ b/packages/myst-to-tex/src/index.ts @@ -17,6 +17,7 @@ import MATH_HANDLERS, { withRecursiveCommands } from './math.js'; import { selectAll } from 'unist-util-select'; import type { FootnoteDefinition } from 'myst-spec-ext'; import { transformLegends } from './legends.js'; +import { TexProofSerializer, proofHandler } from './proof.js'; export type { LatexResult } from './types.js'; @@ -230,6 +231,7 @@ const handlers: Record = { state.closeBlock(node); }, container: containerHandler, + proof: proofHandler, caption: captionHandler, captionNumber: () => undefined, crossReference(node, state) { @@ -308,6 +310,7 @@ class TexSerializer implements ITexSerializer { handlers: Record; references: References; footnotes: Record; + hasProofs: boolean; constructor(file: VFile, tree: Root, opts?: Options) { file.result = ''; @@ -322,6 +325,7 @@ class TexSerializer implements ITexSerializer { return [fn.identifier, fn]; }), ); + this.hasProofs = false; this.renderChildren(tree); } @@ -404,8 +408,13 @@ const plugin: Plugin<[Options?], Root, VFile> = function (opts) { transformLegends(node); const state = new TexSerializer(file, node, opts ?? { handlers }); const tex = (file.result as string).trim(); + const preamble: string[] = []; + if (state.hasProofs) { + preamble.push(new TexProofSerializer().preamble); + } const result: LatexResult = { imports: [...state.data.imports], + preamble, commands: withRecursiveCommands(state), value: tex, }; diff --git a/packages/myst-to-tex/src/proof.ts b/packages/myst-to-tex/src/proof.ts new file mode 100644 index 000000000..4b313f32e --- /dev/null +++ b/packages/myst-to-tex/src/proof.ts @@ -0,0 +1,101 @@ +import { fileError, writeTexLabelledComment } from 'myst-common'; +import type { Text } from 'myst-spec'; +import type { ProofContainer, ProofKind } from 'myst-ext-proof'; +import { select } from 'unist-util-select'; +import { remove } from 'unist-util-remove'; +import type { Handler } from './types.js'; + +function kindToEnvironment(kind: ProofKind): string { + switch (kind) { + case 'theorem': + return 'theorem'; + case 'proof': + return 'proof'; + case 'proposition': + return 'proposition'; + case 'definition': + return 'definition'; + case 'example': + return 'example'; + case 'remark': + return 'remark'; + case 'axiom': + return 'axiom'; + case 'conjecture': + return 'conjecture'; + case 'lemma': + return 'lemma'; + case 'observation': + return 'observation'; + default: + return ''; + } +} + +export const proofHandler: Handler = (node, state) => { + state.usePackages('amsthm'); + + const p = node as ProofContainer; + const env = kindToEnvironment(p.kind); + if (!env) { + fileError(state.file, `Unhandled LaTeX proof environment "${p.kind}"`, { + node, + source: 'myst-to-tex', + }); + return; + } + + const t = select('admonitionTitle > text', node); + if (t) { + // Do not render the title twice + t.type = '__delete__'; + } + const newNode = remove(node, '__delete__'); + + state.write('\\begin{'); + state.write(env); + state.write('}'); + if (t) { + state.write('['); + state.write((t as Text).value); + state.write(']'); + } + state.renderChildren(newNode, true); + state.write('\\end{'); + state.write(env); + state.write('}'); + + state.hasProofs = true; +}; + +export class TexProofSerializer { + static COMMENT_LENGTH = 50; + + preamble: string; + + constructor() { + this.preamble = this.renderThmDefinitions(); + } + + private renderThmDefinitions(): string { + const definitions = [ + '\\newtheorem{theorem}{Theorem}[section]', + '\\newtheorem{corollary}{Corollary}[theorem]', + '\\newtheorem{lemma}[theorem]{Lemma}', + '\\newtheorem{proposition}{Proposition}[section]', + '\\newtheorem{definition}{Definition}[section]', + '\\newtheorem{example}{Example}[section]', + '\\newtheorem{remark}{Remark}[section]', + '\\newtheorem{axiom}{Axiom}[section]', + '\\newtheorem{conjecture}{Conjecture}[section]', + '\\newtheorem{observation}{Observation}[section]', + ]; + const block = writeTexLabelledComment( + 'theorem', + definitions, + TexProofSerializer.COMMENT_LENGTH, + ); + const percents = ''.padEnd(TexProofSerializer.COMMENT_LENGTH, '%'); + return `${percents}\n${block}${percents}`; + } +} diff --git a/packages/myst-to-tex/src/types.ts b/packages/myst-to-tex/src/types.ts index 1e5f9a7e5..9b91297b0 100644 --- a/packages/myst-to-tex/src/types.ts +++ b/packages/myst-to-tex/src/types.ts @@ -11,6 +11,7 @@ export type Handler = (node: any, state: ITexSerializer, parent: any) => void; export type LatexResult = { value: string; imports: string[]; + preamble: string[]; commands: Record; }; @@ -41,6 +42,7 @@ export interface ITexSerializer = StateData> { options: Options; references: References; footnotes: Record; + hasProofs: boolean; usePackages: (...packageNames: string[]) => void; write: (value: string) => void; text: (value: string, mathMode?: boolean) => void; From 427152651983272ca5ef08a04800fc5675b76410 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 19 Sep 2023 08:45:24 +0200 Subject: [PATCH 02/13] Fix references --- packages/myst-to-tex/src/proof.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/myst-to-tex/src/proof.ts b/packages/myst-to-tex/src/proof.ts index 4b313f32e..0fb0e05cc 100644 --- a/packages/myst-to-tex/src/proof.ts +++ b/packages/myst-to-tex/src/proof.ts @@ -1,4 +1,4 @@ -import { fileError, writeTexLabelledComment } from 'myst-common'; +import { GenericNode, fileError, writeTexLabelledComment } from 'myst-common'; import type { Text } from 'myst-spec'; import type { ProofContainer, ProofKind } from 'myst-ext-proof'; import { select } from 'unist-util-select'; @@ -50,7 +50,7 @@ export const proofHandler: Handler = (node, state) => { // Do not render the title twice t.type = '__delete__'; } - const newNode = remove(node, '__delete__'); + const newNode = remove(node, '__delete__') as GenericNode; state.write('\\begin{'); state.write(env); @@ -60,6 +60,11 @@ export const proofHandler: Handler = (node, state) => { state.write((t as Text).value); state.write(']'); } + if (newNode.identifier && newNode.identifier.length > 0) { + state.write('\\label{'); + state.write(newNode.identifier); + state.write('}'); + } state.renderChildren(newNode, true); state.write('\\end{'); state.write(env); From fe5f3a9f0f45885028f882ec8150d078be351eea Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 27 Sep 2023 23:49:11 +0200 Subject: [PATCH 03/13] Fix linting issues --- packages/myst-ext-proof/src/types.ts | 2 +- packages/myst-to-tex/src/index.ts | 2 +- packages/myst-to-tex/src/proof.ts | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/myst-ext-proof/src/types.ts b/packages/myst-ext-proof/src/types.ts index 3feb493c5..e1f41af0b 100644 --- a/packages/myst-ext-proof/src/types.ts +++ b/packages/myst-ext-proof/src/types.ts @@ -15,7 +15,7 @@ const PROOF_KINDS = [ 'observation', 'proposition', 'assumption', - 'theorem' + 'theorem', ] as const; type ProofKinds = typeof PROOF_KINDS; diff --git a/packages/myst-to-tex/src/index.ts b/packages/myst-to-tex/src/index.ts index a06b2d253..afb363f6e 100644 --- a/packages/myst-to-tex/src/index.ts +++ b/packages/myst-to-tex/src/index.ts @@ -609,7 +609,7 @@ const plugin: Plugin<[Options?], Root, VFile> = function (opts) { preamble.push(new TexProofSerializer().preamble); } preamble.push(opts?.printGlossaries ? glossaryState.preamble : ''); - + let tex = (file.result as string).trim(); tex += opts?.printGlossaries ? '\n' + glossaryState.printedDefinitions : ''; diff --git a/packages/myst-to-tex/src/proof.ts b/packages/myst-to-tex/src/proof.ts index 0fb0e05cc..2e2999bfa 100644 --- a/packages/myst-to-tex/src/proof.ts +++ b/packages/myst-to-tex/src/proof.ts @@ -1,4 +1,5 @@ -import { GenericNode, fileError, writeTexLabelledComment } from 'myst-common'; +import { fileError, writeTexLabelledComment } from 'myst-common'; +import type { GenericNode } from 'myst-common'; import type { Text } from 'myst-spec'; import type { ProofContainer, ProofKind } from 'myst-ext-proof'; import { select } from 'unist-util-select'; From 1dce2914b8e32925cdee2d1ec296a3c96b16948a Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 28 Sep 2023 07:56:10 +0200 Subject: [PATCH 04/13] Address one linting issue --- packages/myst-transforms/src/abbreviations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/myst-transforms/src/abbreviations.ts b/packages/myst-transforms/src/abbreviations.ts index 564eef3e0..0cdf4851d 100644 --- a/packages/myst-transforms/src/abbreviations.ts +++ b/packages/myst-transforms/src/abbreviations.ts @@ -2,7 +2,7 @@ import type { Plugin } from 'unified'; import type { GenericParent } from 'myst-common'; import { toText } from 'myst-common'; import { selectAll } from 'unist-util-select'; -import type { Abbreviation, StaticPhrasingContent, Text } from 'myst-spec'; +import type { Abbreviation, Text } from 'myst-spec'; import { u } from 'unist-builder'; import type { FindAndReplaceSchema, RegExpMatchObject } from 'mdast-util-find-and-replace'; import { findAndReplace } from 'mdast-util-find-and-replace'; From 5cb21a58c7ab31a13e5dea4b0542f8083db70648 Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 29 Sep 2023 23:35:10 +0200 Subject: [PATCH 05/13] Move hasProofs to StateData --- packages/myst-to-tex/src/index.ts | 6 ++---- packages/myst-to-tex/src/proof.ts | 2 +- packages/myst-to-tex/src/types.ts | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/myst-to-tex/src/index.ts b/packages/myst-to-tex/src/index.ts index afb363f6e..089263aba 100644 --- a/packages/myst-to-tex/src/index.ts +++ b/packages/myst-to-tex/src/index.ts @@ -498,7 +498,6 @@ class TexSerializer implements ITexSerializer { handlers: Record; references: References; footnotes: Record; - hasProofs: boolean; glossary: Record; abbreviations: Record; @@ -506,11 +505,10 @@ class TexSerializer implements ITexSerializer { file.result = ''; this.file = file; this.options = opts ?? {}; - this.data = { mathPlugins: {}, imports: new Set() }; + this.data = { mathPlugins: {}, imports: new Set(), hasProofs: false }; this.handlers = opts?.handlers ?? handlers; this.references = opts?.references ?? {}; this.footnotes = createFootnoteDefinitions(tree); - this.hasProofs = false; // Improve: render definition when encountering terms this.glossary = opts?.printGlossaries ? createGlossaryDefinitions(tree) : {}; // Improve: render definition when encountering terms @@ -605,7 +603,7 @@ const plugin: Plugin<[Options?], Root, VFile> = function (opts) { const glossaryState = new TexGlossaryAndAcronymSerializer(state.glossary, state.abbreviations); const preamble: string[] = []; - if (state.hasProofs) { + if (state.data.hasProofs) { preamble.push(new TexProofSerializer().preamble); } preamble.push(opts?.printGlossaries ? glossaryState.preamble : ''); diff --git a/packages/myst-to-tex/src/proof.ts b/packages/myst-to-tex/src/proof.ts index 2e2999bfa..da8c0cd26 100644 --- a/packages/myst-to-tex/src/proof.ts +++ b/packages/myst-to-tex/src/proof.ts @@ -71,7 +71,7 @@ export const proofHandler: Handler = (node, state) => { state.write(env); state.write('}'); - state.hasProofs = true; + state.data.hasProofs = true; }; export class TexProofSerializer { diff --git a/packages/myst-to-tex/src/types.ts b/packages/myst-to-tex/src/types.ts index adec3a6a2..9a57c0641 100644 --- a/packages/myst-to-tex/src/types.ts +++ b/packages/myst-to-tex/src/types.ts @@ -35,6 +35,7 @@ export type StateData = { nextCaptionId?: string; mathPlugins: Required['math']; imports: Set; + hasProofs: boolean; }; export interface ITexSerializer = StateData> { @@ -43,7 +44,6 @@ export interface ITexSerializer = StateData> { options: Options; references: References; footnotes: Record; - hasProofs: boolean; glossary: Record; abbreviations: Record; get printGlossary(): boolean; From 3ddd729f3dda8a23f0e75facecb05e16c63f750e Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 29 Sep 2023 23:39:20 +0200 Subject: [PATCH 06/13] More feedback on hasProofs --- packages/myst-to-tex/src/index.ts | 2 +- packages/myst-to-tex/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/myst-to-tex/src/index.ts b/packages/myst-to-tex/src/index.ts index 089263aba..6811fb76a 100644 --- a/packages/myst-to-tex/src/index.ts +++ b/packages/myst-to-tex/src/index.ts @@ -505,7 +505,7 @@ class TexSerializer implements ITexSerializer { file.result = ''; this.file = file; this.options = opts ?? {}; - this.data = { mathPlugins: {}, imports: new Set(), hasProofs: false }; + this.data = { mathPlugins: {}, imports: new Set() }; this.handlers = opts?.handlers ?? handlers; this.references = opts?.references ?? {}; this.footnotes = createFootnoteDefinitions(tree); diff --git a/packages/myst-to-tex/src/types.ts b/packages/myst-to-tex/src/types.ts index 9a57c0641..5969e37e5 100644 --- a/packages/myst-to-tex/src/types.ts +++ b/packages/myst-to-tex/src/types.ts @@ -33,9 +33,9 @@ export type StateData = { nextCaptionNumbered?: boolean; nextHeadingIsFrameTitle?: boolean; nextCaptionId?: string; + hasProofs?: boolean; mathPlugins: Required['math']; imports: Set; - hasProofs: boolean; }; export interface ITexSerializer = StateData> { From bac1b27fb72f8ac718933309ad07b24f9f95e4cd Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 4 Oct 2023 08:25:25 +0200 Subject: [PATCH 07/13] Update package-lock --- package-lock.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 0725c9ca2..b6ecfaab5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13733,7 +13733,8 @@ "version": "1.0.4", "license": "MIT", "dependencies": { - "myst-common": "^1.1.7" + "myst-common": "^1.1.7", + "myst-spec": "^0.0.4" }, "devDependencies": { "myst-parser": "^1.0.8" @@ -14018,6 +14019,7 @@ "license": "MIT", "dependencies": { "myst-common": "^1.1.8", + "myst-ext-proof": "^1.0.3", "myst-frontmatter": "^1.1.8", "myst-spec-ext": "^1.1.8", "unist-util-select": "^4.0.3", From a8c6f9058b0f1e372d0c7121f5386f48aa6a989b Mon Sep 17 00:00:00 2001 From: Rowan Cockett Date: Wed, 4 Oct 2023 08:44:21 -0600 Subject: [PATCH 08/13] Add myst-to-tex to dev deps of jats-to-myst --- packages/jats-to-myst/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/jats-to-myst/package.json b/packages/jats-to-myst/package.json index 100ef621c..e9fcee355 100644 --- a/packages/jats-to-myst/package.json +++ b/packages/jats-to-myst/package.json @@ -45,5 +45,8 @@ "myst-transforms": "^1.1.2", "unist-util-select": "^4.0.3", "vfile-reporter": "^7.0.4" + }, + "devDependencies": { + "myst-to-tex": "^1.0.7" } } From 98c6010d78216c0b01739bad4b556b681ba5bf4d Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 12 Oct 2023 11:10:56 +0200 Subject: [PATCH 09/13] Add tests --- packages/myst-to-tex/tests/proofs.yml | 209 ++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 packages/myst-to-tex/tests/proofs.yml diff --git a/packages/myst-to-tex/tests/proofs.yml b/packages/myst-to-tex/tests/proofs.yml new file mode 100644 index 000000000..4ad1fa8b6 --- /dev/null +++ b/packages/myst-to-tex/tests/proofs.yml @@ -0,0 +1,209 @@ +title: myst-to-tex basic features +cases: + - title: theorem after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before a theorem' + - type: proof + kind: theorem + label: theo-t1 + identifier: theo-t1 + enumerated: true + children: + - type: text + value: 'Given this, then that.' + latex: |- + Some text before a theorem + + \begin{theorem}\label{theo-t1}Given this, then that.\end{theorem} + - title: theorem ad proof after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before a theorem' + - type: proof + kind: theorem + label: theo-t1 + identifier: theo-t1 + enumerated: true + children: + - type: text + value: 'Given this, then that.' + - type: proof + kind: proof + label: proof-t1 + identifier: proof-t1 + children: + - type: text + value: 'qed.' + latex: |- + Some text before a theorem + + \begin{theorem}\label{theo-t1}Given this, then that.\end{theorem}\begin{proof}\label{proof-t1}qed.\end{proof} + - title: proposition after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before a proposition' + - type: proof + kind: proposition + label: prop-t1 + identifier: prop-t1 + enumerated: true + children: + - type: text + value: 'Given this, then that.' + latex: |- + Some text before a proposition + + \begin{proposition}\label{prop-t1}Given this, then that.\end{proposition} + - title: definition after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before a definition' + - type: proof + kind: definition + label: def-t1 + identifier: def-t1 + enumerated: true + children: + - type: text + value: 'Given this, then that.' + latex: |- + Some text before a definition + + \begin{definition}\label{def-t1}Given this, then that.\end{definition} + - title: example after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before an example' + - type: proof + kind: example + label: ex-t1 + identifier: ex-t1 + enumerated: true + children: + - type: text + value: 'This is it.' + latex: |- + Some text before an example + + \begin{example}\label{ex-t1}This is it.\end{example} + - title: remark after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before a remark' + - type: proof + kind: remark + label: rem-t1 + identifier: rem-t1 + enumerated: true + children: + - type: text + value: 'This is it.' + latex: |- + Some text before a remark + + \begin{remark}\label{rem-t1}This is it.\end{remark} + - title: axiom after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before an axiom' + - type: proof + kind: axiom + label: ax-t1 + identifier: ax-t1 + enumerated: true + children: + - type: text + value: 'This is it.' + latex: |- + Some text before an axiom + + \begin{axiom}\label{ax-t1}This is it.\end{axiom} + - title: conjecture after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before a conjecture' + - type: proof + kind: conjecture + label: conj-t1 + identifier: conj-t1 + enumerated: true + children: + - type: text + value: 'This is it.' + latex: |- + Some text before a conjecture + + \begin{conjecture}\label{conj-t1}This is it.\end{conjecture} + - title: lemma after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before a lemma' + - type: proof + kind: lemma + label: lem-t1 + identifier: lem-t1 + enumerated: true + children: + - type: text + value: 'When this, then that.' + latex: |- + Some text before a lemma + + \begin{lemma}\label{lem-t1}When this, then that.\end{lemma} + - title: observation after paragraph + mdast: + type: root + children: + - type: paragraph + children: + - type: text + value: 'Some text before an observation' + - type: proof + kind: observation + label: obs-t1 + identifier: obs-t1 + enumerated: true + children: + - type: text + value: 'This is it.' + latex: |- + Some text before an observation + + \begin{observation}\label{obs-t1}This is it.\end{observation} From 34bfe9a19dc4730f3c36cfbb2b036867aa6dbf08 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 12 Oct 2023 11:17:10 +0200 Subject: [PATCH 10/13] Add changeset --- .changeset/quiet-taxis-grab.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/quiet-taxis-grab.md diff --git a/.changeset/quiet-taxis-grab.md b/.changeset/quiet-taxis-grab.md new file mode 100644 index 000000000..cd9ae9603 --- /dev/null +++ b/.changeset/quiet-taxis-grab.md @@ -0,0 +1,8 @@ +--- +'myst-transforms': patch +'myst-ext-proof': patch +'jats-to-myst': patch +'myst-to-tex': patch +--- + +Add support for proofs in LaTeX From 3ebcc5e3a1028e7e84cb04b2a1ab17daba30f116 Mon Sep 17 00:00:00 2001 From: Franklin Koch Date: Fri, 13 Oct 2023 10:40:28 -0600 Subject: [PATCH 11/13] =?UTF-8?q?=F0=9F=93=8F=20Add=20ruleid=20to=20tex=20?= =?UTF-8?q?proof=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/myst-to-tex/src/proof.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/myst-to-tex/src/proof.ts b/packages/myst-to-tex/src/proof.ts index da8c0cd26..640d0606e 100644 --- a/packages/myst-to-tex/src/proof.ts +++ b/packages/myst-to-tex/src/proof.ts @@ -1,5 +1,5 @@ import { fileError, writeTexLabelledComment } from 'myst-common'; -import type { GenericNode } from 'myst-common'; +import type { GenericNode, RuleId } from 'myst-common'; import type { Text } from 'myst-spec'; import type { ProofContainer, ProofKind } from 'myst-ext-proof'; import { select } from 'unist-util-select'; @@ -42,6 +42,7 @@ export const proofHandler: Handler = (node, state) => { fileError(state.file, `Unhandled LaTeX proof environment "${p.kind}"`, { node, source: 'myst-to-tex', + ruleId: RuleId.texRenders, }); return; } From 9f796513fbfb5c7903f8e6bc22c08abcfb207f85 Mon Sep 17 00:00:00 2001 From: Franklin Koch Date: Fri, 13 Oct 2023 10:45:28 -0600 Subject: [PATCH 12/13] =?UTF-8?q?=F0=9F=93=8F=20Import=20ruleid=20correctl?= =?UTF-8?q?y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/myst-to-tex/src/proof.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/myst-to-tex/src/proof.ts b/packages/myst-to-tex/src/proof.ts index 640d0606e..72c024199 100644 --- a/packages/myst-to-tex/src/proof.ts +++ b/packages/myst-to-tex/src/proof.ts @@ -1,5 +1,5 @@ -import { fileError, writeTexLabelledComment } from 'myst-common'; -import type { GenericNode, RuleId } from 'myst-common'; +import { fileError, writeTexLabelledComment, RuleId } from 'myst-common'; +import type { GenericNode } from 'myst-common'; import type { Text } from 'myst-spec'; import type { ProofContainer, ProofKind } from 'myst-ext-proof'; import { select } from 'unist-util-select'; From 2d6fe0996906ee8ae79a4c88a8d927fa5e42033f Mon Sep 17 00:00:00 2001 From: Andrea Date: Sat, 14 Oct 2023 10:56:43 +0200 Subject: [PATCH 13/13] Add ruleid --- packages/myst-to-tex/src/proof.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/myst-to-tex/src/proof.ts b/packages/myst-to-tex/src/proof.ts index da8c0cd26..ce63de8a2 100644 --- a/packages/myst-to-tex/src/proof.ts +++ b/packages/myst-to-tex/src/proof.ts @@ -1,4 +1,4 @@ -import { fileError, writeTexLabelledComment } from 'myst-common'; +import { RuleId, fileError, writeTexLabelledComment } from 'myst-common'; import type { GenericNode } from 'myst-common'; import type { Text } from 'myst-spec'; import type { ProofContainer, ProofKind } from 'myst-ext-proof'; @@ -42,6 +42,7 @@ export const proofHandler: Handler = (node, state) => { fileError(state.file, `Unhandled LaTeX proof environment "${p.kind}"`, { node, source: 'myst-to-tex', + ruleId: RuleId.texRenders, }); return; }