vis-chronicle 1.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vis-chronicle",
3
- "version": "1.3.5",
3
+ "version": "1.4.5",
4
4
  "description": "Generates JSON for populating a vis.js timeline from Wikidata queries.",
5
5
  "keywords": [
6
6
  "wikidata",
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('./index.js');
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()
@@ -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,6 +26,54 @@ function durationToWikidataPrecision(duration)
24
26
  else return 9
25
27
  }
26
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)
37
+ {
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
+
27
77
  /**
28
78
  * Breaks down a relative date path into its components.
29
79
  * @param {*} dateString
@@ -31,7 +81,7 @@ function durationToWikidataPrecision(duration)
31
81
  */
32
82
  function breakRelativeDate(dateString)
33
83
  {
34
- if (dateString == '') return null
84
+ if (!dateString) return null
35
85
 
36
86
  // parse out relative date components
37
87
  var match = dateString.match(wikidata.pathQueryRegex)
@@ -59,8 +109,81 @@ function breakRelativeDate(dateString)
59
109
  return dateComponents
60
110
  }
61
111
 
62
- // Flattens a relative date string into a hard date string
63
- function flattenRelativeDate(wikidataCache, dateString)
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
+ }
169
+ }
170
+ else
171
+ {
172
+ if (flatMoment && flatMoment.value)
173
+ {
174
+ flatMoment.value = flatMoment.value.format('YYYYYY-MM-DDThh:mm:ss')
175
+ }
176
+ return flatMoment
177
+ }
178
+ }
179
+
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)
64
187
  {
65
188
  var parsedPath = breakRelativeDate(dateString)
66
189
  if (!parsedPath)
@@ -153,16 +276,15 @@ function flattenRelativeDate(wikidataCache, dateString)
153
276
 
154
277
  //console.log(`${component} (${precision}): ${momentDate}`)
155
278
  }
156
- return {
157
- value: momentDate.format('YYYYYY-MM-DDThh:mm:ss'),
158
- precision: precision
159
- }
279
+ return { value: momentDate, precision: precision }
160
280
  }
161
281
  else
162
282
  {
163
- return {...cacheEntry}
283
+ const cachedOut = {...cacheEntry}
284
+ if (cachedOut.value) cachedOut.value = moment(cachedOut.value)
285
+ return cachedOut
164
286
  }
165
287
  }
166
288
  }
167
289
 
168
- module.exports = { breakRelativeDate, flattenRelativeDate }
290
+ module.exports = { breakRelativeDate, flattenRelativeDate, rangeUnion, rangeUnionAdv }
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")
@@ -489,6 +490,15 @@ const wikidata = module.exports = {
489
490
  return result;
490
491
  },
491
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
+
492
502
  /**
493
503
  * Runs an unsorted list of path queries.
494
504
  */
@@ -555,7 +565,7 @@ const wikidata = module.exports = {
555
565
  for (const binding of data.results.bindings)
556
566
  {
557
567
  const key = this.extractQidFromUrl(binding['item'].value)
558
- 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 }
559
569
  foundKeys.add(key)
560
570
  }
561
571
 
@@ -598,7 +608,7 @@ const wikidata = module.exports = {
598
608
  const qid = this.extractQidFromUrl(binding['item'].value)
599
609
  const pid = this.extractQidFromUrl(binding['p'].value)
600
610
  const key = `${qid}:${pid}`
601
- 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 }
602
612
  foundKeys.add(key)
603
613
  }
604
614
 
@@ -618,6 +628,25 @@ const wikidata = module.exports = {
618
628
  for (const wdProp of queries)
619
629
  {
620
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
+ }
621
650
  }
622
651
  if (qualsToQuery.length > 0)
623
652
  {
@@ -644,7 +673,7 @@ const wikidata = module.exports = {
644
673
  const valId = this.extractQidFromUrl(binding['value'].value)
645
674
  const qualId = this.extractQidFromUrl(binding['q'].value)
646
675
  const key = `${itemId}:${propId}:${valId}:${qualId}`
647
- 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 }
648
677
  foundKeys.add(key)
649
678
  }
650
679