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
ca4e0ada
You need to sign in or sign up before continuing.
Commit
ca4e0ada
authored
May 05, 2019
by
Nick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: markdown editor toolbar + default group rules fix
parent
2ba10040
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
238 additions
and
50 deletions
+238
-50
editor.vue
client/components/editor.vue
+2
-1
editor-markdown.vue
client/components/editor/editor-markdown.vue
+135
-45
editor-modal-blocks.vue
client/components/editor/editor-modal-blocks.vue
+86
-0
editor-modal-media.vue
client/components/editor/editor-modal-media.vue
+1
-1
data.yml
server/app/data.yml
+13
-2
group.js
server/graph/resolvers/group.js
+1
-1
No files found.
client/components/editor.vue
View file @
ca4e0ada
...
...
@@ -67,7 +67,8 @@ export default {
editorModalEditorselect
:
()
=>
import
(
/* webpackChunkName: "editor", webpackMode: "eager" */
'./editor/editor-modal-editorselect.vue'
),
editorModalProperties
:
()
=>
import
(
/* webpackChunkName: "editor", webpackMode: "eager" */
'./editor/editor-modal-properties.vue'
),
editorModalUnsaved
:
()
=>
import
(
/* webpackChunkName: "editor", webpackMode: "eager" */
'./editor/editor-modal-unsaved.vue'
),
editorModalMedia
:
()
=>
import
(
/* webpackChunkName: "editor", webpackMode: "eager" */
'./editor/editor-modal-media.vue'
)
editorModalMedia
:
()
=>
import
(
/* webpackChunkName: "editor", webpackMode: "eager" */
'./editor/editor-modal-media.vue'
),
editorModalBlocks
:
()
=>
import
(
/* webpackChunkName: "editor", webpackMode: "eager" */
'./editor/editor-modal-blocks.vue'
)
},
props
:
{
locale
:
{
...
...
client/components/editor/editor-markdown.vue
View file @
ca4e0ada
<
template
lang=
'pug'
>
.editor-markdown
v-toolbar.editor-markdown-toolbar(dense, color='primary', dark, flat)
v-tooltip(
top
)
v-btn(icon, slot='activator').mx-0
v-tooltip(
bottom, color='primary'
)
v-btn(icon, slot='activator'
, @click='toggleMarkup({ start: `**` })'
).mx-0
v-icon format_bold
span Bold
v-tooltip(
top
)
v-btn(icon, slot='activator').mx-0
v-tooltip(
bottom, color='primary'
)
v-btn(icon, slot='activator'
, @click='toggleMarkup({ start: `*` })'
).mx-0
v-icon format_italic
span Italic
v-tooltip(
top
)
v-btn(icon, slot='activator').mx-0
v-tooltip(
bottom, color='primary'
)
v-btn(icon, slot='activator'
, @click='toggleMarkup({ start: `~~` })'
).mx-0
v-icon format_strikethrough
span Strikethrough
v-menu(offset-y, open-on-hover)
v-btn(icon, slot='activator').mx-0
v-icon font_download
v-list
v-list-tile(v-for='(n, idx) in 6', @click='', :key='idx')
v-icon text_fields
v-list.py-0
template(v-for='(n, idx) in 6')
v-list-tile(@click='setHeaderLine(n)', :key='idx')
v-list-tile-action
v-icon font_download
v-icon(:size='24 - (idx - 1) * 2') title
v-list-tile-title Heading
{{
n
}}
v-tooltip(top)
v-divider(v-if='idx < 5')
v-tooltip(bottom, color='primary')
v-btn(icon, slot='activator', @click='toggleMarkup({ start: `~` })').mx-0
v-icon vertical_align_bottom
span Subscript
v-tooltip(bottom, color='primary')
v-btn(icon, slot='activator', @click='toggleMarkup({ start: `^` })').mx-0
v-icon vertical_align_top
span Superscript
v-menu(offset-y, open-on-hover)
v-btn(icon, slot='activator').mx-0
v-icon format_quote
span Blockquote
v-tooltip(top)
v-btn(icon, slot='activator').mx-0
v-list.py-0
v-list-tile(@click='insertBeforeEachLine({ content: `> `})')
v-list-tile-action
v-icon format_quote
v-list-tile-title Blockquote
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-info}`})')
v-list-tile-action
v-icon(color='blue') format_quote
v-list-tile-title Info Blockquote
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-success}`})')
v-list-tile-action
v-icon(color='success') format_quote
v-list-tile-title Success Blockquote
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-warning}`})')
v-list-tile-action
v-icon(color='warning') format_quote
v-list-tile-title Warning Blockquote
v-divider
v-list-tile(@click='insertBeforeEachLine({ content: `> `, after: `{.is-error}`})')
v-list-tile-action
v-icon(color='error') format_quote
v-list-tile-title Error Blockquote
v-divider
v-tooltip(bottom, color='primary')
v-btn(icon, slot='activator', @click='insertBeforeEachLine({ content: `- `})').mx-0
v-icon format_list_bulleted
span Unordered List
v-tooltip(
top
)
v-btn(icon, slot='activator').mx-0
v-tooltip(
bottom, color='primary'
)
v-btn(icon, slot='activator'
, @click='insertBeforeEachLine({ content: `1. `})'
).mx-0
v-icon format_list_numbered
span Ordered List
v-tooltip(top)
v-btn(icon, slot='activator').mx-0
v-icon insert_link
span Link
v-tooltip(top)
v-btn(icon, slot='activator').mx-0
v-tooltip(bottom, color='primary')
v-btn(icon, slot='activator', @click='toggleMarkup({ start: "`" })').mx-0
v-icon space_bar
span Inline Code
v-tooltip(
top
)
v-btn(icon, slot='activator').mx-0
v-icon
code
span
Code Block
v-tooltip(
top
)
v-btn(icon, slot='activator').mx-0
v-tooltip(
bottom, color='primary'
)
v-btn(icon, slot='activator'
, @click='toggleMarkup({ start: `<kbd>`, end: `</kbd>` })'
).mx-0
v-icon
font_download
span
Keyboard Key
v-tooltip(
bottom, color='primary'
)
v-btn(icon, slot='activator'
, @click='insertAfter({ content: `---`, newLine: true })'
).mx-0
v-icon remove
span Horizontal Bar
.editor-markdown-main
.editor-markdown-sidebar
v-tooltip(right, color='
primary
')
v-btn(icon, slot='activator', dark).mx-0
v-tooltip(right, color='
teal
')
v-btn(icon, slot='activator', dark
, disabled
).mx-0
v-icon link
span Insert Link
v-tooltip(right)
v-tooltip(right
, color='teal'
)
v-btn(icon, slot='activator', dark, @click='toggleModal(`editorModalMedia`)').mx-0
v-icon(:color='activeModal === `editorModalMedia` ? `teal` : ``') image
span Insert Image
v-tooltip(right, color='primary')
v-btn(icon, slot='activator', dark).mx-0
v-tooltip(right, color='teal')
v-btn(icon, slot='activator', dark, @click='toggleModal(`editorModalBlocks`)').mx-0
v-icon(:color='activeModal === `editorModalBlocks` ? `teal` : ``') dashboard
span Insert Block
v-tooltip(right, color='teal')
v-btn(icon, slot='activator', dark, disabled).mx-0
v-icon insert_drive_file
span Insert File
v-tooltip(right, color='primary')
v-btn(icon, slot='activator', dark).mx-0
v-tooltip(right, color='teal')
v-btn(icon, slot='activator', dark, disabled).mx-0
v-icon code
span Insert Code Block
v-tooltip(right, color='teal')
v-btn(icon, slot='activator', dark, disabled).mx-0
v-icon play_circle_outline
span Insert Video / Audio
v-tooltip(right, color='
primary
')
v-btn(icon, slot='activator', dark).mx-0
v-tooltip(right, color='
teal
')
v-btn(icon, slot='activator', dark
, disabled
).mx-0
v-icon multiline_chart
span Insert Diagram
v-tooltip(right, color='
primary
')
v-btn(icon, slot='activator', dark).mx-0
v-tooltip(right, color='
teal
')
v-btn(icon, slot='activator', dark
, disabled
).mx-0
v-icon functions
span Insert Math Expression
v-tooltip(right, color='
primary
')
v-btn(icon, slot='activator', dark).mx-0
v-tooltip(right, color='
teal
')
v-btn(icon, slot='activator', dark
, disabled
).mx-0
v-icon border_outer
span Table Helper
v-spacer
v-tooltip(right, color='
primary
')
v-tooltip(right, color='
teal
')
v-btn(icon, slot='activator', dark, @click='toggleFullscreen').mx-0
v-icon crop_free
span
Fullscreen Editor
v-tooltip(right, color='
primary
')
v-btn(icon, slot='activator', dark).mx-0
span
Distraction Free Mode
v-tooltip(right, color='
teal
')
v-btn(icon, slot='activator', dark
, disabled
).mx-0
v-icon help
span Markdown Formatting Help
.editor-markdown-editor
...
...
@@ -273,6 +312,57 @@ export default {
// console.info(token)
},
toggleMarkup
({
start
,
end
})
{
if
(
!
end
)
{
end
=
start
}
if
(
!
this
.
cm
.
doc
.
somethingSelected
())
{
return
this
.
$store
.
commit
(
'showNotification'
,
{
message
:
'You must select something first!'
,
style
:
'warning'
,
icon
:
'warning'
})
}
this
.
cm
.
doc
.
replaceSelections
(
this
.
cm
.
doc
.
getSelections
().
map
(
s
=>
start
+
s
+
end
))
},
setHeaderLine
(
lvl
)
{
const
curLine
=
this
.
cm
.
doc
.
getCursor
(
'head'
).
line
let
lineContent
=
this
.
cm
.
doc
.
getLine
(
curLine
)
const
lineLength
=
lineContent
.
length
if
(
_
.
startsWith
(
lineContent
,
'#'
))
{
lineContent
=
lineContent
.
replace
(
/^
(
#+
)
/
,
''
)
}
lineContent
=
_
.
times
(
lvl
,
n
=>
'#'
).
join
(
''
)
+
` `
+
lineContent
this
.
cm
.
doc
.
replaceRange
(
lineContent
,
{
line
:
curLine
,
ch
:
0
},
{
line
:
curLine
,
ch
:
lineLength
})
},
insertAfter
({
content
,
newLine
})
{
const
curLine
=
this
.
cm
.
doc
.
getCursor
(
'to'
).
line
const
lineLength
=
this
.
cm
.
doc
.
getLine
(
curLine
).
length
this
.
cm
.
doc
.
replaceRange
(
newLine
?
`\n
${
content
}
\n`
:
content
,
{
line
:
curLine
,
ch
:
lineLength
+
1
})
},
insertBeforeEachLine
({
content
,
after
})
{
let
lines
=
[]
if
(
!
this
.
cm
.
doc
.
somethingSelected
())
{
lines
.
push
(
this
.
cm
.
doc
.
getCursor
(
'head'
).
line
)
}
else
{
lines
=
_
.
flatten
(
this
.
cm
.
doc
.
listSelections
().
map
(
sl
=>
{
const
range
=
Math
.
abs
(
sl
.
anchor
.
line
-
sl
.
head
.
line
)
+
1
const
lowestLine
=
(
sl
.
anchor
.
line
>
sl
.
head
.
line
)
?
sl
.
head
.
line
:
sl
.
anchor
.
line
return
_
.
times
(
range
,
l
=>
l
+
lowestLine
)
}))
}
lines
.
forEach
(
ln
=>
{
let
lineContent
=
this
.
cm
.
doc
.
getLine
(
ln
)
const
lineLength
=
lineContent
.
length
if
(
_
.
startsWith
(
lineContent
,
content
))
{
lineContent
=
lineContent
.
substring
(
content
.
length
)
}
this
.
cm
.
doc
.
replaceRange
(
content
+
lineContent
,
{
line
:
ln
,
ch
:
0
},
{
line
:
ln
,
ch
:
lineLength
})
})
if
(
after
)
{
const
lastLine
=
_
.
last
(
lines
)
this
.
cm
.
doc
.
replaceRange
(
`\n
${
after
}
\n`
,
{
line
:
lastLine
,
ch
:
this
.
cm
.
doc
.
getLine
(
lastLine
).
length
+
1
})
}
},
/**
* Update scroll sync
*/
...
...
client/components/editor/editor-modal-blocks.vue
0 → 100644
View file @
ca4e0ada
<
template
lang=
'pug'
>
v-card.editor-modal-blocks.animated.fadeInLeft(flat, tile)
v-container.pa-3(grid-list-lg, fluid)
v-layout(row, wrap)
v-flex(xs3)
v-card.radius-7(light)
v-card-text
.d-flex
v-toolbar.radius-7(color='teal lighten-5', dense, flat, height='44')
.body-2.teal--text Blocks
v-list(two-line)
template(v-for='(item, idx) of blocks')
v-list-tile(@click='selectBlock(item)')
v-list-tile-avatar
v-avatar.radius-7(color='teal')
v-icon(dark) dashboard
v-list-tile-content
v-list-tile-title.body-2
{{
item
.
title
}}
v-list-tile-sub-title
{{
item
.
description
}}
v-list-tile-avatar(v-if='block.key === item.key')
v-icon.animated.fadeInLeft(color='teal') arrow_forward_ios
v-divider(v-if='idx < blocks.length - 1')
v-flex(xs3)
v-card.radius-7.animated.fadeInLeft(light, v-if='block.key')
v-card-text
v-toolbar.radius-7(color='teal lighten-5', dense, flat)
v-icon.mr-3(color='teal') dashboard
.body-2.teal--text
{{
block
.
title
}}
.d-flex.mt-3
v-toolbar.radius-7(flat, color='grey lighten-4', dense, height='44')
.body-2 Coming soon
v-btn.ml-3.my-0.mr-0.radius-7(color='teal', large, @click='', disabled)
v-icon(left) save_alt
span Insert
</
template
>
<
script
>
import
_
from
'lodash'
import
{
sync
}
from
'vuex-pathify'
export
default
{
props
:
{
value
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
blocks
:
[
{
key
:
'hero'
,
title
:
'Hero'
,
description
:
'A large banner with a title.'
},
{
key
:
'toc'
,
title
:
'Table of Contents'
,
description
:
'A list of children pages.'
}
// { key: 'form', title: 'Form', description: '' }
],
block
:
{
key
:
false
}
}
},
computed
:
{
isShown
:
{
get
()
{
return
this
.
value
},
set
(
val
)
{
this
.
$emit
(
'input'
,
val
)
}
},
activeModal
:
sync
(
'editor/activeModal'
)
},
methods
:
{
selectBlock
(
item
)
{
this
.
block
=
_
.
cloneDeep
(
item
)
}
}
}
</
script
>
<
style
lang=
'scss'
>
.editor-modal-blocks
{
position
:
fixed
;
top
:
112px
;
left
:
64px
;
z-index
:
10
;
width
:
calc
(
100vw
-
64px
-
17px
);
height
:
calc
(
100vh
-
112px
-
24px
);
background-color
:
rgba
(
darken
(
mc
(
'grey'
,
'900'
)
,
3%
)
,
.9
)
!
important
;
}
</
style
>
client/components/editor/editor-modal-media.vue
View file @
ca4e0ada
...
...
@@ -18,7 +18,7 @@
template(v-for='(item, idx) of [1,2,3,4,5,6,7,8,9,10]')
v-list-tile(@click='')
v-list-tile-avatar
v-avatar.radius-7(color='teal'
, tile
)
v-avatar.radius-7(color='teal')
v-icon(dark) image
v-list-tile-content
v-list-tile-title Image
{{
item
}}
...
...
server/app/data.yml
View file @
ca4e0ada
...
...
@@ -63,10 +63,21 @@ jobs:
schedule
:
P1D
groups
:
defaultPermissions
:
-
'
manage
:pages'
-
'
write
:assets'
-
'
read
:pages'
-
'
read
:assets'
-
'
read:comments'
-
'
write:comments'
defaultPageRules
:
-
id
:
default
deny
:
false
match
:
START
roles
:
-
'
read:pages'
-
'
read:assets'
-
'
read:comments'
-
'
write:comments'
path
:
'
'
locales
:
[]
telemetry
:
BUGSNAG_ID
:
'
bb4b324d0675bcbba10025617fd2cec8'
BUGSNAG_REMOTE
:
'
https://notify.bugsnag.com'
...
...
server/graph/resolvers/group.js
View file @
ca4e0ada
...
...
@@ -43,7 +43,7 @@ module.exports = {
const
group
=
await
WIKI
.
models
.
groups
.
query
().
insertAndFetch
({
name
:
args
.
name
,
permissions
:
JSON
.
stringify
(
WIKI
.
data
.
groups
.
defaultPermissions
),
pageRules
:
JSON
.
stringify
(
[]
),
pageRules
:
JSON
.
stringify
(
WIKI
.
data
.
groups
.
defaultPageRules
),
isSystem
:
false
})
await
WIKI
.
auth
.
reloadGroups
()
...
...
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