vis-chronicle 1.2.5 → 1.4.5
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/README.md +0 -2
- package/package.json +1 -1
- package/src/fetch.js +11 -39
- package/src/index.js +1 -1
- package/src/relativeDates.js +165 -34
- package/src/render.js +6 -1
- package/src/wikidata.js +71 -34
package/README.md
CHANGED
|
@@ -95,8 +95,6 @@ Item properties:
|
|
|
95
95
|
* `general`: General query segment, usually for selecting the item and property.
|
|
96
96
|
* `start`: Query segment for selecting the start value.
|
|
97
97
|
* `end`: Query segment for selecting the end value.
|
|
98
|
-
* `startPath`: Another way of writing Wikidata queries. TODO.
|
|
99
|
-
* `endPath`: See `startPath`
|
|
100
98
|
* `expectedDuration`: Describes the expected duration, for hinting if the start or end is missing.
|
|
101
99
|
* `min`: The absolute minimum duration.
|
|
102
100
|
* `max`: The absolute maximum duration.
|
package/package.json
CHANGED
package/src/fetch.js
CHANGED
|
@@ -37,12 +37,11 @@ if (!outputFile)
|
|
|
37
37
|
|
|
38
38
|
var metadataOutputFile = values["out-metadata"]
|
|
39
39
|
|
|
40
|
-
const moment = require('moment')
|
|
41
40
|
const fs = require('fs');
|
|
42
41
|
const wikidata = require('./wikidata.js')
|
|
43
42
|
const renderer = require('./render.js')
|
|
44
43
|
const mypath = require("./mypath.js");
|
|
45
|
-
const { flattenRelativeDate } = require('./
|
|
44
|
+
const { flattenRelativeDate, rangeUnion, rangeUnionAdv } = require('./relativeDates.js');
|
|
46
45
|
const wikidataToRange2 = require('./wikidataToRange.js')
|
|
47
46
|
|
|
48
47
|
function wikidataToRange(param)
|
|
@@ -57,40 +56,6 @@ wikidata.verboseLogging = values["verbose"]
|
|
|
57
56
|
wikidata.setLang(values["lang"])
|
|
58
57
|
wikidata.initialize()
|
|
59
58
|
|
|
60
|
-
function rangeUnionAdv(value, min, max)
|
|
61
|
-
{
|
|
62
|
-
var aggregate = {}
|
|
63
|
-
if (min)
|
|
64
|
-
{
|
|
65
|
-
assert(min.min)
|
|
66
|
-
aggregate.min = min.min
|
|
67
|
-
}
|
|
68
|
-
else if (value && value.min)
|
|
69
|
-
{
|
|
70
|
-
aggregate.min = value.min
|
|
71
|
-
}
|
|
72
|
-
if (max)
|
|
73
|
-
{
|
|
74
|
-
assert(max.max)
|
|
75
|
-
aggregate.max = max.max
|
|
76
|
-
}
|
|
77
|
-
else if (value && value.max)
|
|
78
|
-
{
|
|
79
|
-
aggregate.max = value.max
|
|
80
|
-
}
|
|
81
|
-
return aggregate
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function rangeUnion(a, b)
|
|
85
|
-
{
|
|
86
|
-
if (!a) return b
|
|
87
|
-
if (!b) return a
|
|
88
|
-
return {
|
|
89
|
-
min: a.min && b.min ? moment.min(a.min, b.min) : a.min || b.min,
|
|
90
|
-
max: a.max && b.max ? moment.max(a.max, b.max) : a.max || b.max
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
59
|
async function entryPoint() {}
|
|
95
60
|
|
|
96
61
|
entryPoint()
|
|
@@ -112,7 +77,6 @@ entryPoint()
|
|
|
112
77
|
var templateItem = wikidata.inputSpec.items[i]
|
|
113
78
|
if (templateItem.itemQuery || templateItem.items)
|
|
114
79
|
{
|
|
115
|
-
//TODO: caching for item queries
|
|
116
80
|
wikidata.inputSpec.items.splice(i, 1)
|
|
117
81
|
const newItems = await wikidata.createTemplateItems(templateItem)
|
|
118
82
|
for (const newItem of newItems)
|
|
@@ -200,8 +164,16 @@ entryPoint()
|
|
|
200
164
|
{
|
|
201
165
|
if (item.finished) continue
|
|
202
166
|
|
|
203
|
-
if (item.startPath)
|
|
204
|
-
|
|
167
|
+
if (item.startPath)
|
|
168
|
+
{
|
|
169
|
+
item.startPath = wikidata.replaceQueryWildcards(item.startPath, item)
|
|
170
|
+
pathQueries.push(item.startPath)
|
|
171
|
+
}
|
|
172
|
+
if (item.endPath)
|
|
173
|
+
{
|
|
174
|
+
item.endPath = wikidata.replaceQueryWildcards(item.endPath, item)
|
|
175
|
+
pathQueries.push(item.endPath)
|
|
176
|
+
}
|
|
205
177
|
|
|
206
178
|
// the bundle key is the queries, as well as any wildcard parameters
|
|
207
179
|
const keyObject = {}
|
package/src/index.js
CHANGED
package/src/relativeDates.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
const moment = require('moment')
|
|
3
3
|
const { toJewishDate, toGregorianDate, getIndexByJewishMonth } = require("jewish-date");
|
|
4
4
|
const wikidata = require('./wikidata');
|
|
5
|
+
const wikidataToRange = require('./wikidataToRange');
|
|
6
|
+
const assert = require("node:assert/strict")
|
|
5
7
|
|
|
6
8
|
function momentToHDate(inMoment)
|
|
7
9
|
{
|
|
@@ -24,54 +26,182 @@ function durationToWikidataPrecision(duration)
|
|
|
24
26
|
else return 9
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Combines three {min, max} objects into a range containing all of them.
|
|
31
|
+
* @param {*} value Is overridden by min.min and max.max if they are present.
|
|
32
|
+
* @param {*} min
|
|
33
|
+
* @param {*} max
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
function rangeUnionAdv(value, min, max)
|
|
29
37
|
{
|
|
30
|
-
|
|
38
|
+
var aggregate = {}
|
|
39
|
+
if (min)
|
|
40
|
+
{
|
|
41
|
+
assert(min.min)
|
|
42
|
+
aggregate.min = min.min
|
|
43
|
+
}
|
|
44
|
+
else if (value && value.min)
|
|
45
|
+
{
|
|
46
|
+
aggregate.min = value.min
|
|
47
|
+
}
|
|
48
|
+
if (max)
|
|
49
|
+
{
|
|
50
|
+
assert(max.max)
|
|
51
|
+
aggregate.max = max.max
|
|
52
|
+
}
|
|
53
|
+
else if (value && value.max)
|
|
54
|
+
{
|
|
55
|
+
aggregate.max = value.max
|
|
56
|
+
}
|
|
57
|
+
return aggregate
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Combines two {min, max} objects into a range containing both of them.
|
|
62
|
+
* @param {*} a
|
|
63
|
+
* @param {*} b
|
|
64
|
+
* @returns
|
|
65
|
+
*/
|
|
66
|
+
function rangeUnion(a, b)
|
|
67
|
+
{
|
|
68
|
+
if (!a) return b
|
|
69
|
+
if (!b) return a
|
|
70
|
+
return {
|
|
71
|
+
min: a.min && b.min ? moment.min(a.min, b.min) : a.min || b.min,
|
|
72
|
+
max: a.max && b.max ? moment.max(a.max, b.max) : a.max || b.max
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Breaks down a relative date path into its components.
|
|
79
|
+
* @param {*} dateString
|
|
80
|
+
* @returns An array of strings, or null.
|
|
81
|
+
*/
|
|
82
|
+
function breakRelativeDate(dateString)
|
|
83
|
+
{
|
|
84
|
+
if (!dateString) return null
|
|
31
85
|
|
|
32
86
|
// parse out relative date components
|
|
33
|
-
var relSplit
|
|
34
87
|
var match = dateString.match(wikidata.pathQueryRegex)
|
|
35
|
-
if (match)
|
|
88
|
+
if (!match)
|
|
36
89
|
{
|
|
37
|
-
|
|
90
|
+
console.error(`Failed to parse relative date '${dateString}'.`)
|
|
91
|
+
return null
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const dateComponents = [ match[1] ]
|
|
95
|
+
var opStartIndex = 0
|
|
96
|
+
const operatorString = match[2]
|
|
97
|
+
if (operatorString.length > 0)
|
|
98
|
+
{
|
|
99
|
+
for (var i = 1; i < operatorString.length; i++)
|
|
100
|
+
{
|
|
101
|
+
if (operatorString[i] == '+' || operatorString[i] == '>')
|
|
102
|
+
{
|
|
103
|
+
dateComponents.push(operatorString.substring(opStartIndex, i))
|
|
104
|
+
opStartIndex = i
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
dateComponents.push(operatorString.substring(opStartIndex, i))
|
|
108
|
+
}
|
|
109
|
+
return dateComponents
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Flattens a relative date path string into a hard date.
|
|
114
|
+
* @param {*} wikidataCache
|
|
115
|
+
* @param {*} dateString
|
|
116
|
+
* @param {*} params { returnRange:BOOL }. Result will be a range { min:STRING, max:STRING } instead.
|
|
117
|
+
* @returns An object like { value:STRING, precision:INT }, or null
|
|
118
|
+
*/
|
|
119
|
+
function flattenRelativeDate(wikidataCache, dateString, params)
|
|
120
|
+
{
|
|
121
|
+
var flatMoment = flattenRelativeDateToMoment(wikidataCache, dateString)
|
|
122
|
+
|
|
123
|
+
// if allowed and necessary, produce a range instead of a single value
|
|
124
|
+
if (params?.returnRange)
|
|
125
|
+
{
|
|
126
|
+
var parsedPath = breakRelativeDate(dateString)
|
|
127
|
+
if (!parsedPath) return { value: null }
|
|
128
|
+
|
|
129
|
+
const basePath = parsedPath[0]
|
|
130
|
+
const wdpk = basePath.substring(0, basePath.lastIndexOf(':'))
|
|
131
|
+
const qual = basePath.substring(basePath.lastIndexOf(':') + 1)
|
|
132
|
+
var minQuery
|
|
133
|
+
var maxQuery
|
|
134
|
+
switch (qual)
|
|
135
|
+
{
|
|
136
|
+
case "P580":
|
|
137
|
+
{
|
|
138
|
+
minQuery = `${wdpk}:P1319` // earliest date
|
|
139
|
+
maxQuery = `${wdpk}:P8555` // latest start date
|
|
140
|
+
break
|
|
141
|
+
}
|
|
142
|
+
case "P582":
|
|
143
|
+
{
|
|
144
|
+
minQuery = `${wdpk}:P8554` // earliest end date
|
|
145
|
+
maxQuery = `${wdpk}:P1326` // latest date
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (minQuery && maxQuery)
|
|
150
|
+
{
|
|
151
|
+
const minMoment = flattenRelativeDateToMoment(wikidataCache, minQuery + parsedPath.slice(1).join(''))
|
|
152
|
+
const maxMoment = flattenRelativeDateToMoment(wikidataCache, maxQuery + parsedPath.slice(1).join(''))
|
|
153
|
+
const value = wikidataToRange(flatMoment)
|
|
154
|
+
const minRange = wikidataToRange(minMoment)
|
|
155
|
+
const maxRange = wikidataToRange(maxMoment)
|
|
156
|
+
const aggregateRange = rangeUnionAdv(value, minRange, maxRange)
|
|
157
|
+
return {
|
|
158
|
+
min: aggregateRange.min ? aggregateRange.min.format('YYYYYY-MM-DDThh:mm:ss') : null,
|
|
159
|
+
max: aggregateRange.max ? aggregateRange.max.format('YYYYYY-MM-DDThh:mm:ss') : null
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else
|
|
163
|
+
{
|
|
164
|
+
const flatRange = wikidataToRange(flatMoment)
|
|
165
|
+
return flatRange
|
|
166
|
+
? { min: flatRange.min.format('YYYYYY-MM-DDThh:mm:ss'), max: flatRange.max.format('YYYYYY-MM-DDThh:mm:ss') }
|
|
167
|
+
: { value: null }
|
|
168
|
+
}
|
|
38
169
|
}
|
|
39
170
|
else
|
|
40
171
|
{
|
|
41
|
-
|
|
42
|
-
|
|
172
|
+
if (flatMoment && flatMoment.value)
|
|
173
|
+
{
|
|
174
|
+
flatMoment.value = flatMoment.value.format('YYYYYY-MM-DDThh:mm:ss')
|
|
175
|
+
}
|
|
176
|
+
return flatMoment
|
|
43
177
|
}
|
|
178
|
+
}
|
|
44
179
|
|
|
45
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Flattens a relative date path string into a moment.
|
|
182
|
+
* @param {*} wikidataCache
|
|
183
|
+
* @param {*} dateString
|
|
184
|
+
* @returns An object like { value:MOMENT, precision:INT }, or null
|
|
185
|
+
*/
|
|
186
|
+
function flattenRelativeDateToMoment(wikidataCache, dateString)
|
|
187
|
+
{
|
|
188
|
+
var parsedPath = breakRelativeDate(dateString)
|
|
189
|
+
if (!parsedPath)
|
|
46
190
|
{
|
|
47
191
|
return null
|
|
48
192
|
}
|
|
49
|
-
else if (!wikidataCache[
|
|
193
|
+
else if (!wikidataCache[parsedPath[0]])
|
|
50
194
|
{
|
|
51
|
-
console.error(`Date for '${
|
|
195
|
+
console.error(`Date for '${parsedPath[0]}' wasn't cached.`)
|
|
52
196
|
return null
|
|
53
197
|
}
|
|
54
198
|
else
|
|
55
199
|
{
|
|
56
|
-
const cacheEntry = wikidataCache[
|
|
57
|
-
if (cacheEntry.value &&
|
|
200
|
+
const cacheEntry = wikidataCache[parsedPath[0]]
|
|
201
|
+
if (cacheEntry.value && parsedPath.length > 1)
|
|
58
202
|
{
|
|
59
203
|
// break up operators
|
|
60
|
-
const dateOperators =
|
|
61
|
-
var opStartIndex = 0
|
|
62
|
-
const operatorString = relSplit[1]
|
|
63
|
-
if (operatorString.length > 0)
|
|
64
|
-
{
|
|
65
|
-
for (var i = 1; i < operatorString.length; i++)
|
|
66
|
-
{
|
|
67
|
-
if (operatorString[i] == '+' || operatorString[i] == '>')
|
|
68
|
-
{
|
|
69
|
-
dateOperators.push(operatorString.substring(opStartIndex, i))
|
|
70
|
-
opStartIndex = i
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
dateOperators.push(operatorString.substring(opStartIndex, i))
|
|
74
|
-
}
|
|
204
|
+
const dateOperators = parsedPath.slice(1)
|
|
75
205
|
|
|
76
206
|
// handle relative segments of date
|
|
77
207
|
// About precision:
|
|
@@ -146,14 +276,15 @@ module.exports = function flattenRelativeDate(wikidataCache, dateString)
|
|
|
146
276
|
|
|
147
277
|
//console.log(`${component} (${precision}): ${momentDate}`)
|
|
148
278
|
}
|
|
149
|
-
return {
|
|
150
|
-
value: momentDate.format('YYYYYY-MM-DDThh:mm:ss'),
|
|
151
|
-
precision: precision
|
|
152
|
-
}
|
|
279
|
+
return { value: momentDate, precision: precision }
|
|
153
280
|
}
|
|
154
281
|
else
|
|
155
282
|
{
|
|
156
|
-
|
|
283
|
+
const cachedOut = {...cacheEntry}
|
|
284
|
+
if (cachedOut.value) cachedOut.value = moment(cachedOut.value)
|
|
285
|
+
return cachedOut
|
|
157
286
|
}
|
|
158
287
|
}
|
|
159
|
-
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
module.exports = { breakRelativeDate, flattenRelativeDate, rangeUnion, rangeUnionAdv }
|
package/src/render.js
CHANGED
|
@@ -461,7 +461,12 @@ renderer.produceOutput = function(inputSpec, items)
|
|
|
461
461
|
{
|
|
462
462
|
const labelItem = {...outputItem}
|
|
463
463
|
labelItem.id += "-label"
|
|
464
|
-
|
|
464
|
+
|
|
465
|
+
var classes = labelItem.className.split(' ')
|
|
466
|
+
classes = classes.filter(c => c != "visc-left-connection" && c != "visc-right-connection")
|
|
467
|
+
classes.push("visc-toplabel")
|
|
468
|
+
labelItem.className = classes.join(' ')
|
|
469
|
+
|
|
465
470
|
outputObject.items.push(labelItem)
|
|
466
471
|
outputItem.content = outputItem.content ? " " : ""
|
|
467
472
|
}
|
package/src/wikidata.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const mypath = require("./mypath.js")
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const nodepath = require('node:path');
|
|
5
|
+
const moment = require('moment')
|
|
5
6
|
const globalData = require("./global-data.json")
|
|
6
7
|
const assert = require('node:assert/strict')
|
|
7
8
|
const SparqlBuilder = require("./sparql-builder.js")
|
|
@@ -12,9 +13,9 @@ const wikidata = module.exports = {
|
|
|
12
13
|
verboseLogging: false,
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
+
* Caches results for SPARQL queries, using the query string as the key.
|
|
16
17
|
*/
|
|
17
|
-
|
|
18
|
+
queryCache: {},
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Caches results for path queries, using the path as the key.
|
|
@@ -25,9 +26,9 @@ const wikidata = module.exports = {
|
|
|
25
26
|
cacheBuster: undefined,
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
* Relative path to the
|
|
29
|
+
* Relative path to the query cache file.
|
|
29
30
|
*/
|
|
30
|
-
|
|
31
|
+
queryCacheFile: "intermediate/sparql-query-cache.json",
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Relative path to the path cache file.
|
|
@@ -126,8 +127,8 @@ const wikidata = module.exports = {
|
|
|
126
127
|
{
|
|
127
128
|
try
|
|
128
129
|
{
|
|
129
|
-
const contents = await fs.promises.readFile(this.
|
|
130
|
-
this.
|
|
130
|
+
const contents = await fs.promises.readFile(this.queryCacheFile)
|
|
131
|
+
this.queryCache = JSON.parse(contents)
|
|
131
132
|
}
|
|
132
133
|
catch
|
|
133
134
|
{
|
|
@@ -147,11 +148,11 @@ const wikidata = module.exports = {
|
|
|
147
148
|
|
|
148
149
|
writeCache: async function()
|
|
149
150
|
{
|
|
150
|
-
await mypath.ensureDirectoryForFile(this.
|
|
151
|
+
await mypath.ensureDirectoryForFile(this.queryCacheFile)
|
|
151
152
|
|
|
152
|
-
fs.writeFile(this.
|
|
153
|
+
fs.writeFile(this.queryCacheFile, JSON.stringify(this.queryCache), err => {
|
|
153
154
|
if (err) {
|
|
154
|
-
console.error(`Error writing wikidata
|
|
155
|
+
console.error(`Error writing wikidata query cache:`)
|
|
155
156
|
console.error(err)
|
|
156
157
|
}
|
|
157
158
|
})
|
|
@@ -184,25 +185,32 @@ const wikidata = module.exports = {
|
|
|
184
185
|
}
|
|
185
186
|
},
|
|
186
187
|
|
|
187
|
-
|
|
188
|
+
replaceQueryWildcards: function(term, item, itemPrefix = "")
|
|
188
189
|
{
|
|
189
|
-
if (!term)
|
|
190
|
-
{
|
|
191
|
-
return term;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
190
|
// replace query wildcards
|
|
195
191
|
for (const key in item)
|
|
196
192
|
{
|
|
197
193
|
var insertValue = item[key]
|
|
198
194
|
if (typeof insertValue === "string" && insertValue.startsWith("Q"))
|
|
199
|
-
insertValue =
|
|
195
|
+
insertValue = itemPrefix + insertValue
|
|
200
196
|
term = term.replaceAll(`{${key}}`, insertValue)
|
|
201
197
|
}
|
|
202
198
|
|
|
203
199
|
// detect unreplaced wildcards
|
|
204
200
|
//TODO:
|
|
205
201
|
|
|
202
|
+
return term
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
preprocessQueryTerm: function(context, term, item)
|
|
206
|
+
{
|
|
207
|
+
if (!term)
|
|
208
|
+
{
|
|
209
|
+
return term
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
term = this.replaceQueryWildcards(term, item, "wd:")
|
|
213
|
+
|
|
206
214
|
// terminate term
|
|
207
215
|
if (!term.trim().endsWith("."))
|
|
208
216
|
{
|
|
@@ -238,7 +246,7 @@ const wikidata = module.exports = {
|
|
|
238
246
|
|
|
239
247
|
//TODO: validate query has required wildcards
|
|
240
248
|
|
|
241
|
-
queryTerm = this.
|
|
249
|
+
queryTerm = this.preprocessQueryTerm(inQueryTerm, queryTerm, item)
|
|
242
250
|
return queryTerm
|
|
243
251
|
},
|
|
244
252
|
|
|
@@ -275,7 +283,7 @@ const wikidata = module.exports = {
|
|
|
275
283
|
if (typeof queryTerm === 'string' || queryTerm instanceof String)
|
|
276
284
|
{
|
|
277
285
|
return {
|
|
278
|
-
value: this.
|
|
286
|
+
value: this.preprocessQueryTerm(inQueryTerm, queryTerm, item),
|
|
279
287
|
min: "?_prop pqv:P1319 ?_min_value.",
|
|
280
288
|
max: "?_prop pqv:P1326 ?_max_value."
|
|
281
289
|
}
|
|
@@ -285,7 +293,7 @@ const wikidata = module.exports = {
|
|
|
285
293
|
const result = {}
|
|
286
294
|
for (const key in queryTerm)
|
|
287
295
|
{
|
|
288
|
-
result[key] = this.
|
|
296
|
+
result[key] = this.preprocessQueryTerm(inQueryTerm, queryTerm[key], item)
|
|
289
297
|
}
|
|
290
298
|
return result
|
|
291
299
|
}
|
|
@@ -393,15 +401,7 @@ const wikidata = module.exports = {
|
|
|
393
401
|
queryBuilder.addOptionalQueryTerm(`${propVar} wikibase:rank ${rankVar}.`)
|
|
394
402
|
|
|
395
403
|
const query = queryBuilder.build()
|
|
396
|
-
|
|
397
|
-
// read cache
|
|
398
|
-
const cacheKey = query
|
|
399
|
-
if (!this.skipCache && !item.skipCache && this.cache[cacheKey])
|
|
400
|
-
{
|
|
401
|
-
return this.cache[cacheKey]
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const data = await this.runQuery(query)
|
|
404
|
+
const data = await this.runQuery(query, item.skipCache)
|
|
405
405
|
console.log(`\tQuery for ${item.id} returned ${data.results.bindings.length} results.`)
|
|
406
406
|
|
|
407
407
|
const readBinding = function(binding)
|
|
@@ -487,10 +487,18 @@ const wikidata = module.exports = {
|
|
|
487
487
|
}
|
|
488
488
|
}
|
|
489
489
|
|
|
490
|
-
this.cache[cacheKey] = result;
|
|
491
490
|
return result;
|
|
492
491
|
},
|
|
493
492
|
|
|
493
|
+
/**
|
|
494
|
+
* Formats the provided Wikidata date string as ISO 8601 with a six-digit year.
|
|
495
|
+
*/
|
|
496
|
+
normalizeWikidataDate: function(dateStr)
|
|
497
|
+
{
|
|
498
|
+
const date = moment(dateStr, 'Y-MM-DDThh:mm:ss')
|
|
499
|
+
return date.format('YYYYYY-MM-DDThh:mm:ss')
|
|
500
|
+
},
|
|
501
|
+
|
|
494
502
|
/**
|
|
495
503
|
* Runs an unsorted list of path queries.
|
|
496
504
|
*/
|
|
@@ -557,7 +565,7 @@ const wikidata = module.exports = {
|
|
|
557
565
|
for (const binding of data.results.bindings)
|
|
558
566
|
{
|
|
559
567
|
const key = this.extractQidFromUrl(binding['item'].value)
|
|
560
|
-
this.pathCache[key] = { value: binding['date'].value, precision: binding['precision'].value }
|
|
568
|
+
this.pathCache[key] = { value: this.normalizeWikidataDate(binding['date'].value), precision: binding['precision'].value }
|
|
561
569
|
foundKeys.add(key)
|
|
562
570
|
}
|
|
563
571
|
|
|
@@ -600,7 +608,7 @@ const wikidata = module.exports = {
|
|
|
600
608
|
const qid = this.extractQidFromUrl(binding['item'].value)
|
|
601
609
|
const pid = this.extractQidFromUrl(binding['p'].value)
|
|
602
610
|
const key = `${qid}:${pid}`
|
|
603
|
-
this.pathCache[key] = { value: binding['date'].value, precision: binding['precision'].value }
|
|
611
|
+
this.pathCache[key] = { value: this.normalizeWikidataDate(binding['date'].value), precision: binding['precision'].value }
|
|
604
612
|
foundKeys.add(key)
|
|
605
613
|
}
|
|
606
614
|
|
|
@@ -620,6 +628,25 @@ const wikidata = module.exports = {
|
|
|
620
628
|
for (const wdProp of queries)
|
|
621
629
|
{
|
|
622
630
|
if (!this.pathCache[wdProp]) qualsToQuery.push(wdProp)
|
|
631
|
+
|
|
632
|
+
// grab corresponding min/max props as well
|
|
633
|
+
const split = wdProp.split(':')
|
|
634
|
+
const wdpk = split.slice(0, 3).join(':')
|
|
635
|
+
switch (split[3])
|
|
636
|
+
{
|
|
637
|
+
case "P580":
|
|
638
|
+
query = `${wdpk}:P1319` // earliest date
|
|
639
|
+
if (!this.pathCache[query]) qualsToQuery.push(query)
|
|
640
|
+
query = `${wdpk}:P8555` // latest start date
|
|
641
|
+
if (!this.pathCache[query]) qualsToQuery.push(query)
|
|
642
|
+
break;
|
|
643
|
+
case "P582":
|
|
644
|
+
query = `${wdpk}:P8554` // earliest end date
|
|
645
|
+
if (!this.pathCache[query]) qualsToQuery.push(query)
|
|
646
|
+
query = `${wdpk}:P1326` // latest date
|
|
647
|
+
if (!this.pathCache[query]) qualsToQuery.push(query)
|
|
648
|
+
break;
|
|
649
|
+
}
|
|
623
650
|
}
|
|
624
651
|
if (qualsToQuery.length > 0)
|
|
625
652
|
{
|
|
@@ -646,7 +673,7 @@ const wikidata = module.exports = {
|
|
|
646
673
|
const valId = this.extractQidFromUrl(binding['value'].value)
|
|
647
674
|
const qualId = this.extractQidFromUrl(binding['q'].value)
|
|
648
675
|
const key = `${itemId}:${propId}:${valId}:${qualId}`
|
|
649
|
-
this.pathCache[key] = { value: binding['date'].value, precision: binding['precision'].value }
|
|
676
|
+
this.pathCache[key] = { value: this.normalizeWikidataDate(binding['date'].value), precision: binding['precision'].value }
|
|
650
677
|
foundKeys.add(key)
|
|
651
678
|
}
|
|
652
679
|
|
|
@@ -695,7 +722,11 @@ const wikidata = module.exports = {
|
|
|
695
722
|
queryBuilder.addWikibaseLabel(this.lang)
|
|
696
723
|
|
|
697
724
|
const query = queryBuilder.build()
|
|
698
|
-
const data = await this.runQuery(query)
|
|
725
|
+
const data = await this.runQuery(query, templateItem.skipCache)
|
|
726
|
+
if (!data)
|
|
727
|
+
{
|
|
728
|
+
throw 'No response data from Wikidata query.'
|
|
729
|
+
}
|
|
699
730
|
|
|
700
731
|
const newItems = []
|
|
701
732
|
|
|
@@ -723,8 +754,13 @@ const wikidata = module.exports = {
|
|
|
723
754
|
},
|
|
724
755
|
|
|
725
756
|
// runs a SPARQL query
|
|
726
|
-
runQuery: async function(query)
|
|
757
|
+
runQuery: async function(query, skipCache = false)
|
|
727
758
|
{
|
|
759
|
+
if (!skipCache && !this.skipCache && this.queryCache[query])
|
|
760
|
+
{
|
|
761
|
+
return this.queryCache[query]
|
|
762
|
+
}
|
|
763
|
+
|
|
728
764
|
if (this.verboseLogging) console.log(query)
|
|
729
765
|
|
|
730
766
|
assert(this.options)
|
|
@@ -739,6 +775,7 @@ const wikidata = module.exports = {
|
|
|
739
775
|
else
|
|
740
776
|
{
|
|
741
777
|
const data = await response.json()
|
|
778
|
+
this.queryCache[query] = data
|
|
742
779
|
return data
|
|
743
780
|
}
|
|
744
781
|
}
|