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
efab00fa
You need to sign in or sign up before continuing.
Commit
efab00fa
authored
Sep 02, 2019
by
Nick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: content link states
parent
e491af44
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
203 additions
and
11 deletions
+203
-11
nav-header.vue
client/components/common/nav-header.vue
+1
-0
tags.vue
client/components/tags.vue
+72
-8
icon-price-tag.svg
client/static/svg/icon-price-tag.svg
+2
-0
app.scss
client/themes/default/scss/app.scss
+31
-2
contribute.js
server/graph/resolvers/contribute.js
+1
-1
render-page.js
server/jobs/render-page.js
+2
-0
renderer.js
server/modules/rendering/html-core/renderer.js
+94
-0
No files found.
client/components/common/nav-header.vue
View file @
efab00fa
...
@@ -71,6 +71,7 @@
...
@@ -71,6 +71,7 @@
single-line,
single-line,
solo
solo
flat
flat
rounded
hide-details,
hide-details,
prepend-inner-icon='mdi-magnify',
prepend-inner-icon='mdi-magnify',
:loading='searchIsLoading',
:loading='searchIsLoading',
...
...
client/components/tags.vue
View file @
efab00fa
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
.overline.mr-3.animated.fadeInLeft Current Selection
.overline.mr-3.animated.fadeInLeft Current Selection
v-chip.mr-3.primary--text(
v-chip.mr-3.primary--text(
v-for='tag of tagsSelected'
v-for='tag of tagsSelected'
:key='`tagSelected-` + tag.tag'
color='white'
color='white'
close
close
@click:close='toggleTag(tag.tag)'
@click:close='toggleTag(tag.tag)'
...
@@ -38,7 +39,7 @@
...
@@ -38,7 +39,7 @@
template(v-else)
template(v-else)
v-icon.mr-3.animated.fadeInRight mdi-arrow-left
v-icon.mr-3.animated.fadeInRight mdi-arrow-left
.overline.animated.fadeInRight Select one or more tags
.overline.animated.fadeInRight Select one or more tags
v-toolbar(
color='grey lighten-4
', flat, height='58')
v-toolbar(
:color='$vuetify.theme.dark ? `grey darken-4-l5` : `grey lighten-4`
', flat, height='58')
v-text-field.tags-search(
v-text-field.tags-search(
label='Search within results...'
label='Search within results...'
solo
solo
...
@@ -50,12 +51,29 @@
...
@@ -50,12 +51,29 @@
prepend-icon='mdi-file-document-box-search-outline'
prepend-icon='mdi-file-document-box-search-outline'
append-icon='mdi-arrow-right'
append-icon='mdi-arrow-right'
)
)
template(v-if='locales.length > 1')
v-divider.mx-3(vertical)
.overline Locale
v-select.ml-2(
:items='locales'
v-model='locale'
:background-color='$vuetify.theme.dark ? `grey darken-3` : `white`'
hide-details
label='Locale'
item-text='name'
item-value='code'
rounded
single-line
dense
height='40'
style='max-width: 170px;'
)
v-divider.mx-3(vertical)
v-divider.mx-3(vertical)
.overline Order By
.overline Order By
v-select.ml-2(
v-select.ml-2(
:items='orderByItems'
:items='orderByItems'
v-model='orderBy'
v-model='orderBy'
background-color='white
'
:background-color='$vuetify.theme.dark ? `grey darken-3` : `white`
'
hide-details
hide-details
label='Order By'
label='Order By'
rounded
rounded
...
@@ -64,12 +82,13 @@
...
@@ -64,12 +82,13 @@
height='40'
height='40'
style='max-width: 250px;'
style='max-width: 250px;'
)
)
v-divider.mx-3(vertical)
v-btn-toggle.ml-2(v-model='orderByDirection', rounded, mandatory)
v-btn-toggle(v-model='displayStyle', rounded, mandatory)
v-btn(text, height='40'): v-icon(size='20') mdi-chevron-double-up
v-btn(text, height='40'): v-icon(small) mdi-view-list
v-btn(text, height='40'): v-icon(size='20') mdi-chevron-double-down
v-btn(text, height='40'): v-icon(small) mdi-cards-variant
v-btn(text, height='40'): v-icon(small) mdi-format-align-justify
v-divider
v-divider
.text-center.pt-10
img(src='/svg/icon-price-tag.svg')
.subtitle-2.grey--text Select one or more tags on the left.
nav-footer
nav-footer
notify
notify
search-results
search-results
...
@@ -77,16 +96,25 @@
...
@@ -77,16 +96,25 @@
<
script
>
<
script
>
import
{
get
}
from
'vuex-pathify'
import
{
get
}
from
'vuex-pathify'
import
VueRouter
from
'vue-router'
import
_
from
'lodash'
import
_
from
'lodash'
import
tagsQuery
from
'gql/common/common-pages-query-tags.gql'
import
tagsQuery
from
'gql/common/common-pages-query-tags.gql'
/* global siteLangs */
const
router
=
new
VueRouter
({
mode
:
'history'
,
base
:
'/t'
})
export
default
{
export
default
{
data
()
{
data
()
{
return
{
return
{
tags
:
[],
tags
:
[],
selection
:
[],
selection
:
[],
displayStyle
:
0
,
locale
:
'any'
,
locales
:
[],
orderBy
:
'TITLE'
,
orderBy
:
'TITLE'
,
orderByItems
:
[
orderByItems
:
[
{
text
:
'Creation Date'
,
value
:
'CREATED'
},
{
text
:
'Creation Date'
,
value
:
'CREATED'
},
...
@@ -95,6 +123,7 @@ export default {
...
@@ -95,6 +123,7 @@ export default {
{
text
:
'Path'
,
value
:
'PATH'
},
{
text
:
'Path'
,
value
:
'PATH'
},
{
text
:
'Title'
,
value
:
'TITLE'
}
{
text
:
'Title'
,
value
:
'TITLE'
}
],
],
orderByDirection
:
0
,
scrollStyle
:
{
scrollStyle
:
{
vuescroll
:
{},
vuescroll
:
{},
scrollPanel
:
{
scrollPanel
:
{
...
@@ -127,8 +156,27 @@ export default {
...
@@ -127,8 +156,27 @@ export default {
return
_
.
filter
(
this
.
tags
,
t
=>
_
.
includes
(
this
.
selection
,
t
.
tag
))
return
_
.
filter
(
this
.
tags
,
t
=>
_
.
includes
(
this
.
selection
,
t
.
tag
))
}
}
},
},
watch
:
{
locale
(
newValue
,
oldValue
)
{
this
.
rebuildURL
()
},
orderBy
(
newValue
,
oldValue
)
{
this
.
rebuildURL
()
},
orderByDirection
(
newValue
,
oldValue
)
{
this
.
rebuildURL
()
}
},
router
,
created
()
{
created
()
{
this
.
$store
.
commit
(
'page/SET_MODE'
,
'tags'
)
this
.
$store
.
commit
(
'page/SET_MODE'
,
'tags'
)
this
.
locales
=
_
.
concat
(
[{
name
:
'Any'
,
code
:
'any'
}],
(
siteLangs
.
length
>
0
?
siteLangs
:
[])
)
this
.
selection
=
_
.
compact
(
this
.
$route
.
path
.
split
(
'/'
))
},
},
methods
:
{
methods
:
{
toggleTag
(
tag
)
{
toggleTag
(
tag
)
{
...
@@ -137,9 +185,25 @@ export default {
...
@@ -137,9 +185,25 @@ export default {
}
else
{
}
else
{
this
.
selection
.
push
(
tag
)
this
.
selection
.
push
(
tag
)
}
}
this
.
rebuildURL
()
},
},
isSelected
(
tag
)
{
isSelected
(
tag
)
{
return
_
.
includes
(
this
.
selection
,
tag
)
return
_
.
includes
(
this
.
selection
,
tag
)
},
rebuildURL
()
{
let
urlObj
=
{
path
:
'/'
+
this
.
selection
.
join
(
'/'
)
}
if
(
this
.
locale
!==
`any`
)
{
_
.
set
(
urlObj
,
'query.lang'
,
this
.
locale
)
}
if
(
this
.
orderBy
!==
`TITLE`
)
{
_
.
set
(
urlObj
,
'query.sort'
,
this
.
orderBy
.
toLowerCase
())
}
if
(
this
.
orderByDirection
!==
0
)
{
_
.
set
(
urlObj
,
'query.dir'
,
this
.
orderByDirection
===
0
?
`asc`
:
`desc`
)
}
this
.
$router
.
push
(
urlObj
)
}
}
},
},
apollo
:
{
apollo
:
{
...
...
client/static/svg/icon-price-tag.svg
0 → 100644
View file @
efab00fa
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 128 128"
width=
"256"
height=
"256"
><path
fill=
"#f7f7fb"
d=
"M43.5,28L16.9,45.4c-5,2.3-2.3,9.1,0,14.1l17.9,17.9l62.2,23l17-47L43.5,28 M35.3,59.5 c-3.9-1.4-5.9-5.7-4.5-9.6c1.4-3.9,5.7-5.9,9.6-4.5s5.9,5.7,4.5,9.6C43.5,58.9,39.2,61,35.3,59.5"
/><path
fill=
"#dfdfe3"
d=
"M30.353,52.448c0-0.846,0.144-1.706,0.446-2.548c1.098-3.057,3.977-4.946,7.048-4.946 c0.847,0,1.709,0.144,2.552,0.446l0,0c3.065,1.1,4.957,3.993,4.946,7.074C45.349,53.317,45.206,54.17,44.9,55l0,0 c-1.091,3.04-3.945,4.986-6.997,4.986c-0.864,0-1.743-0.156-2.603-0.486C32.242,58.402,30.352,55.521,30.353,52.448 M43.5,28 L16.9,45.4c-2.078,0.956-2.826,2.689-2.825,4.746c0,2.894,1.481,6.431,2.825,9.354l17.9,17.9l21.635,8H102.4l11.6-32L43.5,28"
/><path
fill=
"#454b54"
d=
"M97,103.5c-0.4,0-0.7-0.1-1-0.2l-62.2-23c-0.4-0.2-0.8-0.4-1.1-0.7L14.8,61.7 c-0.6-0.6-0.9-1.3-0.9-2.1V45.4c0-1,0.5-2,1.4-2.5l26.6-17.5c0.8-0.5,1.8-0.6,2.7-0.3l70.5,25.5c0.7,0.3,1.4,0.8,1.7,1.5 s0.4,1.5,0.1,2.3l-17,47c-0.3,0.8-0.8,1.4-1.6,1.7C97.9,103.4,97.4,103.5,97,103.5z M36.5,74.9l58.7,21.7l15-41.4l-66.3-24L19.9,47 v11.3L36.5,74.9z"
/><path
fill=
"#6ec7b0"
d=
"M34.8,27.5L16.9,45.4c-3.9,3.9-3.9,10.2,0,14.1l17.9,17.9h75v-50h-75V27.5z M37.8,60 c-4.1,0-7.5-3.4-7.5-7.5s3.4-7.5,7.5-7.5s7.5,3.4,7.5,7.5S42,60,37.8,60z"
/><path
fill=
"#454b54"
d=
"M109.8,80.5h-75c-0.8,0-1.6-0.3-2.1-0.9L14.8,61.7C12.3,59.2,11,56,11,52.5s1.4-6.7,3.8-9.2 l17.9-17.9c0.6-0.6,1.3-0.9,2.1-0.9h75c1.7,0,3,1.3,3,3v50C112.8,79.2,111.5,80.5,109.8,80.5z M36.1,74.5h70.8v-44H36.1L19,47.5 c-1.3,1.3-2,3.1-2,5s0.7,3.6,2,4.9L36.1,74.5z"
/><path
fill=
"#fff"
d=
"M89.8 50.5h-25c-1.7 0-3-1.3-3-3s1.3-3 3-3h25c1.7 0 3 1.3 3 3S91.5 50.5 89.8 50.5zM89.8 60.5h-25c-1.7 0-3-1.3-3-3s1.3-3 3-3h25c1.7 0 3 1.3 3 3S91.5 60.5 89.8 60.5z"
/><path
fill=
"#454b54"
d=
"M7.8,85.5c-0.8,0-1.5-0.3-2.1-0.9c-1.2-1.2-1.2-3.1,0-4.2l9.1-9.1c1.2-1.2,3.1-1.2,4.2,0 c1.2,1.2,1.2,3.1,0,4.2l-9.1,9.1C9.4,85.2,8.6,85.5,7.8,85.5z"
/></svg>
\ No newline at end of file
client/themes/default/scss/app.scss
View file @
efab00fa
...
@@ -10,11 +10,40 @@
...
@@ -10,11 +10,40 @@
}
}
@at-root
.theme--dark
&
{
@at-root
.theme--dark
&
{
// background-color: darken(mc('grey', '900'), 4%);
color
:
mc
(
'grey'
,
'300'
);
color
:
mc
(
'grey'
,
'300'
);
}
// ---------------------------------
// LINKS
// ---------------------------------
a
{
a
{
color
:
mc
(
'blue'
,
'100'
);
color
:
mc
(
'blue'
,
'700'
);
&
.is-internal-link.is-invalid-page
{
color
:
mc
(
'red'
,
'700'
);
@at-root
.theme--dark
&
{
color
:
mc
(
'red'
,
'200'
);
}
}
&
.is-external-link
{
padding-right
:
3px
;
&
:
:
after
{
font-family
:
'Material Design Icons'
;
font-size
:
24px
/
1
;
padding-left
:
3px
;
display
:
inline-block
;
content
:
'\F3CC'
;
color
:
mc
(
'grey'
,
'500'
);
text-decoration
:
none
;
}
}
@at-root
.theme--dark
&
{
color
:
mc
(
'blue'
,
'200'
);
}
}
}
}
...
...
server/graph/resolvers/contribute.js
View file @
efab00fa
...
@@ -22,7 +22,7 @@ module.exports = {
...
@@ -22,7 +22,7 @@ module.exports = {
name
:
_
.
get
(
c
,
'name'
,
'Anonymous'
)
||
''
,
name
:
_
.
get
(
c
,
'name'
,
'Anonymous'
)
||
''
,
profile
:
_
.
get
(
c
,
'profile'
,
''
),
profile
:
_
.
get
(
c
,
'profile'
,
''
),
tier
:
_
.
toLower
(
_
.
get
(
c
,
'tier'
,
'backers'
)),
tier
:
_
.
toLower
(
_
.
get
(
c
,
'tier'
,
'backers'
)),
totalDonated
:
_
.
get
(
c
,
'totalAmountDonated'
,
0
),
totalDonated
:
Math
.
ceil
(
_
.
get
(
c
,
'totalAmountDonated'
,
0
)
),
twitter
:
_
.
get
(
c
,
'twitter'
,
''
)
||
''
,
twitter
:
_
.
get
(
c
,
'twitter'
,
''
)
||
''
,
website
:
_
.
get
(
c
,
'website'
,
''
)
||
''
website
:
_
.
get
(
c
,
'website'
,
''
)
||
''
}))
}))
...
...
server/jobs/render-page.js
View file @
efab00fa
...
@@ -8,6 +8,8 @@ module.exports = async (pageId) => {
...
@@ -8,6 +8,8 @@ module.exports = async (pageId) => {
try
{
try
{
WIKI
.
models
=
require
(
'../core/db'
).
init
()
WIKI
.
models
=
require
(
'../core/db'
).
init
()
await
WIKI
.
configSvc
.
loadFromDb
()
await
WIKI
.
configSvc
.
applyFlags
()
const
page
=
await
WIKI
.
models
.
pages
.
getPageFromDb
(
pageId
)
const
page
=
await
WIKI
.
models
.
pages
.
getPageFromDb
(
pageId
)
if
(
!
page
)
{
if
(
!
page
)
{
...
...
server/modules/rendering/html-core/renderer.js
View file @
efab00fa
const
_
=
require
(
'lodash'
)
const
_
=
require
(
'lodash'
)
const
cheerio
=
require
(
'cheerio'
)
const
cheerio
=
require
(
'cheerio'
)
/* global WIKI */
module
.
exports
=
{
module
.
exports
=
{
async
render
()
{
async
render
()
{
const
$
=
cheerio
.
load
(
this
.
input
)
const
$
=
cheerio
.
load
(
this
.
input
)
...
@@ -14,6 +16,98 @@ module.exports = {
...
@@ -14,6 +16,98 @@ module.exports = {
renderer
.
init
(
$
,
child
.
config
)
renderer
.
init
(
$
,
child
.
config
)
}
}
// --------------------------------
// Detect internal / external links
// --------------------------------
let
internalRefs
=
[]
const
reservedPrefixes
=
/^
\/[
a-z
]\/
/gi
const
isHostSet
=
WIKI
.
config
.
host
.
length
>
7
&&
WIKI
.
config
.
host
!==
'http://'
if
(
!
isHostSet
)
{
WIKI
.
logger
.
warn
(
'Host is not set. You must set the Site Host under General in the Administration Area!'
)
}
$
(
'a'
).
each
((
i
,
elm
)
=>
{
let
href
=
$
(
elm
).
attr
(
'href'
)
// -> Ignore empty links
if
(
!
href
||
href
.
length
<
1
)
{
return
}
// -> Strip host from local links
if
(
isHostSet
&&
href
.
indexOf
(
WIKI
.
config
.
site
.
host
)
===
0
)
{
href
=
href
.
replace
(
WIKI
.
config
.
site
.
host
,
''
)
}
// -> Assign local / external tag
if
(
href
.
indexOf
(
'://'
)
<
0
)
{
// -> Remove trailing slash
if
(
_
.
endsWith
(
'/'
))
{
href
=
href
.
slice
(
0
,
-
1
)
}
// -> Check for system prefix
if
(
!
reservedPrefixes
.
test
(
href
))
{
$
(
elm
).
addClass
(
`is-internal-link`
)
// -> Reformat paths
if
(
href
.
indexOf
(
'/'
)
!==
0
)
{
href
=
`/
${
this
.
page
.
localeCode
}
/
${
this
.
page
.
path
}
/
${
href
}
`
}
else
if
(
href
.
charAt
(
3
)
!==
'/'
)
{
href
=
`/
${
this
.
page
.
localeCode
}${
href
}
`
}
// -> Save internal references
internalRefs
.
push
({
localeCode
:
href
.
substring
(
1
,
3
),
path
:
_
.
head
(
href
.
substring
(
4
).
split
(
'#'
))
})
}
else
{
$
(
elm
).
addClass
(
`is-system-link`
)
}
}
else
{
$
(
elm
).
addClass
(
`is-external-link`
)
}
// -> Update element
$
(
elm
).
attr
(
'href'
,
href
)
})
// --------------------------------
// Detect internal link states
// --------------------------------
if
(
internalRefs
.
length
>
0
)
{
// -> Find matching pages
const
results
=
await
WIKI
.
models
.
pages
.
query
().
column
(
'path'
,
'localeCode'
).
where
(
builder
=>
{
internalRefs
.
forEach
((
ref
,
idx
)
=>
{
if
(
idx
<
1
)
{
builder
.
where
(
ref
)
}
else
{
builder
.
orWhere
(
ref
)
}
})
})
// -> Apply tag to internal links for found pages
$
(
'a.is-internal-link'
).
each
((
i
,
elm
)
=>
{
const
href
=
$
(
elm
).
attr
(
'href'
)
const
hrefObj
=
{
localeCode
:
href
.
substring
(
1
,
3
),
path
:
_
.
head
(
href
.
substring
(
4
).
split
(
'#'
))
}
if
(
_
.
some
(
results
,
r
=>
{
return
r
.
localeCode
===
hrefObj
.
localeCode
&&
r
.
path
===
hrefObj
.
path
}))
{
$
(
elm
).
addClass
(
`is-valid-page`
)
}
else
{
$
(
elm
).
addClass
(
`is-invalid-page`
)
}
})
}
return
$
.
html
(
'body'
).
replace
(
'<body>'
,
''
).
replace
(
'</body>'
,
''
)
return
$
.
html
(
'body'
).
replace
(
'<body>'
,
''
).
replace
(
'</body>'
,
''
)
}
}
}
}
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