Skip to content

Commit 9727206

Browse files
committed
feat(ooxast-unified): add lists
1 parent c2c6711 commit 9727206

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+26451
-41607
lines changed

libs/jast/jast-util-to-texast/src/lib/handlers/graphic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Graphic, List } from 'jast-types'
2-
import { all } from 'jast-util-to-texast'
2+
import { all } from '../all'
33
import { J } from '../types'
44
import { wrapCommandArg } from '../util/wrap-command-arg'
55

libs/jast/jast-util-to-texast/src/lib/handlers/sec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export function sec(j: J, node: Parents) {
4343
type: 'commandArg',
4444
optional: false,
4545
// TODO: [jast-util-to-texast] Figure out how to properly nest environments and commands
46-
// @ts-expect-error
46+
// @ts-expect-error theres something wrong with this nesting
4747
children: all(j, titleElement),
4848
},
4949
],
Lines changed: 194 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,202 @@
11
// based on https://github.com/syntax-tree/hast-util-to-mdast/blob/main/lib/handlers/em
22

3-
import { H, Body, Handle } from '../types'
3+
import { H, Body, Handle, P, UnifiedLatexNode } from '../types'
44
import { all } from '../all'
5+
import { getPStyle } from '../util/get-pstyle'
6+
import { getListInfo } from '../util/get-listinfo'
7+
import { one } from '../one'
8+
import { Element } from 'xast-util-to-string/lib'
9+
import {
10+
Argument,
11+
Environment,
12+
Macro,
13+
Verb,
14+
Whitespace,
15+
} from '@unified-latex/unified-latex-types'
16+
import { WhiteSpace } from 'nlcst'
17+
import { arg, m, SP } from '@unified-latex/unified-latex-builder'
18+
import { PB } from '../util/PB'
19+
import { updateRenderInfo } from '@unified-latex/unified-latex-util-render-info'
20+
21+
const isP = (node: Element): node is P =>
22+
node.type === 'element' && node.name === 'w:p'
523

624
export const body: Handle = (h: H, body: Body) => {
725
const bod = all(h, body)
826

9-
return bod
27+
const processedBody = body.children.reduce((acc, child, index) => {
28+
if (child.type !== 'element') return acc
29+
30+
if (!isP(child)) {
31+
acc.push(...makeOne(h, child, body))
32+
return acc
33+
}
34+
35+
const isListItem = getPStyle(child) === 'ListParagraph'
36+
37+
if (!isListItem) {
38+
acc.push(...makeOne(h, child, body))
39+
return acc
40+
}
41+
42+
const { ilvl, numId } = getListInfo(child) ?? {}
43+
44+
if (ilvl == null || numId == null) {
45+
acc.push(...makeOne(h, child, body))
46+
return acc
47+
}
48+
49+
const prevChild = body.children[index - 1]
50+
51+
const isPrevListItem =
52+
prevChild && isP(prevChild) && getPStyle(prevChild) === 'ListParagraph'
53+
54+
const { ilvl: prevIlvl, numId: prevNumId } =
55+
(isPrevListItem && getListInfo(prevChild)) || {}
56+
57+
const listItem = makeItem(h, child)
58+
59+
// there's no previous list item, we need to create a new environment
60+
if (!isPrevListItem || prevIlvl == null || prevNumId == null) {
61+
const env: Environment = {
62+
type: 'environment',
63+
env: 'enumerate',
64+
content: listItem,
65+
_renderInfo: {
66+
ilvl,
67+
numId,
68+
},
69+
}
70+
71+
acc.push(env)
72+
return acc
73+
}
74+
75+
// there is a previous list item, and it's the same level, so we need to add it to the previous environment
76+
if (isPrevListItem && ilvl === prevIlvl && numId === prevNumId) {
77+
const mainEnv = acc[acc.length - 1] as Environment
78+
79+
if (mainEnv.env !== 'enumerate') {
80+
throw new Error('prevEnv.env !== enumerate')
81+
}
82+
83+
const embeddedEnvs = findEmbeddedEnvs(mainEnv)
84+
const lastEnv = embeddedEnvs[embeddedEnvs.length - 1]
85+
86+
lastEnv.content.push(...listItem)
87+
return acc
88+
}
89+
90+
// there is a previous list item, and it's a lower level, so we need to add a new environment inside the previous environment
91+
if (isPrevListItem && ilvl > prevIlvl) {
92+
const mainEnv = acc[acc.length - 1] as Environment
93+
const embeddedEnvs = findEmbeddedEnvs(mainEnv)
94+
const lastEnv = embeddedEnvs[embeddedEnvs.length - 1]
95+
const env: Environment = {
96+
type: 'environment',
97+
env: 'enumerate',
98+
content: listItem,
99+
_renderInfo: {
100+
ilvl,
101+
numId,
102+
},
103+
}
104+
lastEnv.content.push(env)
105+
return acc
106+
}
107+
108+
// there is a previous list item, and it's a higher level, so we need to close the previous environment and create a new one
109+
if (isPrevListItem && ilvl < prevIlvl) {
110+
const mainEnv = acc[acc.length - 1] as Environment
111+
const embeddedEnvs = findEmbeddedEnvs(mainEnv)
112+
const toBeEmbeddedEnv =
113+
embeddedEnvs[embeddedEnvs.length - (prevIlvl - ilvl) - 1]
114+
115+
const env: Environment = {
116+
type: 'environment',
117+
env: 'enumerate',
118+
content: listItem,
119+
_renderInfo: {
120+
ilvl,
121+
numId,
122+
},
123+
}
124+
125+
if (!toBeEmbeddedEnv) {
126+
acc.push(env)
127+
return acc
128+
}
129+
130+
if (toBeEmbeddedEnv._renderInfo?.ilvl !== ilvl) {
131+
toBeEmbeddedEnv.content.push(env)
132+
return acc
133+
}
134+
135+
const item = makeItem(h, child)
136+
137+
toBeEmbeddedEnv.content.push(...item)
138+
return acc
139+
}
140+
141+
// if we are immediately starting a new, but different list after a previous list, we need to close the previous list and start a new one
142+
if (isPrevListItem && ilvl === prevIlvl && numId !== prevNumId) {
143+
const mainEnv = acc[acc.length - 1] as Environment
144+
const embeddedEnvs = findEmbeddedEnvs(mainEnv)
145+
const lastEnv = embeddedEnvs[embeddedEnvs.length - 1]
146+
const env: Environment = {
147+
type: 'environment',
148+
env: 'enumerate',
149+
content: listItem,
150+
_renderInfo: {
151+
ilvl,
152+
numId,
153+
},
154+
}
155+
lastEnv.content.push(env)
156+
return acc
157+
}
158+
159+
return acc
160+
}, [] as UnifiedLatexNode[])
161+
return processedBody
162+
}
163+
164+
function makeItem(
165+
h: H,
166+
item: P
167+
): [typeof PB, Macro, typeof SP, ...UnifiedLatexNode[], typeof PB] {
168+
const mIte = m('item')
169+
updateRenderInfo(mIte, {
170+
hangingIndent: true,
171+
inParMode: true,
172+
})
173+
174+
return [PB, mIte, SP, ...all(h, item), PB]
175+
}
176+
177+
function findEmbeddedEnvs(envs: Environment[] | Environment): Environment[] {
178+
envs = Array.isArray(envs) ? envs : [envs]
179+
180+
if (envs.length === 0) return []
181+
const env = envs[envs.length - 1]
182+
if (env.content.length === 0) return envs
183+
184+
const last = env.content[env.content.length - 1]
185+
186+
if (last.type !== 'environment') return envs
187+
188+
return findEmbeddedEnvs([...envs, last])
189+
}
190+
191+
function makeOne(h: H, node: Element, body: Body): UnifiedLatexNode[] {
192+
const res = one(h, node, body)
193+
if (!res) {
194+
return []
195+
}
196+
197+
if (Array.isArray(res)) {
198+
return res
199+
}
200+
201+
return [res]
10202
}

libs/ooxast/ooxast-util-to-unified-latex/src/lib/handlers/p.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { x } from 'xastscript'
22
import { toUnifiedLatex } from '../ooxast-util-to-unified-latex'
3+
import { s, SP } from '@unified-latex/unified-latex-builder'
4+
35
describe('p', () => {
46
it('should do something', () => {
57
const basicp = x('p', { id: 'ayy' }, [
@@ -9,6 +11,6 @@ describe('p', () => {
911
x('w:t', {}, [{ type: 'text', value: 'lmao' }]),
1012
]),
1113
])
12-
expect(toUnifiedLatex(basicp)).toEqual(x('p', [{ type: 'text', value: 'lmao' }]))
14+
expect(toUnifiedLatex(basicp)).toEqual([SP])
1315
})
1416
})

libs/ooxast/ooxast-util-to-unified-latex/src/lib/handlers/root.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,9 @@ import { H, Node, Root } from '../types'
55

66
export function root(h: H, node: Root) {
77
// if (!article) {
8-
const children: any[] = [
9-
{
10-
type: 'instruction',
11-
name: 'xml',
12-
value: 'version="1.0" encoding="utf-8"',
13-
},
14-
{
15-
type: 'doctype',
16-
name: 'article',
17-
public:
18-
'-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.2 20190208//EN',
19-
system:
20-
'https://jats.nlm.nih.gov/publishing/1.2/JATS-journalpublishing1.dtd',
21-
},
22-
]
238

24-
const content = all(j, node)
25-
content.unshift(...children)
26-
return j(node, 'root', content)
9+
const content = all(h, node)
10+
return h(node, 'root', content)
2711
// }
2812

2913
// return j(article, 'root', [

libs/ooxast/ooxast-util-to-unified-latex/src/lib/ooxast-util-to-unified-latex.spec.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { P } from 'ooxast'
1+
import { Document, P, Root } from 'ooxast'
22
import { Macro } from '@unified-latex/unified-latex-types'
33
import { p } from './handlers/p'
44
import { toUnifiedLatex } from './ooxast-util-to-unified-latex'
55
import { toString } from '@unified-latex/unified-latex-util-to-string'
66
import { m } from '@unified-latex/unified-latex-builder'
77
import { updateRenderInfo } from '@unified-latex/unified-latex-util-render-info'
88
import { PB } from './util/PB'
9+
import listTree from '../lib/test/list.json'
910

1011
// test whether a ooxast p node with style 'Heading1' is converted to a macro with name 'section'
1112
describe('ooxast-util-to-unified-latex', () => {
@@ -71,4 +72,37 @@ describe('ooxast-util-to-unified-latex', () => {
7172
)
7273
expect(toUnifiedLatex(ooxastParagraph)).toEqual(res)
7374
})
75+
76+
it('should convert a file with lists to nested enum envs', () => {
77+
const res = toUnifiedLatex(listTree as Root)
78+
console.dir(res, { depth: null })
79+
expect(toString(res)).toEqual(`\\begin{enumerate}··
80+
\\item Number one···
81+
\\item Two···
82+
\\item Three·
83+
\\begin{enumerate}··
84+
\\item Indent··
85+
\\end{enumerate}
86+
\\end{enumerate}···
87+
\\begin{enumerate}··
88+
\\item Unordered···
89+
\\item List···
90+
\\item Items·
91+
\\begin{enumerate}··
92+
\\item Indentatio··
93+
\\end{enumerate}
94+
\\end{enumerate}···
95+
\\begin{enumerate}··
96+
\\item Continuing···
97+
\\item Previous···
98+
\\item List·
99+
\\begin{enumerate}··
100+
\\item Indentation··
101+
\\end{enumerate}·
102+
\\item Going down a step again·
103+
\\begin{enumerate}··
104+
\\item Immediately starting other list··
105+
\\end{enumerate}
106+
\\end{enumerate}`)
107+
})
74108
})

0 commit comments

Comments
 (0)