Skip to content

Commit d082082

Browse files
committed
p, m, b column types in tabular environment
1 parent c77a5ff commit d082082

File tree

2 files changed

+43
-27
lines changed

2 files changed

+43
-27
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ instead of version numbers.
1010
## 2023-12-14
1111

1212
* `\begin{tabular}` improvements:
13+
* `p{width}`, `m{width}`, and `b{width}` columns supported
1314
* `*` repetitions supported: `*3c` is shorthand for `ccc`,
14-
`*{10}{c}` is shorthand for `cccccccccc`,
15-
`*3{lr}` is shorthand for `lrlrlr`.
15+
`*3{lr}` is shorthand for `lrlrlr`,
16+
`*{10}{c}` is shorthand for `cccccccccc`.
1617
* Copy/pasting a URL from a message no longer adds extraneous zero-width spaces
1718
* `\verb|$|` now works both inside and outside math mode
1819

lib/formats.coffee

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,14 @@ splitOutside = (text, re) ->
288288
parts.push text[start..]
289289
parts
290290

291+
colStyle =
292+
c: 'text-align: center;'
293+
l: 'text-align: left;'
294+
r: 'text-align: right;'
295+
p: 'vertical-align: top;'
296+
m: 'vertical-align: middle;'
297+
b: 'vertical-align: bottom;'
298+
291299
## Process all commands starting with \ followed by a letter a-z.
292300
## This is not a valid escape sequence in Markdown, so can be safely supported
293301
## in Markdown too.
@@ -299,17 +307,31 @@ latex2htmlCommandsAlpha = (tex, math) ->
299307
(match, char, verb) => "<code>#{latexEscape verb}</code>"
300308
## Process tabular environments first in order to split cells at &
301309
## (so e.g. \bf is local to the cell)
302-
.replace /\\begin\s*{tabular}\s*{((?:[^{}]|{[^{}]*})*)}([^]*?)\\end\s*{tabular}/g, (m, cols, body) ->
310+
.replace /\\begin\s*{tabular}\s*{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}([^]*?)\\end\s*{tabular}/g, (m, cols, body) ->
303311
cols = cols.replace /\|/g, '' # not yet supported
304312
body = body.replace /\\hline\s*|\\cline\s*{[^{}]*}/g, '' # not yet supported
305-
cols = cols.replace /\*(\d|{\d+})([^{}]|{(?:[^{}]|{[^{}]*})*})/g,
313+
cols = cols.replace /\*\s*(\d|{\s*\d+\s*})\s*([^{}\s]|{(?:[^{}]|{[^{}]*})*})/g,
306314
(match, repeat, body) =>
307315
body = body[1...-1] if body[0] == '{'
308-
repeat = parseInt (repeat.replace /[{}]/g, ''), 10
316+
repeat = repeat[1...-1] if repeat.startsWith '{'
317+
repeat = parseInt repeat, 10
309318
repeat = 0 if repeat < 0
310319
repeat = 1000 if repeat > 1000
311320
body.repeat repeat
312-
skip = (0 for colnum in [0...cols.length])
321+
parseAlign = (pattern) =>
322+
pattern = pattern[1...-1] if pattern.startsWith '{'
323+
align = pattern[0]
324+
width = pattern[1..]
325+
width = width[1...-1] if width.startsWith '{'
326+
style = ''
327+
if align of colStyle
328+
style += colStyle[align]
329+
if width
330+
style += "width: #{width};"
331+
style
332+
colStyles = []
333+
cols.replace /(\w)({[^{}]*})?/g, (match) => colStyles.push parseAlign match
334+
skip = {}
313335
'<table>' +
314336
(for row in splitOutside body, /(?:\\\\|\[DOUBLEBACKSLASH\])/ #(?:\s*\\(?:hline|cline\s*{[^{}]*}))?/
315337
#console.log row
@@ -321,38 +343,31 @@ latex2htmlCommandsAlpha = (tex, math) ->
321343
skip[colnum]--
322344
colnum++
323345
continue
324-
align = cols[colnum]
325346
attrs = ''
326-
style = ''
347+
style = colStyles[colnum]
327348
## "If you want to use both \multirow and \multicolumn on the same
328349
## entry, you must put the \multirow inside the \multicolumn"
329350
## [http://ctan.mirrors.hoobly.com/macros/latex/contrib/multirow/multirow.pdf]
330-
if (match = /\\multicolumn\s*(\d+|{\s*(\d+)\s*})\s*(\w|{([^{}]*)})\s*{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}/.exec col)?
331-
colspan = parseInt match[2] ? match[1], 10
351+
if (match = /\\multicolumn\s*(\d|{\s*\d+\s*})\s*(\w|{[^{}]*})\s*{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}/.exec col)?
352+
colspan = parseInt (match[1].replace /[{}]/g, ''), 10
332353
attrs += " colspan=\"#{colspan}\""
333-
align = match[4] ? match[3]
334-
col = match[5]
354+
style = parseAlign match[2]
355+
col = match[3]
335356
else
336357
colspan = 1
337358
## In HTML, rowspan means that later rows shouldn't specify <td>s
338359
## for that column, while in LaTeX, they are still present.
339-
if (match = /\\multirow\s*(\d+|{\s*(\d+)\s*})\s*(\*|{([^{}]*)})\s*{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}/.exec col)?
340-
rowspan = parseInt match[2] ? match[1]
360+
if (match = /\\multirow\s*(\d|{\s*\d+\s*})\s*([\w\*]|{[^{}]*})\s*{((?:[^{}]|{(?:[^{}]|{[^{}]*})*})*)}/.exec col)?
361+
rowspan = parseInt (match[1].replace /[{}]/g, ''), 10
362+
skip[colnum] ?= 0
341363
skip[colnum] += rowspan - 1
342364
attrs += " rowspan=\"#{rowspan}\""
343-
style = 'vertical-align: middle; '
344-
#width = match[4] ? match[3]
345-
col = match[5]
346-
attrs +=
347-
switch align
348-
when 'c'
349-
" style=\"#{style}text-align: center\""
350-
when 'l'
351-
" style=\"#{style}text-align: left\""
352-
when 'r'
353-
" style=\"#{style}text-align: right\""
354-
else
355-
style
365+
style += 'vertical-align: middle;'
366+
if (width = match[2]) and width != '*'
367+
width = width[1...-1] if width.startsWith '{'
368+
style += "width: #{width};"
369+
col = match[3]
370+
attrs += " style=\"#{style}\"" if style
356371
colnum += colspan
357372
"<td#{attrs}>#{col}</td>\n"
358373
).join('') +

0 commit comments

Comments
 (0)