Text vIewer for Digital Objects. With this project we provide a highly configurable viewer for projects that implement the TextAPI.
- Demo
- Getting Started
- Configuration
- Bookmarking
- Getting Started (Developers)
- TextAPI Support
- Viewer Architecture
- Dockerfile
- Architecture
- Contributing
- Versioning
- Authors
You can preview TIDO at GitLab Pages with different configurations to compare with. Generally the deployment to Pages runs at every branch.
You can access the preview with the following URL syntax:
[GitLab Pages base URL]/[branch-name]/config-tester/[project].html
List of preview configurations:
- Ahiqar Textual Witnesses In Syriac
- Ahiqar Textual Witnesses In Arabic And Karshuni
- Goethes Farbenlehre in Berlin
- Zero Config
(here you can append an entrypoint URL parameter like
?collection=https://example.com
. For more details, please check the Bookmarking section.)
TIDO is provided as npm package. Please follow the steps below to include it for production:
Since npm communicates with the package API, it is necessary to setup a valid endpoint.
echo @subugoe:registry=https://gitlab.gwdg.de/api/v4/packages/npm/ >>.npmrc
Note: Fire this command inside the root of your project directory.
npm i @subugoe/tido
- Add these two files to your application:
tido.js
andtido.css
.
HTML:
<link href="/node_modules/@subugoe/tido/dist/tido.css" rel="stylesheet">
<script src="/node_modules/@subugoe/tido/dist/tido.js"></script>
JS:
import '@subugoe/tido/dist/tido.js'
import '@subugoe/tido/dist/tido.css'
- Add a container element to your application where TIDO can hook into. Please make sure that this element has your desired dimensions and position.
<style>
#app {
height: 100vh;
width: 100%;
}
</style>
<div id="app"></div>
- Create a new TIDO instance and provide optionally your TIDO configuration:
<script>
const tido = new Tido({
manifest: 'https://example.com/textapi/manifest.json'
});
</script>
Below you can find a detailed explanation of the configuration object.
TIDO requires an entrypoint URL to be useful at all. You can provide either a collection
or a manifest
key
and additionally provide an item
key to start a certain item with a sequence. Technically you could also provide
a single item
key only, but it is recommended to use manifests as wrappers.
By default, TIDO will render five panels displaying sequence tree, metadata, image, text content and annotation views. Nevertheless, you can fully customize the viewer's behaviour.
There are options to
- add/remove multiple panels
- freely combine view components in panels
- show/hide header features
- change the color scheme
- and more ...
Real world example:
<script id="tido-config" type="application/json">
{
"collection": "http://localhost:8181/ahiqar/arabic-karshuni/collection.json",
"panels": [
{
"label": "contents_and_metadata",
"views": [
{
"id": "tree",
"label": "contents",
"connector": {
"id": 1,
"options": {
"labels": {
"item": "Sheet",
"manifest": "Manuscript"
}
}
}
},
{
"id": "metadata",
"label": "metadata",
"connector": {
"id": 2,
"options": {
"collection": {
"all": true
},
"manifest": {
"all": true
},
"item": {
"all": true
}
}
}
}
]
},
{
"label": "image",
"views": [
{
"id": "image",
"label": "Image",
"connector": {
"id": 3
}
}]
},
{
"label": "text",
"views": [
{
"id": "text1",
"label": "Transcription",
"default": true,
"connector": {
"id": 4,
"options": {
"type": "transcription"
}
}
},
{
"id": "text2",
"label": "Transliteration",
"connector": {
"id": 4,
"options": {
"type": "transliteration"
}
}
}
]
},
{
"label": "annotations",
"views": [
{
"id": "annotations1",
"label": "Editorial",
"default": true,
"connector": {
"id": 5,
"options": {
"types": [
{
"name": "Person",
"index": "biPersonFill",
},
{
"name": "Place",
"index": "biGeoAltFill",
},
{
"name": "Editorial Comment",
"index": "biChatFill",
},
{
"name": "Reference",
"index": "biBoxArrowUpRight",
}
]
}
}
},
{
"id": "annotations2",
"label": "Motif",
"connector": {
"id": 5,
"options": {
"types": [
{
"name": "Motif",
"index": "biPenFill",
}
]
}
}
}
]
}
],
"translations": {
"en": {
"contents_and_metadata": "Contents & Metadata"
}
}
}
</script>
Name | Type | Default | Description |
---|---|---|---|
collection | String | null | Specifies a collection endpoint URL. Will be prioritized over manifest key. |
colors | Object | ↓ | Sets custom theme colors. If any value is left blank (e.g. "primary": "", ), a default color scheme will be used. |
colors.forceMode | String | light |
Enforces the initial color mod despite the browser settings. Supported values: light , dark , none . |
colors.primary | String | #477fbf |
Used as main color in buttons, active states, highlights |
colors.secondary | String | #eeeeee |
Can be used as contrast or background color |
colors.accent | Srring | empty |
|
container | String | #app |
Specifies the CSS selector where we should append the TIDO app to. |
header | Object | ↓ | Controls the elements in the section above the content |
header.show | Boolean | true |
Toggle visibility of the whole header |
header.navigation | Boolean | true |
Toggle visibility of prev/next buttons |
header.panelsToggle | Boolean | true |
Toggle visibility of panel toggle buttons |
header.languageSwitch | Boolean | false |
Toggle visibility of language switch for supported languages |
item | String | null | Specifies an item endpoint URL. |
lang | String | en |
Sets the default language. Possible supported values: en , de |
manifest | String | null | Specifies a manifest endpoint URL. Will be ignored when there is a collection key specified. |
notificationColors | Object | ↓ | Sets custom notification colors. Used in error messages. |
notificationColors.info | String | blue-9 |
Sets the info level color. |
notificationColors.warning | String | red-9 |
Sets the warning level color. |
panels | PanelConfig[] | ↓ | Defines an array of panel objects. The panels will appear in the same order. |
panels[i].label | String | Panel i |
Sets the label which appears in the panel header. If there is only one view in the panel then the view label will be displayed instead. Translatable. |
panels[i].views | ViewConfig[] | ↓ | Defines an array of views inside of a panel. If there are multiple views, we display them in tabs. If there is only one view we omit the tabs and display the view directly inside the panel. |
panels[i].views[j].id | String | view-j |
Unique identifier for the view across the app. |
panels[i].views[j].label | String | View j |
Sets the label which appears in the tab header. If there is only one view then this label will be displayed as panel header label. Translatable. |
panels[i].views[j].default | Boolean | false |
Specifies whether this view should be visible at the initial start of the app. If no default keys provided on views or all default keys are set to false , then the first view will be considered as default. |
panels[i].views[j].connector | Object | ↓ | Defines which view component and its options. Each view can have its own arbitrary config options. |
panels[i].views[j].connector.id | Number | null | Defines the component id which will be rendered dynamically for this view. See view connectors. |
panels[i].views[j].connector.options | Object | null | Defines options for individual view components. Each view component has different options. See view connector options. |
translations | Object | null | Specifies a custom translations object. |
translations.[langKey] | Object | null | Defines a translation object for supported languages with the respective langKey which can have following values: en , de . |
translations.[langKey].[translationKey] | String | null | Defines a translation key/value pair for a supported language. You can override existing key/value pairs or define custom key/value pairs. |
TIDO can be configured to display dynamic panel with dynamic views inside. In order to tell TIDO how the panels and views should be rendered, you need to assign the right connectors in the config. This is done via component IDs which currently are plain integers. Below you can find a list of available components.
ID | Name | Description |
---|---|---|
1 | Tree | Displays an expandable/collapsible tree view that renders TextAPi sequences. |
2 | Metadata | Displays dynamic metadata from collection, manifest and item levels. |
3 | Image | Displays the image resource from the item in an OpenSeadragon instance. |
4 | Text | Displays one text type from the item. Loads a support CSS file it provided. Handles text highlighting and selecting |
5 | Annotations | Displays a list of annotations. Handles selecting. |
Each view component can be configured via an options
object that can be passed at the connector.
Here is an overview of available options:
Name | Type | Default | Description |
---|---|---|---|
labels | Object | null | You can overwrite default labels of tree nodes. |
labels["item"] | String | "page" |
Label prefix for an item tree node. The item number in the sequence will be appended. It will be displayed when no other label is given by the item itself. The output could look like this: "Page 3" |
labels["manifest"] | String | "manifest" |
Label prefix for an manifest tree node. The manifest number in the sequence will be appended. It will be displayed when no other label is given by the item itself. The output could look like this: "Manifest 3" |
Name | Type | Default | Description |
---|---|---|---|
collection | Boolean | true |
Toggle on/off the collection section. |
manifest | Boolean | true |
Toggle on/off the manifest section. |
item | Boolean | true |
Toggle on/off the item section. |
no options
Name | Type | Default | Description |
---|---|---|---|
type | String | null | Specify the content type slug that is served from item.content response. |
Name | Type | Default | Description |
---|---|---|---|
types | AnnotationTypeConfig[] | [] |
Defines annotation types that should be displayed in this view. The Annotation API response will then be filtered according to this config. |
types[i].name | String | null |
Specifies the name which corresponds to the x-content-type property from annotations response. |
types[i].index | String | null |
Specifies the index name that should be used in the annotation item. TIDO uses Bootstrap Icons, please lookup the allowed values here |
types[i].displayWhen | String | null |
Text content type that was specified under Text options. Annotation will only be shown if that content type is currently active. |
types[i].annotationType | String | annotation |
Controls the look of the annotation item. Allowed values: annotation or text . Currently the only difference is that there is no index at type text . |
TIDO will reflect certain state changes to the URL so you can save and share your current view.
It appends only one GET parameter. The key
is tido
and the value
are the settings of the current app state.
Full example of the bookmarking concept: http://localhost:5173/?tido=m0_i1_s0-2-3_p0.0-1.0-2.0-3.1
.
The 'value' consists of 4 parts:
- Manifest part: m0
- Item part: i1
- Visible panels: s0-2-3
- Active tab for each panel: p0.0-1.0-2.0-3.1
Currently we provide the following bookmarking keys:
Key | Value | Description |
---|---|---|
collection |
URL | Specifies a collection entrypoint. Will be preferred before manifest . |
manifest |
URL | Specifies a manifest entrypoint. |
item |
URL | Specifies an item entrypoint. If not set the first possible item will be appended and displayed. |
m |
Int: i.e 0 | Specifies the manifest index inside a certain collection. Syntax: m[manifest index], example: m0 |
i |
Int: i.e 1 | Specifies the item index of a certain manifest. Syntax: i[item index], example: i1 |
s |
0-1-2 |
Controls the visibility of panels. It's a list of dash-separated panel indexes. All other panels will be hidden. Not set = all visible. Syntax: s[index1]-[index2]..., example: s0-1-2 |
p |
0.1-1.1-2.1-3.1 |
Specifies the active view (tab) in a respective panel. Syntax: p[panel index1].[view_index1]-[panel index2].[view_index2].. , example p0.1-1.1-2.1-3.1 . Each user interaction will change this parameter. |
Hint: With this setup you are able to load your entrypoint dynamically by appending it at the URL instead of rendering it via the configuration object inside your wrapper application.
To get TIDO up and running you should have the following software installed:
- npm
- nvm
Note:
We recommend to make use of nvm
, since there might be issues with npm regarding permissions.
The main purpose of nvm
is to have multiple node versions installed in regards to different projects which might demand some sort of backwards compatibility.
It enables you to just switch to the appropriate node version.
Besides it also keeps track of resolving permission issues, since all your global installations go to your home directory (~/.nvm/) instead of being applied systemwide.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
nvm install stable
Note:
After the nvm installation is done, please restart
your shell session once. That's due to changes to your profile environment.
git clone [email protected]:subugoe/emo/tido.git
Head over to your project directory, where you just cloned the repository to as described above and get all the dependencies needed by typing:
cd /path/to/projectdir
npm install
That's it. You should now be able to run the Viewer.
Please run this command to create a production build.
npm run build
The output files are located at /dist
.
Builds the app in development mode
(hot reloading, error reporting, etc.).
npm run serve:dev
It will be available under localhost:5173
.
You can serve a production build by viewing example configurations that we provide under /examples
.
Run this command which will create a TIDO production build and copy the result files into /examples
:
npm run serve:prod
This examples are available under localhost:2222
. Each example has its own HTML file:
http://localhost:2222/[example-name].html
You can start your own local API server which will serve TextAPI responses from tests/mocks
.
The folder structure represents a portion of resources of the Ahiqar project.
npm run serve:mock-api
The server will be available at localhost:8181
.
We run tests only on production code. So you need to make sure to create a TIDO build before starting to run tests. TIDO follows the "Zero Config" policy but projects can provide a very detailed config that can drastically change the behaviour of the app. Therefor we provide some example configurations from previous implementation projects that cover the most important features.
Following examples are available under (examples/
):
ahiqar-arabic-karshuni.html
ahiqar-arabic-karshuni-local.html
ahiqar-syriac.html
gfl.html
zero-config.html
Prepare the environment before running the tests.
npm run build
npm run serve:mock-api
npm run serve:prod
Now you can run the tests on your local machine with a proper Cypress UI and selective steps or run the tests only in headless more which will prompt the results on the console.
npm run cypress
ornpm run cypress:headless
You can use a one-line command which will start the mock API server and run tests in headless mode after it has connected to that mock API server.
npm run build
npm run test:e2e
npm run lint # to lint all the files at once
npm run lint:js # to lint js files only
npm run lint:markdown # to lint the markdown
npm run lint:scss # to lint the styles
npm run lint:vue # to lint vue files only
We maintain a JSON file (/.validation/support-matrix.json
) that keeps track of supported TextAPI features.
If you need to recreate that file and rerender /SUPPORT.md
, here is an explanation:
- Make sure you run NodeJS version >= 20
- Set
GITLAB_ACCESS_TOKEN
in/.env
file - Run
node ./.validation/create-support-matrix.js
- Inspect
/.validation/support-matrix.json
, all status values are set to 0 (= not supported) by default - Edit the statuses manually: 0 = not supported, 1 = supported, 2 = partially supported, 3 = unused
- Run
node ./.validation/create-support-matrix.js
again to generate new/SUPPORT.md
Please view this document to see an overview of supported TextAPI features: State of TextAPI support
The Dockerfile is used for GitLab CI.
docker build --pull -t docker.gitlab.gwdg.de/subugoe/emo/tido/node .
docker push docker.gitlab.gwdg.de/subugoe/emo/tido/node
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
We use SemVer for versioning. For the versions available, see the tags on this repository.
See the list of contributors who participated in this project. First line added!