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
50054dfa
Unverified
Commit
50054dfa
authored
Apr 03, 2023
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: markdown editor renderer
parent
d2a18eca
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
502 additions
and
11 deletions
+502
-11
package.json
server/package.json
+1
-1
package-lock.json
ux/package-lock.json
+0
-0
package.json
ux/package.json
+16
-0
EditorMarkdown.vue
ux/src/components/EditorMarkdown.vue
+17
-5
PageHeader.vue
ux/src/components/PageHeader.vue
+10
-0
WelcomeOverlay.vue
ux/src/components/WelcomeOverlay.vue
+8
-1
en.json
ux/src/i18n/locales/en.json
+3
-0
markdown.js
ux/src/renderers/markdown.js
+99
-0
katex.js
ux/src/renderers/modules/katex.js
+145
-0
markdown-it-underline.js
ux/src/renderers/modules/markdown-it-underline.js
+12
-0
plantuml.js
ux/src/renderers/modules/plantuml.js
+187
-0
page.js
ux/src/stores/page.js
+4
-4
No files found.
server/package.json
View file @
50054dfa
...
...
@@ -8,7 +8,7 @@
"dev"
:
true
,
"scripts"
:
{
"start"
:
"cd .. && node server"
,
"dev"
:
"cd .. && nodemon server"
"dev"
:
"cd .. && nodemon server
--watch server --ext js,json,graphql,gql
"
},
"repository"
:
{
"type"
:
"git"
,
...
...
ux/package-lock.json
View file @
50054dfa
B
{
...
...
ux/package.json
View file @
50054dfa
...
...
@@ -53,9 +53,24 @@
"graphql-tag"
:
"2.12.6"
,
"js-cookie"
:
"3.0.1"
,
"jwt-decode"
:
"3.1.2"
,
"katex"
:
"0.16.4"
,
"lodash-es"
:
"4.17.21"
,
"lowlight"
:
"2.8.1"
,
"luxon"
:
"3.3.0"
,
"markdown-it"
:
"13.0.1"
,
"markdown-it-abbr"
:
"1.0.4"
,
"markdown-it-attrs"
:
"4.1.6"
,
"markdown-it-decorate"
:
"1.2.2"
,
"markdown-it-emoji"
:
"2.0.2"
,
"markdown-it-expand-tabs"
:
"1.0.13"
,
"markdown-it-footnote"
:
"3.0.3"
,
"markdown-it-imsize"
:
"2.0.1"
,
"markdown-it-mark"
:
"3.0.1"
,
"markdown-it-multimd-table"
:
"4.2.1"
,
"markdown-it-sub"
:
"1.0.0"
,
"markdown-it-sup"
:
"1.0.0"
,
"markdown-it-task-lists"
:
"2.1.1"
,
"pako"
:
"2.1.0"
,
"pinia"
:
"2.0.33"
,
"prosemirror-commands"
:
"1.5.1"
,
"prosemirror-history"
:
"1.3.0"
,
...
...
@@ -71,6 +86,7 @@
"socket.io-client"
:
"4.6.1"
,
"tabulator-tables"
:
"5.4.4"
,
"tippy.js"
:
"6.3.7"
,
"twemoji"
:
"14.0.2"
,
"uuid"
:
"9.0.0"
,
"v-network-graph"
:
"0.9.1"
,
"vue"
:
"3.2.47"
,
...
...
ux/src/components/EditorMarkdown.vue
View file @
50054dfa
...
...
@@ -236,9 +236,10 @@
import
{
reactive
,
ref
,
shallowRef
,
nextTick
,
onBeforeMount
,
onMounted
,
watch
}
from
'vue'
import
{
useMeta
,
useQuasar
,
setCssVar
}
from
'quasar'
import
{
useI18n
}
from
'vue-i18n'
import
{
get
,
flatten
,
last
,
times
,
startsWith
}
from
'lodash-es'
import
{
get
,
flatten
,
last
,
times
,
startsWith
,
debounce
}
from
'lodash-es'
import
{
useEditorStore
}
from
'src/stores/editor'
import
{
usePageStore
}
from
'src/stores/page'
import
{
useSiteStore
}
from
'src/stores/site'
// Code Mirror
...
...
@@ -260,6 +261,9 @@ import 'codemirror/addon/fold/foldcode.js'
import
'codemirror/addon/fold/foldgutter.js'
import
'codemirror/addon/fold/foldgutter.css'
// Markdown Renderer
import
{
MarkdownRenderer
}
from
'src/renderers/markdown'
// QUASAR
const
$q
=
useQuasar
()
...
...
@@ -267,6 +271,7 @@ const $q = useQuasar()
// STORES
const
editorStore
=
useEditorStore
()
const
pageStore
=
usePageStore
()
const
siteStore
=
useSiteStore
()
// I18N
...
...
@@ -279,12 +284,13 @@ const cm = shallowRef(null)
const
cmRef
=
ref
(
null
)
const
state
=
reactive
({
content
:
''
,
previewShown
:
true
,
previewHTML
:
''
,
previewScrollSync
:
true
}
)
const
md
=
new
MarkdownRenderer
({
}
)
// Platform detection
const
CtrlKey
=
/Mac/
.
test
(
navigator
.
platform
)
?
'Cmd'
:
'Ctrl'
...
...
@@ -396,6 +402,12 @@ function toggleMarkup ({ start, end }) {
cm
.
value
.
doc
.
replaceSelections
(
cm
.
value
.
doc
.
getSelections
().
map
(
s
=>
start
+
s
+
end
))
}
const
onCmInput
=
debounce
(
processContent
,
600
)
function
processContent
(
newContent
)
{
state
.
previewHTML
=
md
.
render
(
newContent
)
}
// MOUNTED
onMounted
(
async
()
=>
{
...
...
@@ -424,12 +436,12 @@ onMounted(async () => {
gutters
:
[
'CodeMirror-linenumbers'
,
'CodeMirror-foldgutter'
]
}
)
cm
.
value
.
setValue
(
stat
e
.
content
)
cm
.
value
.
setValue
(
pageStor
e
.
content
)
cm
.
value
.
on
(
'change'
,
c
=>
{
editor
Store
.
$patch
({
page
Store
.
$patch
({
content
:
c
.
getValue
()
}
)
// onCmInput(editor
Store.content)
onCmInput
(
page
Store
.
content
)
}
)
cm
.
value
.
setSize
(
null
,
'100%'
)
...
...
ux/src/components/PageHeader.vue
View file @
50054dfa
...
...
@@ -199,6 +199,16 @@ const editUrl = computed(() => {
// METHODS
async
function
discardChanges
()
{
// Is it the home page in create mode?
if
(
editorStore
.
mode
===
'create'
&&
pageStore
.
path
===
''
&&
pageStore
.
locale
===
'en'
)
{
editorStore
.
$patch
({
isActive
:
false
,
editor
:
''
})
siteStore
.
overlay
=
'Welcome'
return
}
$q
.
loading
.
show
()
try
{
editorStore
.
$patch
({
...
...
ux/src/components/WelcomeOverlay.vue
View file @
50054dfa
...
...
@@ -90,7 +90,14 @@ useMeta({
function
createHomePage
(
editor
)
{
siteStore
.
overlay
=
''
pageStore
.
pageCreate
({
editor
,
locale
:
'en'
,
path
:
''
})
pageStore
.
pageCreate
({
editor
,
locale
:
'en'
,
path
:
''
,
title
:
t
(
'welcome.homeDefault.title'
),
description
:
t
(
'welcome.homeDefault.description'
),
content
:
t
(
'welcome.homeDefault.content'
)
})
}
function
loadAdmin
()
{
...
...
ux/src/i18n/locales/en.json
View file @
50054dfa
...
...
@@ -1732,6 +1732,9 @@
"tags.selectOneMoreTagsHint"
:
"Select one or more tags on the left."
,
"welcome.admin"
:
"Administration Area"
,
"welcome.createHome"
:
"Create the homepage"
,
"welcome.homeDefault.content"
:
"Write some content here..."
,
"welcome.homeDefault.description"
:
"Welcome to my wiki!"
,
"welcome.homeDefault.title"
:
"Home"
,
"welcome.subtitle"
:
"Let's get started..."
,
"welcome.title"
:
"Welcome to Wiki.js!"
}
ux/src/renderers/markdown.js
0 → 100644
View file @
50054dfa
import
MarkdownIt
from
'markdown-it'
import
mdAttrs
from
'markdown-it-attrs'
import
mdDecorate
from
'markdown-it-decorate'
import
mdEmoji
from
'markdown-it-emoji'
import
mdTaskLists
from
'markdown-it-task-lists'
import
mdExpandTabs
from
'markdown-it-expand-tabs'
import
mdAbbr
from
'markdown-it-abbr'
import
mdSup
from
'markdown-it-sup'
import
mdSub
from
'markdown-it-sub'
import
mdMark
from
'markdown-it-mark'
import
mdMultiTable
from
'markdown-it-multimd-table'
import
mdFootnote
from
'markdown-it-footnote'
// import mdImsize from 'markdown-it-imsize'
import
katex
from
'katex'
import
underline
from
'./modules/markdown-it-underline'
import
'katex/dist/contrib/mhchem'
import
twemoji
from
'twemoji'
import
plantuml
from
'./modules/plantuml'
import
katexHelper
from
'./modules/katex'
import
{
escape
}
from
'lodash-es'
export
class
MarkdownRenderer
{
constructor
(
conf
=
{})
{
this
.
md
=
new
MarkdownIt
({
html
:
true
,
breaks
:
true
,
linkify
:
true
,
typography
:
true
,
highlight
(
str
,
lang
)
{
if
(
lang
===
'diagram'
)
{
return
`<pre class="diagram">
${
Buffer
.
from
(
str
,
'base64'
).
toString
()}
</pre>`
}
else
if
([
'mermaid'
,
'plantuml'
].
includes
(
lang
))
{
return
`<pre class="codeblock-
${
lang
}
"><code>
${
escape
(
str
)}
</code></pre>`
}
else
{
return
`<pre class="line-numbers"><code class="language-
${
lang
}
">
${
escape
(
str
)}
</code></pre>`
}
}
})
.
use
(
mdAttrs
,
{
allowedAttributes
:
[
'id'
,
'class'
,
'target'
]
})
.
use
(
mdDecorate
)
.
use
(
underline
)
.
use
(
mdEmoji
)
.
use
(
mdTaskLists
,
{
label
:
false
,
labelAfter
:
false
})
.
use
(
mdExpandTabs
)
.
use
(
mdAbbr
)
.
use
(
mdSup
)
.
use
(
mdSub
)
.
use
(
mdMultiTable
,
{
multiline
:
true
,
rowspan
:
true
,
headerless
:
true
})
.
use
(
mdMark
)
.
use
(
mdFootnote
)
// .use(mdImsize)
// -> PLANTUML
plantuml
.
init
(
this
.
md
,
{})
// -> KATEX
const
macros
=
{}
this
.
md
.
inline
.
ruler
.
after
(
'escape'
,
'katex_inline'
,
katexHelper
.
katexInline
)
this
.
md
.
renderer
.
rules
.
katex_inline
=
(
tokens
,
idx
)
=>
{
try
{
return
katex
.
renderToString
(
tokens
[
idx
].
content
,
{
displayMode
:
false
,
macros
})
}
catch
(
err
)
{
console
.
warn
(
err
)
return
tokens
[
idx
].
content
}
}
this
.
md
.
block
.
ruler
.
after
(
'blockquote'
,
'katex_block'
,
katexHelper
.
katexBlock
,
{
alt
:
[
'paragraph'
,
'reference'
,
'blockquote'
,
'list'
]
})
this
.
md
.
renderer
.
rules
.
katex_block
=
(
tokens
,
idx
)
=>
{
try
{
return
'<p>'
+
katex
.
renderToString
(
tokens
[
idx
].
content
,
{
displayMode
:
true
,
macros
})
+
'</p>'
}
catch
(
err
)
{
console
.
warn
(
err
)
return
tokens
[
idx
].
content
}
}
// -> TWEMOJI
this
.
md
.
renderer
.
rules
.
emoji
=
(
token
,
idx
)
=>
{
return
twemoji
.
parse
(
token
[
idx
].
content
,
{
callback
(
icon
,
opts
)
{
return
`/_assets/svg/twemoji/
${
icon
}
.svg`
}
})
}
}
render
(
src
)
{
return
this
.
md
.
render
(
src
)
}
}
ux/src/renderers/modules/katex.js
0 → 100644
View file @
50054dfa
// Test if potential opening or closing delimieter
// Assumes that there is a "$" at state.src[pos]
function
isValidDelim
(
state
,
pos
)
{
const
max
=
state
.
posMax
let
canOpen
=
true
let
canClose
=
true
const
prevChar
=
pos
>
0
?
state
.
src
.
charCodeAt
(
pos
-
1
)
:
-
1
const
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
,
canClose
}
}
export
default
{
katexInline
(
state
,
silent
)
{
let
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.
const
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
// Extract the math part without the $
.slice(start, match)
// Escape the curly braces since they will be interpreted as
// attributes by markdown-it-attrs (the "curly_attributes"
// core rule)
.replaceAll('
{
', '
{{
')
.replaceAll('
}
', '
}}
')
}
state.pos = match + 1
return true
},
katexBlock (state, start, end, silent) {
let firstLine; let lastLine; let next; let lastPos; let found = false
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
const 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
}
}
ux/src/renderers/modules/markdown-it-underline.js
0 → 100644
View file @
50054dfa
function
renderEm
(
tokens
,
idx
,
opts
,
env
,
slf
)
{
const
token
=
tokens
[
idx
]
if
(
token
.
markup
===
'_'
)
{
token
.
tag
=
'u'
}
return
slf
.
renderToken
(
tokens
,
idx
,
opts
)
}
export
default
(
md
)
=>
{
md
.
renderer
.
rules
.
em_open
=
renderEm
md
.
renderer
.
rules
.
em_close
=
renderEm
}
ux/src/renderers/modules/plantuml.js
0 → 100644
View file @
50054dfa
import
pako
from
'pako'
// ------------------------------------
// Markdown - PlantUML Preprocessor
// ------------------------------------
export
default
{
init
(
mdinst
,
conf
)
{
mdinst
.
use
((
md
,
opts
)
=>
{
const
openMarker
=
opts
.
openMarker
||
'```plantuml'
const
openChar
=
openMarker
.
charCodeAt
(
0
)
const
closeMarker
=
opts
.
closeMarker
||
'```'
const
closeChar
=
closeMarker
.
charCodeAt
(
0
)
const
imageFormat
=
opts
.
imageFormat
||
'svg'
const
server
=
opts
.
server
||
'https://plantuml.requarks.io'
md
.
block
.
ruler
.
before
(
'fence'
,
'uml_diagram'
,
(
state
,
startLine
,
endLine
,
silent
)
=>
{
let
nextLine
let
i
let
autoClosed
=
false
let
start
=
state
.
bMarks
[
startLine
]
+
state
.
tShift
[
startLine
]
let
max
=
state
.
eMarks
[
startLine
]
// Check out the first character quickly,
// this should filter out most of non-uml blocks
//
if
(
openChar
!==
state
.
src
.
charCodeAt
(
start
))
{
return
false
}
// Check out the rest of the marker string
//
for
(
i
=
0
;
i
<
openMarker
.
length
;
++
i
)
{
if
(
openMarker
[
i
]
!==
state
.
src
[
start
+
i
])
{
return
false
}
}
const
markup
=
state
.
src
.
slice
(
start
,
start
+
i
)
const
params
=
state
.
src
.
slice
(
start
+
i
,
max
)
// Since start is found, we can report success here in validation mode
//
if
(
silent
)
{
return
true
}
// Search for the end of the block
//
nextLine
=
startLine
for
(;;)
{
nextLine
++
if
(
nextLine
>=
endLine
)
{
// unclosed block should be autoclosed by end of document.
// also block seems to be autoclosed by end of parent
break
}
start
=
state
.
bMarks
[
nextLine
]
+
state
.
tShift
[
nextLine
]
max
=
state
.
eMarks
[
nextLine
]
if
(
start
<
max
&&
state
.
sCount
[
nextLine
]
<
state
.
blkIndent
)
{
// non-empty line with negative indent should stop the list:
// - ```
// test
break
}
if
(
closeChar
!==
state
.
src
.
charCodeAt
(
start
))
{
// didn't find the closing fence
continue
}
if
(
state
.
sCount
[
nextLine
]
>
state
.
sCount
[
startLine
])
{
// closing fence should not be indented with respect of opening fence
continue
}
let
closeMarkerMatched
=
true
for
(
i
=
0
;
i
<
closeMarker
.
length
;
++
i
)
{
if
(
closeMarker
[
i
]
!==
state
.
src
[
start
+
i
])
{
closeMarkerMatched
=
false
break
}
}
if
(
!
closeMarkerMatched
)
{
continue
}
// make sure tail has spaces only
if
(
state
.
skipSpaces
(
start
+
i
)
<
max
)
{
continue
}
// found!
autoClosed
=
true
break
}
const
contents
=
state
.
src
.
split
(
'
\
n'
)
.
slice
(
startLine
+
1
,
nextLine
)
.
join
(
'
\
n'
)
// We generate a token list for the alt property, to mimic what the image parser does.
const
altToken
=
[]
// Remove leading space if any.
const
alt
=
params
?
params
.
slice
(
1
)
:
'uml diagram'
state
.
md
.
inline
.
parse
(
alt
,
state
.
md
,
state
.
env
,
altToken
)
const
zippedCode
=
encode64
(
pako
.
deflate
(
'@startuml
\
n'
+
contents
+
'
\
n@enduml'
,
{
to
:
'string'
}))
const
token
=
state
.
push
(
'uml_diagram'
,
'img'
,
0
)
// alt is constructed from children. No point in populating it here.
token
.
attrs
=
[[
'src'
,
`
${
server
}
/
${
imageFormat
}
/
${
zippedCode
}
`
],
[
'alt'
,
''
],
[
'class'
,
'uml-diagram'
]]
token
.
block
=
true
token
.
children
=
altToken
token
.
info
=
params
token
.
map
=
[
startLine
,
nextLine
]
token
.
markup
=
markup
state
.
line
=
nextLine
+
(
autoClosed
?
1
:
0
)
return
true
},
{
alt
:
[
'paragraph'
,
'reference'
,
'blockquote'
,
'list'
]
})
md
.
renderer
.
rules
.
uml_diagram
=
md
.
renderer
.
rules
.
image
},
{
openMarker
:
conf
.
openMarker
,
closeMarker
:
conf
.
closeMarker
,
imageFormat
:
conf
.
imageFormat
,
server
:
conf
.
server
})
}
}
function
encode64
(
data
)
{
let
r
=
''
for
(
let
i
=
0
;
i
<
data
.
length
;
i
+=
3
)
{
if
(
i
+
2
===
data
.
length
)
{
r
+=
append3bytes
(
data
.
charCodeAt
(
i
),
data
.
charCodeAt
(
i
+
1
),
0
)
}
else
if
(
i
+
1
===
data
.
length
)
{
r
+=
append3bytes
(
data
.
charCodeAt
(
i
),
0
,
0
)
}
else
{
r
+=
append3bytes
(
data
.
charCodeAt
(
i
),
data
.
charCodeAt
(
i
+
1
),
data
.
charCodeAt
(
i
+
2
))
}
}
return
r
}
function
append3bytes
(
b1
,
b2
,
b3
)
{
const
c1
=
b1
>>
2
const
c2
=
((
b1
&
0x3
)
<<
4
)
|
(
b2
>>
4
)
const
c3
=
((
b2
&
0xF
)
<<
2
)
|
(
b3
>>
6
)
const
c4
=
b3
&
0x3F
let
r
=
''
r
+=
encode6bit
(
c1
&
0x3F
)
r
+=
encode6bit
(
c2
&
0x3F
)
r
+=
encode6bit
(
c3
&
0x3F
)
r
+=
encode6bit
(
c4
&
0x3F
)
return
r
}
function
encode6bit
(
raw
)
{
let
b
=
raw
if
(
b
<
10
)
{
return
String
.
fromCharCode
(
48
+
b
)
}
b
-=
10
if
(
b
<
26
)
{
return
String
.
fromCharCode
(
65
+
b
)
}
b
-=
26
if
(
b
<
26
)
{
return
String
.
fromCharCode
(
97
+
b
)
}
b
-=
26
if
(
b
===
0
)
{
return
'-'
}
if
(
b
===
1
)
{
return
'_'
}
return
'?'
}
ux/src/stores/page.js
View file @
50054dfa
...
...
@@ -173,7 +173,7 @@ export const usePageStore = defineStore('page', {
/**
* PAGE - CREATE
*/
pageCreate
({
editor
,
locale
,
path
})
{
pageCreate
({
editor
,
locale
,
path
,
title
=
''
,
description
=
''
,
content
=
''
})
{
const
editorStore
=
useEditorStore
()
// if (['markdown', 'api'].includes(editor)) {
...
...
@@ -196,14 +196,14 @@ export const usePageStore = defineStore('page', {
}
else
{
this
.
path
=
this
.
path
.
length
<
2
?
'new-page'
:
`
${
this
.
path
}
/new-page`
}
this
.
title
=
''
this
.
description
=
''
this
.
title
=
title
??
''
this
.
description
=
description
??
''
this
.
icon
=
'las la-file-alt'
this
.
publishState
=
'published'
this
.
relations
=
[]
this
.
tags
=
[]
this
.
content
=
''
this
.
content
=
content
??
''
this
.
render
=
''
// -> View Mode
...
...
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