{"id":40929426,"url":"https://github.com/bodleian/archiox-mirador-plugin","last_synced_at":"2026-01-22T04:04:52.187Z","repository":{"id":174959094,"uuid":"555329689","full_name":"bodleian/archiox-mirador-plugin","owner":"bodleian","description":"An experimental plugin to display depth information captured with Lucida or Selene scanners from FactumARTE.  However, the plug-in can present any normal map/albedo map combination produced from any technique.","archived":false,"fork":false,"pushed_at":"2025-07-28T14:00:52.000Z","size":3177,"stargazers_count":6,"open_issues_count":11,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-10-11T00:45:08.394Z","etag":null,"topics":["iiif","mirador-plugins"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bodleian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-21T11:17:50.000Z","updated_at":"2025-06-16T15:05:03.000Z","dependencies_parsed_at":"2023-11-06T22:57:23.349Z","dependency_job_id":"b9f6db15-db21-4304-b139-4056b72fdfe0","html_url":"https://github.com/bodleian/archiox-mirador-plugin","commit_stats":null,"previous_names":["bodleian/archiox-mirador-plugin"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/bodleian/archiox-mirador-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodleian%2Farchiox-mirador-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodleian%2Farchiox-mirador-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodleian%2Farchiox-mirador-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodleian%2Farchiox-mirador-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bodleian","download_url":"https://codeload.github.com/bodleian/archiox-mirador-plugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodleian%2Farchiox-mirador-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28653670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["iiif","mirador-plugins"],"created_at":"2026-01-22T04:04:51.559Z","updated_at":"2026-01-22T04:04:52.179Z","avatar_url":"https://github.com/bodleian.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# archiox-mirador-plugin\nThis is the ARCHiOx Mirador Viewer plug-in, it is designed to be installed as a Mirador viewer plug-in and is not\na standalone application.\n\n# Demo\nYou can play around with our implementation [here](https://iiif.bodleian.ox.ac.uk/iiif/mirador/?iiif-content=https://iiif.bodleian.ox.ac.uk/iiif/manifest/1fc3f35d-bbb5-4524-8fbe-a5bcb5468be2.json)\n\nLook for the torch button in the top left of the viewer window, pressing this will open up our plug-in menu that allows \nyou to render the normal map data alongside the albedo map in realtime in your browser giving the object the illusion of\n3D depth (2.5D) and allowing you to re-light and change the light direction by dragging your mouse cursor over the \n\"sphere\" control.  You can also play around with metalness and roughness in `physically based rendering` (PBR) mode, or \nshininess in `specular enhancement` mode.  The intensity of both directional and ambient light, and the normal depths\ncan also be changed using the slider controls to allow you to explore all the details recorded in these special objects.\n\n# Image Formats\nThe plug-in makes use of normal map data generated from photometric techniques of objects and renders a \"2.5D\"\ninteractive experience using a three.js canvas overlay.  Because of this, we recommend that you use a lossless image\nformat such as PNG or WebP for your albedo and normal map layers. WebP, however, is not currently supported as of \nversion 4.10 of OpenSeadragon, it is, however, planned for inclusion in version 5.0.  In order to work around this for \nnow, you can build your own version of OpenSeadragon with the following modification, where we have added WebP to the \nlist of formats supported.\n\n```javascript\nvar FILEFORMATS = {\n            bmp:  false,\n            jpeg: true,\n            jpg:  true,\n            png:  true,\n            tif:  false,\n            wdp:  false,\n            webp: true\n}\n```\n\nHost your build on GitHub or GitLabs and override the version used by Mirador by adding something like the following\nto your package.json file, where the `org/repository` points to your own.\n\n```json\n\"overrides\": {\n    \"openseadragon\": \"github:org/repository\"\n  }\n```\n\n# IIIF Presentation and Image API Support\nThe plug-in is intended to be used with version 3 of the IIIF presentation and image APIs to make use of the\n`preferredFormat` property, so that you can use WebP format.  However, you can technically get choices working\nin version 2.  For the plug-in to work at all you will need to extend IIIF presentation API for choices in the \nfollowing way, where we add in type `lightingMapExtension` and `mapType`:\n\n```json\n{\n            \"id\": \"http://0.0.0.0:8000/iiif/canvas/object_id.json\",\n            \"type\": \"Canvas\",\n            \"label\": {\n                \"en\": [\n                    \"front end\"\n                ]\n            },\n            \"width\": 1508,\n            \"height\": 5300,\n            \"items\": [\n                {\n                    \"id\": \"http://0.0.0.0:8000/iiif/annotationpage/object_id.json\",\n                    \"type\": \"AnnotationPage\",\n                    \"items\": [\n                        {\n                            \"id\": \"http://0.0.0.0:8000/iiif/annotation/object_id.json\",\n                            \"type\": \"Annotation\",\n                            \"target\": \"http://0.0.0.0:8000/iiif/canvas/object_id.json\",\n                            \"body\": {\n                                \"type\": \"Choice\",\n                                \"items\": [\n                                    {\n                                        \"id\": \"http://0.0.0.0:8000/iiif/image/image_id/full/max/0/default.png\",\n                                        \"type\": \"Image\",\n                                        \"format\": \"image/png\",\n                                        \"label\": {\n                                            \"en\": [\n                                                \"front end\"\n                                            ]\n                                        },\n                                        \"width\": 1508,\n                                        \"height\": 5300,\n                                        \"service\": [\n                                            {\n                                                \"@id\": \"http://0.0.0.0:8000/iiif/image/image_id\",\n                                                \"@type\": \"ImageService2\",\n                                                \"profile\": \"http://iiif.io/api/image/2/level1.json\"\n                                            },\n                                            {\n                                                \"id\": \"http://0.0.0.0:8000/iiif/image/image_id\",\n                                                \"type\": \"ImageService3\",\n                                                \"profile\": \"level1\"\n                                            },\n                                            {\n                                                \"id\": \"http://0.0.0.0:8000/iiif/image/lightingmap/image_id.json\",\n                                                \"type\": \"LightingMapExtension\",\n                                                \"profile\": \"http://iiif.io/api/extension/lightingmap\",\n                                                \"mapType\": \"albedo\"\n                                            }\n                                        ]\n                                    },\n                                    {\n                                        \"id\": \"http://0.0.0.0:8000/iiif/image/image_id/full/max/0/default.png\",\n                                        \"type\": \"Image\",\n                                        \"format\": \"image/png\",\n                                        \"label\": {\n                                            \"en\": [\n                                                \"front end\"\n                                            ]\n                                        },\n                                        \"width\": 1508,\n                                        \"height\": 5300,\n                                        \"service\": [\n                                            {\n                                                \"@id\": \"http://0.0.0.0:8000/iiif/image/image_id\",\n                                                \"@type\": \"ImageService2\",\n                                                \"profile\": \"http://iiif.io/api/image/2/level1.json\"\n                                            },\n                                            {\n                                                \"id\": \"http://0.0.0.0:8000/iiif/image/image_id\",\n                                                \"type\": \"ImageService3\",\n                                                \"profile\": \"level1\"\n                                            },\n                                            {\n                                                \"id\": \"http://0.0.0.0:8000/iiif/image/lightingmap/image_id.json\",\n                                                \"type\": \"LightingMapExtension\",\n                                                \"profile\": \"http://iiif.io/api/extension/lightingmap\",\n                                                \"mapType\": \"normal\"\n                                            }\n                                        ]\n                                    }\n                                ]\n                            }\n                        }\n                    ],\n                    \"motivation\": \"painting\"\n                }\n            ]\n        }\n```\n\n# IIIF Choices and Mirador Viewer Config\nThis Mirador plug-in makes use of IIIF Choices and is developed for single page view only; because of this we take control of Mirador via the plug-in and set\nthe config for the default viewing experience whenever a Choices body type is detected at canvas level.  \n\nYou are still free to manually change to book view in the Mirador menu, however, the plug-in won't work as intended.\n\nThe view config we inject is identical to the exerpt below:\n\n```json\n    views: [\n    { key: 'single', behaviors: ['individuals', 'paged'] },\n    { key: 'book', behaviors: ['individuals', 'paged'] },\n    { key: 'scroll', behaviors: ['continuous'] },\n    { key: 'gallery' },\n    ]\n```\n\n# Installation and build\nMake sure you have node.js and npm installed.  It might also be good to install nvm to allow you to switch versions of\nnode.js more easily.\n\nChange the default version of node, node version 22+ is compatible.\n\n```bash\nnvm install 20.19.0\n```\n\nMake nvm use whatever version is compatible.\n\n```bash\nnvm use 20\n```\n\nTo build Mirador bundled with our plug-in, run the following commands from the root directory of your \nMirador build repository:\n\nInstall the dependencies.\n\n```bash\nnpm install mirador@3.4.2  \n```\n\nThen add the following dependencies verbatim to the dependencies dictionary of the package.json file so that it looks\nlike the example below:\n\n```json\n\"dependencies\": {\n    \"mirador\": \"3.4.3\",\n    \"archiox-mirador-plugin\": \"github:bodleian/archiox-mirador-plugin.git\",\n    \"mirador-image-tools\": \"0.11\",\n    \"react\": \"^16.14.0\",\n    \"react-dom\": \"^16.14.0\",\n    \"@emotion/react\": \"^11.14.0\",\n    \"@emotion/styled\": \"^11.14.0\",\n    \"react-i18next\": \"^15.4.1\",\n    \"url-loader\": \"^4.1.1\",\n    \"vite\": \"^6.2.3\",\n    \"@vitejs/plugin-react\": \"^4.3.4\",\n    \"vite-plugin-svgr\": \"^4.3.0\"\n}\n```\nThen delete the package-lock.json file and re-run the install command as follows:\n\n```bash\nnpm install\n```\n\nCreate a `/src` folder with a new `index.js` in it, copy-paste the following into it (edit for your needs):\n**NB: ** This example is configured for the Bodleian Library set up of using content negotiation to serve \neither v2/v3 IIIF image and or presentation API requests.  Replace `your_iiif_manifest.json` with the uri to the \nmanifest you wish to serve Mirador viewer.\n\n```javascript\nimport Mirador from 'mirador';\nimport { relightMiradorPlugin } from 'archiox-mirador-plugin';\nimport { miradorImageToolsPlugin } from \"mirador-image-tools/es/index\";\n\nconst MiradorPlugins = {\n    relightMiradorPlugin: relightMiradorPlugin,\n    miradorImageToolsPlugin: miradorImageToolsPlugin\n};\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  let sideBarOpen = true;\n\n  if (Math.min(window.innerWidth) \u003c 1500 || navigator.userAgent.indexOf(\"Mobi\") \u003e -1){\n    sideBarOpen = false;\n  }\n\n  const config = {\n    id: 'viewer',\n    windows: [{\n      // enable and show the image tools plugin controls\n      imageToolsEnabled: true,\n      normalsInverted: true,\n      imageToolsOpen: false,\n      sideBarOpen: sideBarOpen,\n      archioxPluginOpen: true,\n      manifestId: 'your_iiif_manifest.json'\n    }],\n    requests: {\n      // Manipulate IIIF HTTP requests (info.json, IIIF presentation manifests, annotations, etc) to add an Accept header so we use our v3 manifests\n      preprocessors: [\n        (url, options) =\u003e ({...options,\n          headers: {\n            ...options.headers,\n            Accept: url.endsWith('/info.json')\n                ? 'application/ld+json;profile=\"http://iiif.io/api/image/3/context.json\"'\n                : 'application/ld+json;profile=\"http://iiif.io/api/presentation/3/context.json\"',\n            ...(url.endsWith('/info.json') \u0026\u0026 { 'Cache-Control': 'no-cache' })\n          }\n        })\n      ],\n    },\n    theme: {\n      palette: {\n        primary: {\n          main: '#1967d2',\n        },\n      },\n    },\n    osdConfig:{\n      crossOriginPolicy: \"Anonymous\",\n      subPixelRoundingForTransparency: 1,\n      overlayPreserveContentDirection: false,\n    },\n  };\n  Mirador.viewer(config, Object.values(MiradorPlugins).flatMap((e) =\u003e ([...e])));\n});\n```\n\nIn your `package.json` file add the following to your scripts as follows:\n\n```json\n \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n```\n\nIn the root folder create a new `index.html` and copy-paste the following example:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"utf-8\" /\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\"\u003e\n    \u003c!-- By default Mirador uses Roboto font. Be sure to load this or change the font --\u003e\n    \u003clink rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Roboto:300,400,500\"\u003e\n    \u003ctitle\u003eMirador Example\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003c!-- Container element of Mirador whose id should be passed to the instantiating call as \"id\" --\u003e\n\u003cdiv id=\"viewer\"\u003e\u003c/div\u003e\n\u003cscript src=\"./src/index.js\" type=\"module\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nIn the root folder create an empty `vite.config.js` file and copy-paste the following config that\nallows transpiling of JSX and exporting of SVGs as components.\n\n```javascript\nimport { defineConfig } from 'vite';\nimport svgr from 'vite-plugin-svgr';\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n    plugins: [\n        react(),\n        svgr()\n    ],\n    esbuild: {\n        loader: 'jsx',\n            include: /.*\\.jsx?$/,\n            exclude: []\n    },\n    optimizeDeps: {\n        esbuildOptions: {\n            loader: {\n                '.js': 'jsx',\n            },\n        },\n    },\n    build: {\n        sourcemap: true,\n    },\n    base: './',\n});\n```\n\nTo build Mirador with the plug-ins installed, run the following script:\n\n```bash\nnpm run build\n```\n\nTo serve a preview of your Mirador build locally on the localhost, run the following strip:\n\n```bash\nnpm run preview\n```\n\n# Development  Rules\nAll new features should be placed in feature branches and not pushed direct to the `qa` or `master` branches as per our \nother repos.  That way we can test new features without breaking anything.\n\n# Developing locally\nTo develop the application locally you can work on and edit the code in your Mirador build folders `node_modules`\ndirectory under `node_modules/archiox-mirador-plugin/src/plugins` and rebuild the application using `npm run build`.\n\nAny changes you get working in this way can be then added to commits as a feature branch of the `archiox-mirador-plugin`\nrepository.\n\nTo pull in changes from a feature branch you can specify the branch and commit in your `package.json` and \n`package-lock.sjon` files in your Mirador build folder.  Update all instances of `archiox-mirador-plugin` to something\nlike the following (this is only an example of the kind of thing to look for):\n\n```json\n\"packages\": {\n    \"\": {\n\"archiox-mirador-plugin\": \"github:bodleian/archiox-mirador-plugin#example-feature-branch\",\n},\n\"node_modules/archiox-mirador-plugin\": {\n\"version\": \"0.0.1\",\n\"resolved\": \"https://github.com/bodleian/archiox-mirador-plugin.git#example-commit-hash\",\n\"license\": \"N/A\",\n\"dependencies\": {\n\"react-loader-spinner\": \"^5.3.4\",\n\"three\": \"^0.146.0\"\n},\n\"peerDependencies\": {\n\"mirador\": \"^3.0.0-rc.4\",\n\"react\": \"16.x\",\n\"react-dom\": \"16.x\"\n}\n}\n```\n\nThen run the following command (warning this will wipe out any local changes, because it does a clean install):\n\n```bash\nnpm ci\n```\n\n## es-lint and Prettier\nTo lint and autoformat your code locally, run the following script from this repositories root directory, \nnot your Mirador build, after installing the relevant dependencies in the normal way:\n\n```bash\nnpm run lint\n```\n\n## Unit testing\nTo run the unit tests locally, run the following command:\n\n```bash\nnpm run test\n```\n\n## Gotchas\nIf you are serving images to your Mirador instance from another host you may not be able to load them depending on your\nCORS policy.  You can get around this for local dev by changing a setting of OpenSeaDragon installed in your\n`node_modules` folder.  Find the openseadragon.js file in `node_modules/openseadragon/build/openseadragon/` and change\nthe value of `crossOriginPolicy` from false to `Anonymous` in the `DEFAULT_SETTINGS` object and rebuild your Mirador\nusing `npm run webpack`.  Be warned that running `npm ci` will wipe out this change and you will need to reimplement it\nevery time you do a clean installation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbodleian%2Farchiox-mirador-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbodleian%2Farchiox-mirador-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbodleian%2Farchiox-mirador-plugin/lists"}