Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wiki-js
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
wiki-js
Commits
830f5166
You need to sign in or sign up before continuing.
Commit
830f5166
authored
Mar 06, 2020
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: katex in markdown preview + xss fix for svg
parent
43985736
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
175 additions
and
2 deletions
+175
-2
katex.js
client/components/editor/common/katex.js
+140
-0
editor-markdown.vue
client/components/editor/editor-markdown.vue
+33
-0
renderer.js
server/modules/rendering/html-security/renderer.js
+2
-2
No files found.
client/components/editor/common/katex.js
0 → 100644
View file @
830f5166
// Test if potential opening or closing delimieter
// Assumes that there is a "$" at state.src[pos]
function
isValidDelim
(
state
,
pos
)
{
let
prevChar
let
nextChar
let
max
=
state
.
posMax
let
canOpen
=
true
let
canClose
=
true
prevChar
=
pos
>
0
?
state
.
src
.
charCodeAt
(
pos
-
1
)
:
-
1
nextChar
=
pos
+
1
<=
max
?
state
.
src
.
charCodeAt
(
pos
+
1
)
:
-
1
// Check non-whitespace conditions for opening and closing, and
// check that closing delimeter isn't followed by a number
if
(
prevChar
===
0x20
/* " " */
||
prevChar
===
0x09
/* \t */
||
(
nextChar
>=
0x30
/* "0" */
&&
nextChar
<=
0x39
/* "9" */
))
{
canClose
=
false
}
if
(
nextChar
===
0x20
/* " " */
||
nextChar
===
0x09
/* \t */
)
{
canOpen
=
false
}
return
{
canOpen
:
canOpen
,
canClose
:
canClose
}
}
export
default
{
katexInline
(
state
,
silent
)
{
let
start
,
match
,
token
,
res
,
pos
if
(
state
.
src
[
state
.
pos
]
!==
'$'
)
{
return
false
}
res
=
isValidDelim
(
state
,
state
.
pos
)
if
(
!
res
.
canOpen
)
{
if
(
!
silent
)
{
state
.
pending
+=
'$'
}
state
.
pos
+=
1
return
true
}
// First check for and bypass all properly escaped delimieters
// This loop will assume that the first leading backtick can not
// be the first character in state.src, which is known since
// we have found an opening delimieter already.
start
=
state
.
pos
+
1
match
=
start
while
((
match
=
state
.
src
.
indexOf
(
'$'
,
match
))
!==
-
1
)
{
// Found potential $, look for escapes, pos will point to
// first non escape when complete
pos
=
match
-
1
while
(
state
.
src
[
pos
]
===
'
\
\'
) { pos -= 1 }
// Even number of escapes, potential closing delimiter found
if (((match - pos) % 2) === 1) { break }
match += 1
}
// No closing delimter found. Consume $ and continue.
if (match === -1) {
if (!silent) { state.pending += '
$
' }
state.pos = start
return true
}
// Check if we have empty content, ie: $$. Do not parse.
if (match - start === 0) {
if (!silent) { state.pending += '
$$
' }
state.pos = start + 1
return true
}
// Check for valid closing delimiter
res = isValidDelim(state, match)
if (!res.canClose) {
if (!silent) { state.pending += '
$
' }
state.pos = start
return true
}
if (!silent) {
token = state.push('
katex_inline
', '
math
', 0)
token.markup = '
$
'
token.content = state.src.slice(start, match)
}
state.pos = match + 1
return true
},
katexBlock (state, start, end, silent) {
let firstLine; let lastLine; let next; let lastPos; let found = false; let token
let pos = state.bMarks[start] + state.tShift[start]
let max = state.eMarks[start]
if (pos + 2 > max) { return false }
if (state.src.slice(pos, pos + 2) !== '
$$
') { return false }
pos += 2
firstLine = state.src.slice(pos, max)
if (silent) { return true }
if (firstLine.trim().slice(-2) === '
$$
') {
// Single line expression
firstLine = firstLine.trim().slice(0, -2)
found = true
}
for (next = start; !found;) {
next++
if (next >= end) { break }
pos = state.bMarks[next] + state.tShift[next]
max = state.eMarks[next]
if (pos < max && state.tShift[next] < state.blkIndent) {
// non-empty line with negative indent should stop the list:
break
}
if (state.src.slice(pos, max).trim().slice(-2) === '
$$
') {
lastPos = state.src.slice(0, max).lastIndexOf('
$$
')
lastLine = state.src.slice(pos, lastPos)
found = true
}
}
state.line = next + 1
token = state.push('
katex_block
', '
math
', 0)
token.block = true
token.content = (firstLine && firstLine.trim() ? firstLine + '
\
n
' : '') +
state.getLines(start + 1, next, state.tShift[start], true) +
(lastLine && lastLine.trim() ? lastLine : '')
token.map = [ start, state.line ]
token.markup = '
$$
'
return true
}
}
client/components/editor/editor-markdown.vue
View file @
830f5166
...
@@ -214,10 +214,14 @@ import mdSup from 'markdown-it-sup'
...
@@ -214,10 +214,14 @@ import mdSup from 'markdown-it-sup'
import
mdSub
from
'markdown-it-sub'
import
mdSub
from
'markdown-it-sub'
import
mdMark
from
'markdown-it-mark'
import
mdMark
from
'markdown-it-mark'
import
mdImsize
from
'markdown-it-imsize'
import
mdImsize
from
'markdown-it-imsize'
import
katex
from
'katex'
// Prism (Syntax Highlighting)
// Prism (Syntax Highlighting)
import
Prism
from
'prismjs'
import
Prism
from
'prismjs'
// Helpers
import
katexHelper
from
'./common/katex'
// ========================================
// ========================================
// INIT
// INIT
// ========================================
// ========================================
...
@@ -279,6 +283,35 @@ md.renderer.rules.heading_open = injectLineNumbers
...
@@ -279,6 +283,35 @@ md.renderer.rules.heading_open = injectLineNumbers
md
.
renderer
.
rules
.
blockquote_open
=
injectLineNumbers
md
.
renderer
.
rules
.
blockquote_open
=
injectLineNumbers
// ========================================
// ========================================
// KATEX
// ========================================
md
.
inline
.
ruler
.
after
(
'escape'
,
'katex_inline'
,
katexHelper
.
katexInline
)
md
.
renderer
.
rules
.
katex_inline
=
(
tokens
,
idx
)
=>
{
try
{
return
katex
.
renderToString
(
tokens
[
idx
].
content
,
{
displayMode
:
false
}
)
}
catch
(
err
)
{
console
.
warn
(
err
)
return
tokens
[
idx
].
content
}
}
md
.
block
.
ruler
.
after
(
'blockquote'
,
'katex_block'
,
katexHelper
.
katexBlock
,
{
alt
:
[
'paragraph'
,
'reference'
,
'blockquote'
,
'list'
]
}
)
md
.
renderer
.
rules
.
katex_block
=
(
tokens
,
idx
)
=>
{
try
{
return
`<p>`
+
katex
.
renderToString
(
tokens
[
idx
].
content
,
{
displayMode
:
true
}
)
+
`</p>`
}
catch
(
err
)
{
console
.
warn
(
err
)
return
tokens
[
idx
].
content
}
}
// ========================================
// Vue Component
// Vue Component
// ========================================
// ========================================
...
...
server/modules/rendering/html-security/renderer.js
View file @
830f5166
...
@@ -29,10 +29,10 @@ module.exports = {
...
@@ -29,10 +29,10 @@ module.exports = {
path
:
[
'd'
,
'style'
],
path
:
[
'd'
,
'style'
],
pre
:
[
'class'
,
'style'
],
pre
:
[
'class'
,
'style'
],
section
:
[
'class'
,
'style'
],
section
:
[
'class'
,
'style'
],
span
:
[
'class'
,
'style'
],
span
:
[
'class'
,
'style'
,
'aria-hidden'
],
strong
:
[
'class'
,
'style'
],
strong
:
[
'class'
,
'style'
],
summary
:
[
'class'
,
'style'
],
summary
:
[
'class'
,
'style'
],
svg
:
[
'width'
,
'height'
,
'view
Box'
,
'preserveAspectR
atio'
,
'style'
],
svg
:
[
'width'
,
'height'
,
'view
box'
,
'preserveaspectr
atio'
,
'style'
],
table
:
[
'border'
,
'class'
,
'id'
,
'style'
,
'width'
],
table
:
[
'border'
,
'class'
,
'id'
,
'style'
,
'width'
],
tbody
:
[
'class'
,
'style'
],
tbody
:
[
'class'
,
'style'
],
td
:
[
'align'
,
'class'
,
'colspan'
,
'rowspan'
,
'style'
,
'valign'
],
td
:
[
'align'
,
'class'
,
'colspan'
,
'rowspan'
,
'style'
,
'valign'
],
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment