Skip to content

Commit 157eb5f

Browse files
authored
Merge pull request #2346 from daiyam/text-deflist
add support to abbreviations, definition lists and subscript/superscript text
2 parents 69691bd + 8f290c2 commit 157eb5f

File tree

9 files changed

+466
-19
lines changed

9 files changed

+466
-19
lines changed

browser/components/markdown.styl

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,36 @@ for name, val in admonition_types
373373
color: val[color]
374374
content: val[icon]
375375

376+
dl
377+
margin 2rem 0
378+
padding 0
379+
display flex
380+
width 100%
381+
flex-wrap wrap
382+
align-items flex-start
383+
border-bottom 1px solid borderColor
384+
background-color tableHeadBgColor
385+
386+
dt
387+
border-top 1px solid borderColor
388+
font-weight bold
389+
text-align right
390+
overflow hidden
391+
flex-basis 20%
392+
padding 0.4rem 0.9rem
393+
box-sizing border-box
394+
395+
dd
396+
border-top 1px solid borderColor
397+
flex-basis 80%
398+
padding 0.4rem 0.9rem
399+
min-height 2.5rem
400+
background-color $ui-noteDetail-backgroundColor
401+
box-sizing border-box
402+
403+
dd + dd
404+
margin-left 20%
405+
376406
pre.fence
377407
flex-wrap wrap
378408

@@ -436,6 +466,14 @@ body[data-theme="dark"]
436466
kbd
437467
background-color themeDarkBorder
438468
color themeDarkText
469+
dl
470+
border-color themeDarkBorder
471+
background-color themeDarkTableHead
472+
dt
473+
border-color themeDarkBorder
474+
dd
475+
border-color themeDarkBorder
476+
background-color themeDarkPreview
439477

440478
themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor
441479
themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%)
@@ -463,6 +501,14 @@ body[data-theme="solarized-dark"]
463501
border-color themeSolarizedDarkTableBorder
464502
&:last-child
465503
border-right solid 1px themeSolarizedDarkTableBorder
504+
dl
505+
border-color themeDarkBorder
506+
background-color themeSolarizedDarkTableHead
507+
dt
508+
border-color themeDarkBorder
509+
dd
510+
border-color themeDarkBorder
511+
background-color $ui-solarized-dark-noteDetail-backgroundColor
466512

467513
themeMonokaiTableOdd = $ui-monokai-noteDetail-backgroundColor
468514
themeMonokaiTableEven = darken($ui-monokai-noteDetail-backgroundColor, 10%)
@@ -492,6 +538,14 @@ body[data-theme="monokai"]
492538
border-right solid 1px themeMonokaiTableBorder
493539
kbd
494540
background-color themeDarkBackground
541+
dl
542+
border-color themeDarkBorder
543+
background-color themeMonokaiTableHead
544+
dt
545+
border-color themeDarkBorder
546+
dd
547+
border-color themeDarkBorder
548+
background-color $ui-monokai-noteDetail-backgroundColor
495549

496550
themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor
497551
themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%)
@@ -520,4 +574,12 @@ body[data-theme="dracula"]
520574
&:last-child
521575
border-right solid 1px themeDraculaTableBorder
522576
kbd
523-
background-color themeDarkBackground
577+
background-color themeDarkBackground
578+
dl
579+
border-color themeDarkBorder
580+
background-color themeDraculaTableHead
581+
dt
582+
border-color themeDarkBorder
583+
dd
584+
border-color themeDarkBorder
585+
background-color $ui-dracula-noteDetail-backgroundColor

browser/lib/markdown-it-deflist.js

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
'use strict'
2+
3+
module.exports = function definitionListPlugin (md) {
4+
var isSpace = md.utils.isSpace
5+
6+
// Search `[:~][\n ]`, returns next pos after marker on success
7+
// or -1 on fail.
8+
function skipMarker (state, line) {
9+
let start = state.bMarks[line] + state.tShift[line]
10+
const max = state.eMarks[line]
11+
12+
if (start >= max) { return -1 }
13+
14+
// Check bullet
15+
const marker = state.src.charCodeAt(start++)
16+
if (marker !== 0x7E/* ~ */ && marker !== 0x3A/* : */) { return -1 }
17+
18+
const pos = state.skipSpaces(start)
19+
20+
// require space after ":"
21+
if (start === pos) { return -1 }
22+
23+
return start
24+
}
25+
26+
function markTightParagraphs (state, idx) {
27+
const level = state.level + 2
28+
29+
let i
30+
let l
31+
for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
32+
if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
33+
state.tokens[i + 2].hidden = true
34+
state.tokens[i].hidden = true
35+
i += 2
36+
}
37+
}
38+
}
39+
40+
function deflist (state, startLine, endLine, silent) {
41+
var ch,
42+
contentStart,
43+
ddLine,
44+
dtLine,
45+
itemLines,
46+
listLines,
47+
listTokIdx,
48+
max,
49+
newEndLine,
50+
nextLine,
51+
offset,
52+
oldDDIndent,
53+
oldIndent,
54+
oldLineMax,
55+
oldParentType,
56+
oldSCount,
57+
oldTShift,
58+
oldTight,
59+
pos,
60+
prevEmptyEnd,
61+
tight,
62+
token
63+
64+
if (silent) {
65+
// quirk: validation mode validates a dd block only, not a whole deflist
66+
if (state.ddIndent < 0) { return false }
67+
return skipMarker(state, startLine) >= 0
68+
}
69+
70+
nextLine = startLine + 1
71+
if (nextLine >= endLine) { return false }
72+
73+
if (state.isEmpty(nextLine)) {
74+
nextLine++
75+
if (nextLine >= endLine) { return false }
76+
}
77+
78+
if (state.sCount[nextLine] < state.blkIndent) { return false }
79+
contentStart = skipMarker(state, nextLine)
80+
if (contentStart < 0) { return false }
81+
82+
// Start list
83+
listTokIdx = state.tokens.length
84+
tight = true
85+
86+
token = state.push('dl_open', 'dl', 1)
87+
token.map = listLines = [ startLine, 0 ]
88+
89+
//
90+
// Iterate list items
91+
//
92+
93+
dtLine = startLine
94+
ddLine = nextLine
95+
96+
// One definition list can contain multiple DTs,
97+
// and one DT can be followed by multiple DDs.
98+
//
99+
// Thus, there is two loops here, and label is
100+
// needed to break out of the second one
101+
//
102+
/* eslint no-labels:0,block-scoped-var:0 */
103+
OUTER:
104+
for (;;) {
105+
prevEmptyEnd = false
106+
107+
token = state.push('dt_open', 'dt', 1)
108+
token.map = [ dtLine, dtLine ]
109+
110+
token = state.push('inline', '', 0)
111+
token.map = [ dtLine, dtLine ]
112+
token.content = state.getLines(dtLine, dtLine + 1, state.blkIndent, false).trim()
113+
token.children = []
114+
115+
token = state.push('dt_close', 'dt', -1)
116+
117+
for (;;) {
118+
token = state.push('dd_open', 'dd', 1)
119+
token.map = itemLines = [ ddLine, 0 ]
120+
121+
pos = contentStart
122+
max = state.eMarks[ddLine]
123+
offset = state.sCount[ddLine] + contentStart - (state.bMarks[ddLine] + state.tShift[ddLine])
124+
125+
while (pos < max) {
126+
ch = state.src.charCodeAt(pos)
127+
128+
if (isSpace(ch)) {
129+
if (ch === 0x09) {
130+
offset += 4 - offset % 4
131+
} else {
132+
offset++
133+
}
134+
} else {
135+
break
136+
}
137+
138+
pos++
139+
}
140+
141+
contentStart = pos
142+
143+
oldTight = state.tight
144+
oldDDIndent = state.ddIndent
145+
oldIndent = state.blkIndent
146+
oldTShift = state.tShift[ddLine]
147+
oldSCount = state.sCount[ddLine]
148+
oldParentType = state.parentType
149+
state.blkIndent = state.ddIndent = state.sCount[ddLine] + 2
150+
state.tShift[ddLine] = contentStart - state.bMarks[ddLine]
151+
state.sCount[ddLine] = offset
152+
state.tight = true
153+
state.parentType = 'deflist'
154+
155+
newEndLine = ddLine
156+
while (++newEndLine < endLine && (state.sCount[newEndLine] >= state.sCount[ddLine] || state.isEmpty(newEndLine))) {
157+
}
158+
159+
oldLineMax = state.lineMax
160+
state.lineMax = newEndLine
161+
162+
state.md.block.tokenize(state, ddLine, newEndLine, true)
163+
164+
state.lineMax = oldLineMax
165+
166+
// If any of list item is tight, mark list as tight
167+
if (!state.tight || prevEmptyEnd) {
168+
tight = false
169+
}
170+
// Item become loose if finish with empty line,
171+
// but we should filter last element, because it means list finish
172+
prevEmptyEnd = (state.line - ddLine) > 1 && state.isEmpty(state.line - 1)
173+
174+
state.tShift[ddLine] = oldTShift
175+
state.sCount[ddLine] = oldSCount
176+
state.tight = oldTight
177+
state.parentType = oldParentType
178+
state.blkIndent = oldIndent
179+
state.ddIndent = oldDDIndent
180+
181+
token = state.push('dd_close', 'dd', -1)
182+
183+
itemLines[1] = nextLine = state.line
184+
185+
if (nextLine >= endLine) { break OUTER }
186+
187+
if (state.sCount[nextLine] < state.blkIndent) { break OUTER }
188+
contentStart = skipMarker(state, nextLine)
189+
if (contentStart < 0) { break }
190+
191+
ddLine = nextLine
192+
193+
// go to the next loop iteration:
194+
// insert DD tag and repeat checking
195+
}
196+
197+
if (nextLine >= endLine) { break }
198+
dtLine = nextLine
199+
200+
if (state.isEmpty(dtLine)) { break }
201+
if (state.sCount[dtLine] < state.blkIndent) { break }
202+
203+
ddLine = dtLine + 1
204+
if (ddLine >= endLine) { break }
205+
if (state.isEmpty(ddLine)) { ddLine++ }
206+
if (ddLine >= endLine) { break }
207+
208+
if (state.sCount[ddLine] < state.blkIndent) { break }
209+
contentStart = skipMarker(state, ddLine)
210+
if (contentStart < 0) { break }
211+
212+
// go to the next loop iteration:
213+
// insert DT and DD tags and repeat checking
214+
}
215+
216+
// Finilize list
217+
token = state.push('dl_close', 'dl', -1)
218+
219+
listLines[1] = nextLine
220+
221+
state.line = nextLine
222+
223+
// mark paragraphs tight if needed
224+
if (tight) {
225+
markTightParagraphs(state, listTokIdx)
226+
}
227+
228+
return true
229+
}
230+
231+
md.block.ruler.before('paragraph', 'deflist', deflist, { alt: [ 'paragraph', 'reference' ] })
232+
}

browser/lib/markdown.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,11 @@ class Markdown {
127127
}
128128
})
129129
this.md.use(require('markdown-it-kbd'))
130-
131130
this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']})
131+
this.md.use(require('markdown-it-abbr'))
132+
this.md.use(require('markdown-it-sub'))
133+
this.md.use(require('markdown-it-sup'))
134+
this.md.use(require('./markdown-it-deflist'))
132135
this.md.use(require('./markdown-it-frontmatter'))
133136

134137
this.md.use(require('./markdown-it-fence'), {
@@ -268,9 +271,12 @@ class Markdown {
268271
this.md.renderer.render = (tokens, options, env) => {
269272
tokens.forEach((token) => {
270273
switch (token.type) {
274+
case 'blockquote_open':
275+
case 'dd_open':
276+
case 'dt_open':
271277
case 'heading_open':
278+
case 'list_item_open':
272279
case 'paragraph_open':
273-
case 'blockquote_open':
274280
case 'table_open':
275281
token.attrPush(['data-line', token.map[0]])
276282
}

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"lodash": "^4.11.1",
7474
"lodash-move": "^1.1.1",
7575
"markdown-it": "^6.0.1",
76+
"markdown-it-abbr": "^1.0.4",
7677
"markdown-it-admonition": "^1.0.4",
7778
"markdown-it-emoji": "^1.1.1",
7879
"markdown-it-footnote": "^3.0.0",
@@ -82,6 +83,8 @@
8283
"markdown-it-named-headers": "^0.0.4",
8384
"markdown-it-plantuml": "^1.1.0",
8485
"markdown-it-smartarrows": "^1.0.1",
86+
"markdown-it-sub": "^1.0.0",
87+
"markdown-it-sup": "^1.0.0",
8588
"markdown-toc": "^1.2.0",
8689
"mdurl": "^1.0.1",
8790
"mermaid": "^8.0.0-rc.8",

0 commit comments

Comments
 (0)