@harvard-lts/mirador-eda-plugin 0.1.1
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/pull_request_template.md +31 -0
- package/.github/workflows/publish-package.yml +34 -0
- package/.nvmrc +1 -0
- package/.parcelrc +9 -0
- package/.travis.yml +16 -0
- package/CONTRIBUTING.md +20 -0
- package/LICENSE +201 -0
- package/README.md +175 -0
- package/__mocks__/fileMock.js +1 -0
- package/babel.config.json +11 -0
- package/demo/data/manifest-3037.json +524 -0
- package/demo/data/manifest-5f3b.json +315 -0
- package/demo/data/manifest-609.json +500 -0
- package/demo/data/ms_am_1118_3_142_0001.jpg +0 -0
- package/demo/data/ms_am_1118_3_142_0002.jpg +0 -0
- package/demo/data/ms_am_1118_3_142_0003.jpg +0 -0
- package/demo/demoEntry.js +21 -0
- package/demo/index.html +23 -0
- package/dist/es/index.js +535 -0
- package/jest.config.js +23 -0
- package/nwb.config.js +20 -0
- package/package.json +73 -0
- package/rollup.config.mjs +12 -0
- package/setupTests.js +1 -0
- package/src/index.js +10 -0
- package/src/plugins/EdaSideBarButtonsWrapper.js +51 -0
- package/src/plugins/EdaTranscriptionButton.js +19 -0
- package/src/plugins/EdaTranscriptionPanel.js +245 -0
- package/src/plugins/__tests__/EdaSideBarButtonsWrapper.spec.js +183 -0
- package/src/plugins/__tests__/EdaTranscriptionButton.spec.js +17 -0
- package/src/plugins/__tests__/EdaTranscriptionPanel.spec.js +188 -0
- package/src/plugins/__tests__/edaManifest.spec.js +110 -0
- package/src/plugins/__tests__/nonEdaManifest.spec.js +64 -0
- package/src/plugins/__tests__/transcriptionUtils.spec.js +430 -0
- package/src/plugins/testFixtures/combinedEditionsTranscriptions.js +62 -0
- package/src/plugins/testFixtures/franklinVariorum1998Transcription.js +85 -0
- package/src/plugins/testFixtures/johnsonPoems1955Transcription.js +88 -0
- package/src/plugins/transcriptionUtils.js +114 -0
- package/src/plugins/utils/suppressWarnings.js +41 -0
- package/webpack.config.cjs +56 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract the edition name from a transcription HTML string
|
|
3
|
+
* @param {string} html
|
|
4
|
+
* @returns {string} "Unknown Edition" if no name is found
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const getEditionName = (html) => {
|
|
8
|
+
const parser = new DOMParser()
|
|
9
|
+
const doc = parser.parseFromString(html, "text/html")
|
|
10
|
+
const workBody = doc.querySelector(".work-body")
|
|
11
|
+
return workBody?.dataset?.edition || "Unknown Edition"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Returns an array of EDA transcriptions from the manifest
|
|
16
|
+
* Transcriptions with the same edition name will be combined into a single transcription
|
|
17
|
+
* @param {Object} state
|
|
18
|
+
* @param {string} windowId
|
|
19
|
+
* @returns {array} - empty if EDA no transcriptions exist
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export const getEdaTranscription = (state, windowId) => {
|
|
23
|
+
const windows = state?.windows || {}
|
|
24
|
+
|
|
25
|
+
let targetWindow
|
|
26
|
+
if (windowId && windows[windowId]) {
|
|
27
|
+
targetWindow = windows[windowId]
|
|
28
|
+
} else {
|
|
29
|
+
const windowIds = Object.keys(windows)
|
|
30
|
+
targetWindow = windowIds.length > 0 ? windows[windowIds[0]] : null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const canvasId = targetWindow?.canvasId
|
|
34
|
+
const manifestId = targetWindow?.manifestId
|
|
35
|
+
const manifest = manifestId ? state.manifests[manifestId] : null
|
|
36
|
+
if (!manifest?.json || !canvasId) {
|
|
37
|
+
return []
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const canvas = manifest.json.items?.find(item => item.id === canvasId)
|
|
41
|
+
if (!canvas?.annotations) {
|
|
42
|
+
return []
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const allTranscriptions = canvas.annotations
|
|
46
|
+
.flatMap(page => page.items || [])
|
|
47
|
+
.filter(annotation => {
|
|
48
|
+
if (annotation?.body?.format !== "text/html") return false
|
|
49
|
+
|
|
50
|
+
const value = annotation?.body?.value
|
|
51
|
+
if (!value) return false
|
|
52
|
+
|
|
53
|
+
return value.includes('data-exhibit="emily-dickinson-archive"')
|
|
54
|
+
})
|
|
55
|
+
.map(annotation => annotation.body.value)
|
|
56
|
+
|
|
57
|
+
// Group transcriptions by edition name
|
|
58
|
+
const transcriptionsByEdition = allTranscriptions.reduce((acc, html) => {
|
|
59
|
+
const editionName = getEditionName(html)
|
|
60
|
+
if (!acc[editionName]) {
|
|
61
|
+
acc[editionName] = []
|
|
62
|
+
}
|
|
63
|
+
acc[editionName].push(html)
|
|
64
|
+
return acc
|
|
65
|
+
}, {})
|
|
66
|
+
|
|
67
|
+
// Combine HTML for editions with multiple transcriptions
|
|
68
|
+
const combinedTranscriptions = Object.entries(transcriptionsByEdition).map(([editionName, htmlArray]) => {
|
|
69
|
+
if (htmlArray.length === 1) {
|
|
70
|
+
return htmlArray[0]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const parser = new DOMParser()
|
|
74
|
+
const firstDoc = parser.parseFromString(htmlArray[0], "text/html")
|
|
75
|
+
const firstWorkBody = firstDoc.querySelector(".work-body")
|
|
76
|
+
const combinedDoc = parser.parseFromString('<div class="work-body"></div>', "text/html")
|
|
77
|
+
const combinedWorkBody = combinedDoc.querySelector(".work-body")
|
|
78
|
+
|
|
79
|
+
if (firstWorkBody.dataset.edition) {
|
|
80
|
+
combinedWorkBody.dataset.edition = firstWorkBody.dataset.edition
|
|
81
|
+
}
|
|
82
|
+
if (firstWorkBody.dataset.exhibit) {
|
|
83
|
+
combinedWorkBody.dataset.exhibit = firstWorkBody.dataset.exhibit
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
htmlArray.forEach(html => {
|
|
87
|
+
const doc = parser.parseFromString(html, "text/html")
|
|
88
|
+
const workBody = doc.querySelector(".work-body")
|
|
89
|
+
|
|
90
|
+
const title = workBody.querySelector("h3")
|
|
91
|
+
const stanzas = workBody.querySelectorAll(".stanza")
|
|
92
|
+
|
|
93
|
+
if (title) {
|
|
94
|
+
const titleClone = title.cloneNode(true)
|
|
95
|
+
combinedWorkBody.appendChild(titleClone)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
stanzas.forEach(stanza => {
|
|
99
|
+
const clone = stanza.cloneNode(true)
|
|
100
|
+
combinedWorkBody.appendChild(clone)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
if (html !== htmlArray[htmlArray.length - 1]) {
|
|
104
|
+
const spacer = combinedDoc.createElement("div")
|
|
105
|
+
spacer.style.height = "2em"
|
|
106
|
+
combinedWorkBody.appendChild(spacer)
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
return combinedWorkBody.outerHTML
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
return combinedTranscriptions
|
|
114
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { version as miradorVersion } from "mirador/package.json"
|
|
2
|
+
|
|
3
|
+
// In Mirador version 3x there is a deprecation console warning:
|
|
4
|
+
// Warning: Failed prop type: Material-UI: `overlap="rectangle"` was deprecated. Use `overlap="rectangular"` instead.
|
|
5
|
+
// This was fixed in Mirador version 4.0.0
|
|
6
|
+
// https://github.com/ProjectMirador/mirador/commit/90e695e0df5df44174a023cfae367a76e5697760
|
|
7
|
+
|
|
8
|
+
// Suppressing this error to improve developer experience
|
|
9
|
+
|
|
10
|
+
const FIXED_VERSION = "4.0.0"
|
|
11
|
+
|
|
12
|
+
const parsedCurrentVersion = parseInt(miradorVersion.replace(/\./g, ""))
|
|
13
|
+
const parsedFixedVersion = parseInt(FIXED_VERSION.replace(/\./g, ""))
|
|
14
|
+
|
|
15
|
+
// Once the version is greater than or equal to the fixed version, we can remove this suppression
|
|
16
|
+
if (parsedCurrentVersion >= parsedFixedVersion) {
|
|
17
|
+
console.log(
|
|
18
|
+
"⚠️ Warning suppression for Material-UI Badge overlap prop may no longer be needed.\n" +
|
|
19
|
+
" Current Mirador version: " + miradorVersion + "\n" +
|
|
20
|
+
" Fixed in version: " + FIXED_VERSION + "\n" +
|
|
21
|
+
" Consider removing src/plugins/utils/suppressWarnings.js"
|
|
22
|
+
)
|
|
23
|
+
} else {
|
|
24
|
+
const originalConsoleError = console.error
|
|
25
|
+
|
|
26
|
+
console.error = (...args) => {
|
|
27
|
+
const suppressedWarnings = [
|
|
28
|
+
"Material-UI: `overlap=\"rectangle\"` was deprecated. Use `overlap=\"rectangular\"` instead.",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const shouldSuppress = suppressedWarnings.some(warning =>
|
|
32
|
+
args[0]?.includes && args[0].includes(warning)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
if (!shouldSuppress) {
|
|
36
|
+
originalConsoleError.apply(console, args)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const webpack = require("webpack");
|
|
3
|
+
|
|
4
|
+
module.exports = (env, options) => {
|
|
5
|
+
return {
|
|
6
|
+
mode: options.mode,
|
|
7
|
+
entry: "./demo/demoEntry.js",
|
|
8
|
+
output: {
|
|
9
|
+
path: path.resolve(__dirname, "demo", "dist"),
|
|
10
|
+
filename: "demo.js",
|
|
11
|
+
publicPath: "/",
|
|
12
|
+
},
|
|
13
|
+
resolve: {
|
|
14
|
+
extensions: [".js", ".jsx"],
|
|
15
|
+
},
|
|
16
|
+
plugins: [
|
|
17
|
+
new webpack.IgnorePlugin({
|
|
18
|
+
resourceRegExp: /@blueprintjs\/(core|icons)/, // ignore optional UI framework dependencies
|
|
19
|
+
}),
|
|
20
|
+
],
|
|
21
|
+
module: {
|
|
22
|
+
rules: [
|
|
23
|
+
{
|
|
24
|
+
test: /\.(js|jsx)$/,
|
|
25
|
+
exclude: /node_modules/,
|
|
26
|
+
use: {
|
|
27
|
+
loader: "babel-loader",
|
|
28
|
+
},
|
|
29
|
+
resolve: {
|
|
30
|
+
fullySpecified: false,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
test: /\.(png|jpe?g|gif|svg)$/i,
|
|
35
|
+
type: 'asset/resource',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
devServer: {
|
|
40
|
+
static: [
|
|
41
|
+
{
|
|
42
|
+
directory: path.join(__dirname, "demo"),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
directory: path.join(__dirname, "demo", "dist"),
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
compress: true,
|
|
49
|
+
port: 9000,
|
|
50
|
+
historyApiFallback: true,
|
|
51
|
+
client: {
|
|
52
|
+
overlay: false,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
};
|