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
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 @@
single-line,
solo
flat
rounded
hide-details,
prepend-inner-icon='mdi-magnify',
:loading='searchIsLoading',
...
...
client/components/tags.vue
View file @
efab00fa
...
...
@@ -21,6 +21,7 @@
.overline.mr-3.animated.fadeInLeft Current Selection
v-chip.mr-3.primary--text(
v-for='tag of tagsSelected'
:key='`tagSelected-` + tag.tag'
color='white'
close
@click:close='toggleTag(tag.tag)'
...
...
@@ -38,7 +39,7 @@
template(v-else)
v-icon.mr-3.animated.fadeInRight mdi-arrow-left
.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(
label='Search within results...'
solo
...
...
@@ -50,12 +51,29 @@
prepend-icon='mdi-file-document-box-search-outline'
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)
.overline Order By
v-select.ml-2(
:items='orderByItems'
v-model='orderBy'
background-color='white
'
:background-color='$vuetify.theme.dark ? `grey darken-3` : `white`
'
hide-details
label='Order By'
rounded
...
...
@@ -64,12 +82,13 @@
height='40'
style='max-width: 250px;'
)
v-divider.mx-3(vertical)
v-btn-toggle(v-model='displayStyle', rounded, mandatory)
v-btn(text, height='40'): v-icon(small) mdi-view-list
v-btn(text, height='40'): v-icon(small) mdi-cards-variant
v-btn(text, height='40'): v-icon(small) mdi-format-align-justify
v-btn-toggle.ml-2(v-model='orderByDirection', rounded, mandatory)
v-btn(text, height='40'): v-icon(size='20') mdi-chevron-double-up
v-btn(text, height='40'): v-icon(size='20') mdi-chevron-double-down
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
notify
search-results
...
...
@@ -77,16 +96,25 @@
<
script
>
import
{
get
}
from
'vuex-pathify'
import
VueRouter
from
'vue-router'
import
_
from
'lodash'
import
tagsQuery
from
'gql/common/common-pages-query-tags.gql'
/* global siteLangs */
const
router
=
new
VueRouter
({
mode
:
'history'
,
base
:
'/t'
})
export
default
{
data
()
{
return
{
tags
:
[],
selection
:
[],
displayStyle
:
0
,
locale
:
'any'
,
locales
:
[],
orderBy
:
'TITLE'
,
orderByItems
:
[
{
text
:
'Creation Date'
,
value
:
'CREATED'
},
...
...
@@ -95,6 +123,7 @@ export default {
{
text
:
'Path'
,
value
:
'PATH'
},
{
text
:
'Title'
,
value
:
'TITLE'
}
],
orderByDirection
:
0
,
scrollStyle
:
{
vuescroll
:
{},
scrollPanel
:
{
...
...
@@ -127,8 +156,27 @@ export default {
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
()
{
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
:
{
toggleTag
(
tag
)
{
...
...
@@ -137,9 +185,25 @@ export default {
}
else
{
this
.
selection
.
push
(
tag
)
}
this
.
rebuildURL
()
},
isSelected
(
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
:
{
...
...
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 @@
}
@at-root
.theme--dark
&
{
// background-color: darken(mc('grey', '900'), 4%);
color
:
mc
(
'grey'
,
'300'
);
}
// ---------------------------------
// LINKS
// ---------------------------------
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 = {
name
:
_
.
get
(
c
,
'name'
,
'Anonymous'
)
||
''
,
profile
:
_
.
get
(
c
,
'profile'
,
''
),
tier
:
_
.
toLower
(
_
.
get
(
c
,
'tier'
,
'backers'
)),
totalDonated
:
_
.
get
(
c
,
'totalAmountDonated'
,
0
),
totalDonated
:
Math
.
ceil
(
_
.
get
(
c
,
'totalAmountDonated'
,
0
)
),
twitter
:
_
.
get
(
c
,
'twitter'
,
''
)
||
''
,
website
:
_
.
get
(
c
,
'website'
,
''
)
||
''
}))
...
...
server/jobs/render-page.js
View file @
efab00fa
...
...
@@ -8,6 +8,8 @@ module.exports = async (pageId) => {
try
{
WIKI
.
models
=
require
(
'../core/db'
).
init
()
await
WIKI
.
configSvc
.
loadFromDb
()
await
WIKI
.
configSvc
.
applyFlags
()
const
page
=
await
WIKI
.
models
.
pages
.
getPageFromDb
(
pageId
)
if
(
!
page
)
{
...
...
server/modules/rendering/html-core/renderer.js
View file @
efab00fa
const
_
=
require
(
'lodash'
)
const
cheerio
=
require
(
'cheerio'
)
/* global WIKI */
module
.
exports
=
{
async
render
()
{
const
$
=
cheerio
.
load
(
this
.
input
)
...
...
@@ -14,6 +16,98 @@ module.exports = {
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>'
,
''
)
}
}
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