wiki-server 0.22.2 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/node.js.yml +2 -2
- package/lib/page.coffee +21 -4
- package/lib/search.coffee +8 -25
- package/lib/server.coffee +16 -8
- package/package.json +5 -5
- package/test/server.coffee +2 -2
- package/test/sitemap.coffee +1 -0
|
@@ -16,11 +16,11 @@ jobs:
|
|
|
16
16
|
|
|
17
17
|
strategy:
|
|
18
18
|
matrix:
|
|
19
|
-
node-version: [
|
|
19
|
+
node-version: [18.x, 20.x, 21.x]
|
|
20
20
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
21
21
|
|
|
22
22
|
steps:
|
|
23
|
-
- uses: actions/checkout@
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
24
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
25
|
uses: actions/setup-node@v3
|
|
26
26
|
with:
|
package/lib/page.coffee
CHANGED
|
@@ -87,6 +87,25 @@ module.exports = exports = (argv) ->
|
|
|
87
87
|
# Reads and writes are async, but serially queued to avoid race conditions.
|
|
88
88
|
queue = []
|
|
89
89
|
|
|
90
|
+
tryDefaults = (file, cb) ->
|
|
91
|
+
lastDefault = (cb) ->
|
|
92
|
+
defloc = path.join(argv.root, 'default-data', 'pages', file)
|
|
93
|
+
fs.exists defloc, (exists) ->
|
|
94
|
+
if exists
|
|
95
|
+
cb(defloc)
|
|
96
|
+
else
|
|
97
|
+
cb(null)
|
|
98
|
+
if argv.defaults
|
|
99
|
+
defloc = path.join(argv.data, '..', argv.defaults, 'pages', file)
|
|
100
|
+
console.log 'firstDefault', defloc
|
|
101
|
+
fs.exists defloc, (exists) ->
|
|
102
|
+
if exists
|
|
103
|
+
cb(defloc)
|
|
104
|
+
else
|
|
105
|
+
lastDefault(cb)
|
|
106
|
+
else
|
|
107
|
+
lastDefault(cb)
|
|
108
|
+
|
|
90
109
|
# Main file io function, when called without page it reads,
|
|
91
110
|
# when called with page it writes.
|
|
92
111
|
fileio = (action, file, page, cb) ->
|
|
@@ -175,12 +194,10 @@ module.exports = exports = (argv) ->
|
|
|
175
194
|
if exists
|
|
176
195
|
load_parse(loc, cb, {plugin: undefined})
|
|
177
196
|
else
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if exists
|
|
197
|
+
tryDefaults(file, (defloc) ->
|
|
198
|
+
if defloc
|
|
181
199
|
load_parse(defloc, cb)
|
|
182
200
|
else
|
|
183
|
-
|
|
184
201
|
glob "wiki-plugin-*/pages", {cwd: argv.packageDir}, (e, plugins) ->
|
|
185
202
|
if e then return cb(e)
|
|
186
203
|
|
package/lib/search.coffee
CHANGED
|
@@ -46,9 +46,6 @@ module.exports = exports = (argv) ->
|
|
|
46
46
|
|
|
47
47
|
searchPageUpdate = (slug, page, cb) ->
|
|
48
48
|
# to update we have to remove the page first, and then readd it
|
|
49
|
-
timeLabel = "SITE INDEX update #{slug} - #{wikiName}"
|
|
50
|
-
console.time timeLabel
|
|
51
|
-
|
|
52
49
|
try
|
|
53
50
|
pageText = page.story.reduce( extractPageText, '')
|
|
54
51
|
catch err
|
|
@@ -66,37 +63,29 @@ module.exports = exports = (argv) ->
|
|
|
66
63
|
'title': page.title
|
|
67
64
|
'content': pageText
|
|
68
65
|
}
|
|
69
|
-
console.timeEnd timeLabel
|
|
70
66
|
cb()
|
|
71
67
|
|
|
72
68
|
searchPageRemove = (slug, cb) ->
|
|
73
69
|
# remove page from index
|
|
74
70
|
timeLabel = "SITE INDEX page remove #{slug} - #{wikiName}"
|
|
75
|
-
console.time timeLabel
|
|
76
71
|
try
|
|
77
72
|
siteIndex.discard slug
|
|
78
73
|
catch err
|
|
79
74
|
# swallow error, if the page was not in index
|
|
80
75
|
console.log "removing #{slug} from index #{wikiName} failed", err unless err.message.includes('not in the index')
|
|
81
|
-
console.timeEnd timeLabel
|
|
82
76
|
cb()
|
|
83
77
|
|
|
84
78
|
searchSave = (siteIndex, cb) ->
|
|
85
79
|
# save index to file
|
|
86
|
-
timeLabel = "SITE INDEX #{wikiName} : Saved"
|
|
87
|
-
console.time timeLabel
|
|
88
|
-
|
|
89
80
|
fs.exists argv.status, (exists) ->
|
|
90
81
|
if exists
|
|
91
82
|
writeFileAtomic siteIndexLoc, JSON.stringify(siteIndex), (e) ->
|
|
92
|
-
console.timeEnd timeLabel
|
|
93
83
|
return cb(e) if e
|
|
94
84
|
touch indexUpdateFlag, (err) ->
|
|
95
85
|
cb()
|
|
96
86
|
else
|
|
97
87
|
mkdirp argv.status, ->
|
|
98
88
|
writeFileAtomic siteIndexLoc, JSON.stringify(siteIndex), (e) ->
|
|
99
|
-
console.timeEnd timeLabel
|
|
100
89
|
return cb(e) if e
|
|
101
90
|
touch indexUpdateFlag, (err) ->
|
|
102
91
|
cb()
|
|
@@ -104,8 +93,6 @@ module.exports = exports = (argv) ->
|
|
|
104
93
|
|
|
105
94
|
searchRestore = (cb) ->
|
|
106
95
|
# restore index, or create if it doesn't already exist
|
|
107
|
-
timeLabel = "SITE INDEX #{wikiName} : Restored"
|
|
108
|
-
console.time timeLabel
|
|
109
96
|
fs.exists siteIndexLoc, (exists) ->
|
|
110
97
|
if exists
|
|
111
98
|
fs.readFile(siteIndexLoc, (err, data) ->
|
|
@@ -115,7 +102,6 @@ module.exports = exports = (argv) ->
|
|
|
115
102
|
fields: ['title', 'content']
|
|
116
103
|
catch e
|
|
117
104
|
return cb(e)
|
|
118
|
-
console.timeEnd timeLabel
|
|
119
105
|
process.nextTick( ->
|
|
120
106
|
serial(queue.shift())))
|
|
121
107
|
|
|
@@ -150,19 +136,16 @@ module.exports = exports = (argv) ->
|
|
|
150
136
|
try
|
|
151
137
|
if currentItem.text?
|
|
152
138
|
switch currentItem.type
|
|
153
|
-
when 'paragraph'
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
pageText += ' ' + currentItem.text.replace /\[{2}|\[(?:[\S]+)|\]{1,2}|\\n/g, ' '
|
|
158
|
-
when 'html'
|
|
159
|
-
pageText += ' ' + currentItem.text.replace /<[^\>]*>?/g, ''
|
|
139
|
+
when 'paragraph', 'markdown', 'html', 'reference'
|
|
140
|
+
noLinks = currentItem.text.replace /\[{2}|\[(?:[\S]+)|\]{1,2}/g, ''
|
|
141
|
+
# strip out all tags.
|
|
142
|
+
pageText += noLinks.replace(/<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>/g, ' ')
|
|
160
143
|
else
|
|
161
144
|
if currentItem.text?
|
|
162
145
|
for line in currentItem.text.split /\r\n?|\n/
|
|
163
146
|
pageText += ' ' + line.replace /\[{2}|\[(?:[\S]+)|\]{1,2}/g, '' unless line.match /^[A-Z]+[ ].*/
|
|
164
147
|
catch err
|
|
165
|
-
throw new Error("Error extracting text from #{currentIndex}, #{err}")
|
|
148
|
+
throw new Error("Error extracting text from #{currentIndex}, #{err}, #{err.stack}")
|
|
166
149
|
pageText
|
|
167
150
|
|
|
168
151
|
|
|
@@ -192,8 +175,8 @@ module.exports = exports = (argv) ->
|
|
|
192
175
|
# we save the pagehandler, so we can recreate the site index if it is removed
|
|
193
176
|
searchPageHandler = pagehandler if !searchPageHandler?
|
|
194
177
|
|
|
195
|
-
timeLabel = "SITE INDEX #{wikiName} : Created"
|
|
196
|
-
console.time timeLabel
|
|
178
|
+
#timeLabel = "SITE INDEX #{wikiName} : Created"
|
|
179
|
+
#console.time timeLabel
|
|
197
180
|
|
|
198
181
|
pagehandler.slugs (e, slugs) ->
|
|
199
182
|
if e
|
|
@@ -227,7 +210,7 @@ module.exports = exports = (argv) ->
|
|
|
227
210
|
|
|
228
211
|
Promise.all(indexPromises)
|
|
229
212
|
.then () ->
|
|
230
|
-
console.timeEnd timeLabel
|
|
213
|
+
# console.timeEnd timeLabel
|
|
231
214
|
process.nextTick ( ->
|
|
232
215
|
serial(queue.shift()))
|
|
233
216
|
|
package/lib/server.coffee
CHANGED
|
@@ -33,7 +33,9 @@ glob = require 'glob'
|
|
|
33
33
|
async = require 'async'
|
|
34
34
|
f = require('flates')
|
|
35
35
|
sanitize = require '@mapbox/sanitize-caja'
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
# node-fetch is now ESM only
|
|
38
|
+
fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
|
|
37
39
|
|
|
38
40
|
# Express 4 middleware
|
|
39
41
|
logger = require 'morgan'
|
|
@@ -145,7 +147,7 @@ module.exports = exports = (argv) ->
|
|
|
145
147
|
# assume http, as we know no better at this point and we need to specify a protocol.
|
|
146
148
|
remoteURL = new URL("http://#{remote}/#{slug}.json").toString()
|
|
147
149
|
# set a two second timeout
|
|
148
|
-
fetch(remoteURL, {
|
|
150
|
+
fetch(remoteURL, {signal: AbortSignal.timeout(2000)})
|
|
149
151
|
.then (res) ->
|
|
150
152
|
if res.ok
|
|
151
153
|
return res
|
|
@@ -652,7 +654,7 @@ module.exports = exports = (argv) ->
|
|
|
652
654
|
if not page.journal
|
|
653
655
|
page.journal = []
|
|
654
656
|
if action.fork
|
|
655
|
-
page.journal.push({type: "fork", site: action.fork})
|
|
657
|
+
page.journal.push({type: "fork", site: action.fork, date: action.date - 1})
|
|
656
658
|
delete action.fork
|
|
657
659
|
page.journal.push(action)
|
|
658
660
|
pagehandler.put req.params[0], page, (e) ->
|
|
@@ -674,7 +676,13 @@ module.exports = exports = (argv) ->
|
|
|
674
676
|
pagehandler.saveToRecycler req.params[0], (err) ->
|
|
675
677
|
if err and err isnt 'page does not exist'
|
|
676
678
|
console.log "Error saving #{req.params[0]} before fork: #{err}"
|
|
677
|
-
|
|
679
|
+
if action.forkPage
|
|
680
|
+
forkPageCopy = JSON.parse(JSON.stringify(action.forkPage))
|
|
681
|
+
delete action.forkPage
|
|
682
|
+
actionCB(null, forkPageCopy)
|
|
683
|
+
else
|
|
684
|
+
# Legacy path, new clients will provide forkPage on implicit forks.
|
|
685
|
+
remoteGet(action.fork, req.params[0], actionCB)
|
|
678
686
|
else if action.type is 'create'
|
|
679
687
|
# Prevent attempt to write circular structure
|
|
680
688
|
itemCopy = JSON.parse(JSON.stringify(action.item))
|
|
@@ -688,10 +696,10 @@ module.exports = exports = (argv) ->
|
|
|
688
696
|
else if action.type == 'fork'
|
|
689
697
|
pagehandler.saveToRecycler req.params[0], (err) ->
|
|
690
698
|
if err then console.log "Error saving #{req.params[0]} before fork: #{err}"
|
|
691
|
-
if action.
|
|
692
|
-
|
|
693
|
-
delete action.
|
|
694
|
-
actionCB(null,
|
|
699
|
+
if action.forkPage # push
|
|
700
|
+
forkPageCopy = JSON.parse(JSON.stringify(action.forkPage))
|
|
701
|
+
delete action.forkPage
|
|
702
|
+
actionCB(null, forkPageCopy)
|
|
695
703
|
else # pull
|
|
696
704
|
remoteGet(action.site, req.params[0], actionCB)
|
|
697
705
|
else
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wiki-server",
|
|
3
3
|
"description": "A Federated Wiki Server",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.24.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ward Cunningham",
|
|
7
7
|
"email": "ward@c2.com",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"cookie-parser": "^1.4.4",
|
|
29
29
|
"errorhandler": "^1.5.1",
|
|
30
30
|
"express": "^4.17.1",
|
|
31
|
-
"express-hbs": "^2.
|
|
31
|
+
"express-hbs": "^2.5.0",
|
|
32
32
|
"flates": "0.0.5",
|
|
33
33
|
"glob": "^7.2.3",
|
|
34
34
|
"lodash": "^4.17.19",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"minisearch": "^6.0.1",
|
|
37
37
|
"mkdirp": "^0.5.6",
|
|
38
38
|
"morgan": "^1.9.1",
|
|
39
|
-
"node-fetch": "^
|
|
39
|
+
"node-fetch": "^3.3.2",
|
|
40
40
|
"write-file-atomic": "^5.0.0",
|
|
41
41
|
"xml2js": "^0.5.0"
|
|
42
42
|
},
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
"mocha": "^10.2.0",
|
|
52
52
|
"should": "^13.2.3",
|
|
53
53
|
"supertest": "^6.3.3",
|
|
54
|
-
"wiki-client": "^0.
|
|
54
|
+
"wiki-client": "^0.29.0",
|
|
55
55
|
"wiki-plugin-activity": "^0.5.0",
|
|
56
56
|
"wiki-plugin-video": "^0.3.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
|
-
"node": ">=
|
|
59
|
+
"node": ">=18.x"
|
|
60
60
|
},
|
|
61
61
|
"testling": {
|
|
62
62
|
"harness": "mocha"
|
package/test/server.coffee
CHANGED
|
@@ -4,7 +4,7 @@ server = require '..'
|
|
|
4
4
|
path = require 'path'
|
|
5
5
|
random = require '../lib/random_id'
|
|
6
6
|
testid = random()
|
|
7
|
-
argv = require('../lib/defaultargs.coffee')({data: path.join('/tmp', 'sfwtests', testid), packageDir: path.join(__dirname, '..', 'node_modules'), port:
|
|
7
|
+
argv = require('../lib/defaultargs.coffee')({data: path.join('/tmp', 'sfwtests', testid), packageDir: path.join(__dirname, '..', 'node_modules'), port: 55557, security_legacy: true})
|
|
8
8
|
|
|
9
9
|
describe 'server', ->
|
|
10
10
|
app = {}
|
|
@@ -21,7 +21,7 @@ describe 'server', ->
|
|
|
21
21
|
))
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
request = request('http://localhost:
|
|
24
|
+
request = request('http://localhost:55557')
|
|
25
25
|
|
|
26
26
|
# location of the test page
|
|
27
27
|
loc = path.join('/tmp', 'sfwtests', testid, 'pages', 'adsf-test-page')
|
package/test/sitemap.coffee
CHANGED
|
@@ -19,6 +19,7 @@ describe 'sitemap', ->
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
request = request('http://localhost:55556')
|
|
22
|
+
fs.mkdirSync path.join('/tmp', 'sfwtests', testid, 'pages'), {recursive: true}
|
|
22
23
|
|
|
23
24
|
# location of the sitemap
|
|
24
25
|
sitemapLoc = path.join('/tmp', 'sfwtests', testid, 'status', 'sitemap.json')
|