textbrowser 0.39.0 → 0.40.3

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,23 +1,12 @@
1
1
  {
2
2
  "name": "textbrowser",
3
- "version": "0.39.0",
3
+ "version": "0.40.3",
4
4
  "description": "Multilinear text browser",
5
5
  "main": "dist/index-umd.min.js",
6
6
  "module": "resources/index.js",
7
7
  "bin": {
8
8
  "textbrowser": "./server/main-cjs.js"
9
9
  },
10
- "scripts": {
11
- "server": "./server/main-cjs.js --allowPlugins --namespace=test",
12
- "start": "static -p 8081",
13
- "rollup": "rollup -c",
14
- "lint": "npm run eslint",
15
- "eslint": "eslint --ext=js,md,html .",
16
- "node": "npm run eslint && npm run rollup && mocha test/textbrowserTests.js",
17
- "open-test": "open-cli http://127.0.0.1:8081/test/",
18
- "start-open-test": "run-p start open-test",
19
- "test": "npm run eslint && npm run rollup && npm run start-open-test"
20
- },
21
10
  "browserslist": [
22
11
  "cover 100%"
23
12
  ],
@@ -39,64 +28,75 @@
39
28
  "text"
40
29
  ],
41
30
  "dependencies": {
42
- "@babel/core": "^7.14.3",
43
- "@babel/register": "^7.13.16",
31
+ "@babel/core": "^7.16.7",
32
+ "@babel/register": "^7.16.9",
44
33
  "@brettz9/node-static": "^0.1.1",
45
- "command-line-args": "^5.1.1",
34
+ "command-line-args": "^5.2.0",
46
35
  "dialog-polyfill": "^0.5.6",
47
36
  "dom-parser": "^0.1.6",
48
37
  "form-serialization": "^0.11.0",
49
38
  "imf": "5.0.2",
50
- "indexeddbshim": "^7.1.0",
39
+ "indexeddbshim": "^9.0.0",
51
40
  "jamilih": "0.54.0",
52
- "jsdom": "^16.6.0",
41
+ "jsdom": "^19.0.0",
53
42
  "json-refs": "git+https://github.com/brettz9/json-refs.git#browser",
54
43
  "load-stylesheets": "0.10.0",
55
- "node-fetch": "^2.6.1",
44
+ "node-fetch": "^2.6.6",
56
45
  "node-serviceworker": "^0.3.0",
57
- "rtl-detect": "^1.0.3",
46
+ "rtl-detect": "^1.0.4",
58
47
  "simple-get-json": "8.1.1",
59
48
  "url-search-params-polyfill": "^8.1.1"
60
49
  },
61
50
  "devDependencies": {
62
- "@babel/eslint-parser": "^7.14.4",
63
- "@babel/plugin-proposal-object-rest-spread": "^7.14.4",
51
+ "@babel/eslint-parser": "^7.16.5",
52
+ "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
64
53
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
65
- "@babel/preset-env": "^7.14.4",
66
- "@brettz9/eslint-plugin": "^1.0.3",
54
+ "@babel/preset-env": "^7.16.8",
55
+ "@brettz9/eslint-plugin": "^1.0.4",
67
56
  "@rollup/plugin-babel": "^5.3.0",
68
- "@rollup/plugin-commonjs": "^19.0.0",
57
+ "@rollup/plugin-commonjs": "^21.0.1",
69
58
  "@rollup/plugin-json": "^4.1.0",
70
- "@rollup/plugin-node-resolve": "^13.0.0",
59
+ "@rollup/plugin-node-resolve": "^13.1.3",
71
60
  "@stadtlandnetz/rollup-plugin-postprocess": "1.1.0",
72
- "ajv": "8.6.0",
61
+ "ajv": "8.8.2",
73
62
  "babel-plugin-dynamic-import-node": "^2.3.3",
74
63
  "chai": "^4.3.4",
75
- "eslint": "^7.28.0",
76
- "eslint-config-ash-nazg": "^29.17.0",
64
+ "eslint": "^8.6.0",
65
+ "eslint-config-ash-nazg": "^32.3.0",
77
66
  "eslint-config-standard": "^16.0.3",
78
67
  "eslint-plugin-array-func": "^3.1.7",
79
- "eslint-plugin-compat": "^3.9.0",
68
+ "eslint-plugin-compat": "^4.0.1",
80
69
  "eslint-plugin-eslint-comments": "^3.2.0",
81
- "eslint-plugin-html": "^6.1.2",
82
- "eslint-plugin-import": "^2.23.4",
83
- "eslint-plugin-jsdoc": "^35.1.3",
84
- "eslint-plugin-markdown": "^2.2.0",
85
- "eslint-plugin-no-unsanitized": "^3.1.5",
70
+ "eslint-plugin-html": "^6.2.0",
71
+ "eslint-plugin-import": "^2.25.4",
72
+ "eslint-plugin-jsdoc": "^37.6.1",
73
+ "eslint-plugin-markdown": "^2.2.1",
74
+ "eslint-plugin-no-unsanitized": "^4.0.1",
86
75
  "eslint-plugin-no-use-extend-native": "^0.5.0",
87
76
  "eslint-plugin-node": "^11.1.0",
88
- "eslint-plugin-promise": "^5.1.0",
89
- "eslint-plugin-radar": "^0.2.1",
77
+ "eslint-plugin-promise": "^6.0.0",
78
+ "eslint-plugin-sonarjs": "^0.11.0",
90
79
  "eslint-plugin-standard": "^4.1.0",
91
- "eslint-plugin-unicorn": "^33.0.1",
92
- "fast-json-patch": "2.2.1",
80
+ "eslint-plugin-unicorn": "^40.0.0",
81
+ "fast-json-patch": "3.1.0",
93
82
  "json-metaschema": "1.3.0",
94
- "mocha": "^9.0.0",
83
+ "mocha": "^9.1.3",
95
84
  "npm-run-all": "^4.1.5",
96
- "open-cli": "^6.0.1",
97
- "remark-lint": "8.0.0",
98
- "rollup": "2.51.0",
85
+ "open-cli": "^7.0.1",
86
+ "rollup": "2.63.0",
99
87
  "rollup-plugin-re": "^1.0.7",
100
88
  "rollup-plugin-terser": "^7.0.2"
101
- }
102
- }
89
+ },
90
+ "scripts": {
91
+ "server": "./server/main-cjs.js --allowPlugins --namespace=test",
92
+ "start": "static -p 8081",
93
+ "rollup": "rollup -c",
94
+ "lint": "npm run eslint",
95
+ "eslint": "eslint --ext=js,md,html .",
96
+ "node": "npm run eslint && npm run rollup && mocha test/textbrowserTests.js",
97
+ "open-test": "open-cli http://127.0.0.1:8081/test/",
98
+ "start-open-test": "run-p start open-test",
99
+ "test": "npm run eslint && npm run rollup && npm run start-open-test"
100
+ },
101
+ "readme": "# TextBrowser\n\n*Please note that this project, while now preliminarily functional,\nis in its early stages. There are some bugs to iron out such as\nwith localization.*\n\n*TextBrowser* supports power-user browsing of arbitrary multi-linear\ntexts following the \"offline first\" motto.\n\nThe splash page for the texts is an internationalized interface\nthat allows for selection by the user of their desired interface language,\nfollowed by a screen to choose from among designated texts, with each text\nbeing given its own page to allow browsing of the contents of the text.\n\nThe text interface offers fine grained control to the *user* for how they\nwish the output of that text to be displayed, both in terms of styling and\npositioning, with its features particularly shining with multilinear/parallel\ntexts (e.g., multiple translations or commentaries that one views\nside-by-side), allowing columns to be displayed in separated columns and/or\ninterlinearly (one verse vertically beneath the corresponding alternate).\n\nDespite the name of the project referring to \"text\", this project\ncan be used for browsing any tabular data with sequential items.\n\nIt is designed to run solely with client-side JavaScript with the intent\nthat the web software will be able to work fully offline in the browser\nas well as online. Currently, it must be run on a server though any static\nserver will do (it comes with a script to run the code on a simple Node.js\nstatic file server--which can be easily set up on a local machine as well).\n(It can't be run from a `file://` URL (at least in Chrome), however, due to\nmore recent browser-added file access restrictions in such an environment.)\n\nThe syntax used in the code currently only works in a modern browser and\nto date has only been tested in Chrome.\n\n## Features / Design Goals\n\nThe following are user-facing features/goals:\n\n- Have the interface be fully internationalized (i18n) to support translation\n into other languages and well localized (l10n) into such languages,\n including for right-to-left languages. Internationalization even\n optionally applies to parameter names, though this functionality\n (and some other i18n features in general are not thoroughly tested at\n present).\n- Allow texts to be grouped on a work selection page with separate\n introductory messages for each work.\n- Allow browsing by a range of verses\n- Allow browsing by alternate mechanisms (e.g., by different ordering schemes\n on the same text)\n- Allow precise and canonical pointing to a specific row or even cell\n within a work (designation of anchors) by graphical means (without the\n user needing to dig through HTML).\n- Provide enumerated choices as pull-downs and numeric choices within\n numerically-aware input fields (including for max and min values).\n- Ability to selectively disable any column\n- Ability to reorder (and even repeat) columns\n- In addition to parallel text functionality where different translations,\n commentaries, etc. are assigned their own separate columns in the results\n table, allow users to designate that any field have any other field(s)\n repeating within its cell (i.e., interlinear as opposed to parallel\n display). Also provides a styling option on whether to repeat column\n names and the option to style them (currently, the administrator can\n also choose exactly how to separate these within cells from one another,\n but we hope to provide user-facing preselected choices in the future).\n- Allow categorization of content by language so that users can quickly\n enable only such content languages in which they are interested\n- Allow user to not only bookmark/share links of the results page and even\n of a particular view of the work page. Functionality should be\n available as much as possible via URL parameters.\n- Allow column-specific styling\n- Allow generic page styling of text, as form controls or CSS for\n experienced users.\n- Allow fine-grained control of the table display beyond border styling\n (e.g., whether to show a caption summarizing the work/selection, whether\n to show a header and if so, whether it should be fixed and/or styled, or\n or whether the \"table\" is even an HTML table or instead HTML `<div>`'s,\n etc.--JSON export is hoped for the future).\n- Ease of navigation within a site (as via breadcrumbs) and accessibility\n (e.g., for the visually impaired) is also desired, but we are hoping\n for expertise to provide a review and ideally assistance. We do have\n some code begun internally.\n\nThe following are administrator-facing features/goals:\n\n- Allow most functionality to work for administrators out of the box via a\n declarative style (via well-used and readable JSON files) without need\n for custom scripting. Though the project originated to meet the need of\n Bahá'í texts, any document and even data with sequential fields\n that can be put into a tabular structure can be browsed.\n- Allow for translations within separate locale files\n- Allows for easy conversion of table structures (e.g., SQL, JSON) into our\n simple JSON array format\n- Allow for standard means (as with our use of\n [JSON Schema](http://json-schema.org/documentation.html))\n to designate type information that can be used by the program for\n automated display as well as optimization. Where a standard means\n does not exist, we provide a declarative meta-data file to house\n this information.\n- It is a goal for us to support plug-ins for extensibility, including\n declarative specification without need for scripting, but such support\n is currently lacking (though some work internally has begun).\n- It is a goal for us to support declarative means for indicating site\n hierarchy and navigation. This is not implemented, but we do have some\n code begun internally.\n\nThe following are third-party-site-facing features/goals:\n\n- The thorough use of query strings (even to customize the work selection\n page as well as the results page) allow for other tools to more easily\n tap into our API, and the control of styling (including of whether to show\n table headers) deliberately allows for third-party sites to embed\n content directly from *TextBrowser*-driven sites (including sites which\n might wish to provide up-to-date, proofread, canonical sources of data\n without duplicating or introducing the possibility of copy-paste error).\n Blogs, discussion forums, and wikis might, for example, provide widgets\n (a popup to our site especially once we may have implemented our to-do\n for canonical syntax selection available through `postMessage`?) which\n could be used to embed a specific range and/or styling of text in a post.\n These advantages of widely-used query strings also go for people sharing\n links or bookmarking for themselves.\n\nThe following are *TextBrowser*-developer-facing features/goals:\n\n- Strong separation of concerns, with \"design logic\" separate from\n \"business logic\". We are using [Jamilih](https://github.com/brettz9/jamilih)-based\n templating to allow for templating functions in Vanilla JavaScript (as\n well as avoiding ugly, angular HTML almost entirely!). While the results\n display for users leverages CSS classes, we still need to remove some\n inline styling for better structural (HTML) vs. styling (CSS) separation.\n- We aim to leverage modern syntax, especially JavaScript, allowing\n derivative projects to polyfill if they wish to support older browsers.\n Besides aiming for better forward-compatibility, this allows us to use\n standard, well-known patterns, as well as more readable, succinct code.\n- We hope for good test-driven development, but currently this is limited to\n schema validation. We are still in need of a choice of UI testing\n framework and tests (as well as for unit tests).\n\n## Installation\n\nThe repository is intended to be used as a\n[npm](https://www.npmjs.com/) dependency.\n\nRun the following from your project root.\n\n```install\nnpm install textbrowser --save\n```\n\nYou can also target the latest code in `master` with the following:\n\n```json\n\"dependencies\": {\n \"textbrowser\": \"git@github.com:brettz9/textbrowser.git#master\"\n}\n```\n\nAnd then run `npm install` on your project path.\n\n(To update, you can remove `node_modules/textbrowser/` from your project\nand reinstall.)\n\n## Usage\n\nThe following instructions are aimed at those adding *TextBrowser* as a\ndependency of their own project.\n\nIf you would like to see a sample package implementing the\nfollowing, see the\n[bahaiwritings](https://bitbucket.org/brettz9/bahaiwritings)\nproject.\n\nProjects derivative to *TextBrowser* will need to adhere to the following:\n\n1. Add the *TextBrowser* dependency per the [Installation](#Installation)\n section.\n\n1. Prepare JSON data files, JSON Schema files, and JSON meta-data files\n to represent your texts. See the section\n [JSON Formats](#JSON Formats).\n To provide a common naming mechanism across projects and to avoid\n the need to tweak the default `TextBrowser` JavaScript class set-up, a\n [specific directory structure](#Recommended Project Directory Structure)\n is recommended for hosting these files.\n\n1. Prepare JSON files to indicate the specific grouping of files you wish\n to make available and optionally the interface languages you wish to\n make available (and for which you have locales), and after it may be\n ready, and if you wish, the JSON files to indicate your site hierarchy.\n See the\n [recommended directory structure](#Recommended Project Directory Structure)\n section for more.\n\n1. Create an HTML page (see `index-sample.html` for an example) which includes\n *TextBrowser*'s own project scripts and your own script to instantiate\n the `TextBrowser` class (and if you did not follow the\n [recommended directory structure](#Recommended Project Directory Structure),\n you will need to point to the above-mentioned JSON\n files). Page titles are set dynamically for each page, so there is no\n need to provide a `<title>`.\n\n## Recommended Project Directory Structure\n\nThe recommended project directory structure (which are used by default by the\n`TextBrowser` JavaScript API) is as follows:\n\n- ***package.json*** - Should indicate `textbrowser` as a dependency as per\n the [Installation](#Installation) section above.\n- ***node_modules*** - *TextBrowser* and its dependencies will be\n added here via npm install as well as any dependencies you indicate\n within `package.json`.\n- ***index.html*** - The main application code. One can use\n `index-sample.html` as is or modified as desired. Note that it\n may be sufficient to modify `resources/user.css` and `resources/user.js`.\n- ***resources/user.css*** - Add any custom CSS you wish to apply\n for `index.html`. (This convention allows you to get custom styling\n without modifying the sample index file.)\n- ***resources/user.js*** - Add any JavaScript you wish to use. (This\n convention allows you to get custom styling without modifying the\n sample index file.) Unless already invoked in `index.html`, you should\n call the `TextBrowser` constructor here. See *TextBrowser*'s\n `resources/user-sample.js` for a pattern you can copy and optionally\n adapt.\n- ***resources/user.json*** - Indicates meta-data for consumption by\n service worker\n- ***plugins/*** - While *not yet in use*, this is the convention we wish\n to begin enforcing for hosting plugins (e.g., for automated columns).\n See [Plugin Format](#Plugin Format).\n- ***sw.js*** - Although you can change the name of this file via\n `serviceWorkerPath` (see [JavaScript API](#JavaScript API)), this\n file should be at or higher than the files you are caching (including\n *TextBrowser*'s). Copying `sw-sample.js` as `sw.js` at your project\n root is the recommended approach.\n- ***data/*** - Directory recommended as a convention for holding JSON data\n files. It is also recommended that child directories be named for each\n file group, and within each file group, have the JSON data files\n as well as \"schema\" and \"metadata\" subdirectories containing the\n specific JSON schemas for each data file and the\n *TextBrowser*-specific meta-data files. See [JSON Formats](#JSON Formats).\n- ***files.json*** - See [JSON Formats](#JSON Formats).\n- ***site.json*** - See [JSON Formats](#JSON Formats).\n- ***locales/*** - Only needed if providing an alternate to *TextBrowser*'s\n own built-in `locales/`. It is recommended to rely on the default\n files and not add any custom files (contributing back here any\n localization fixes or additions you may have done!). See\n [JSON Formats](#JSON Formats).\n- ***languages.json*** - As with `locales/`, only needed if providing an\n alternate to *TextBrowser*'s own built-in `appdata/languages.json` file.\n It is recommended to rely on the default and not add any custom file. See\n [JSON Formats](#JSON Formats).\n\n## JSON Formats\n\nThe sections below begin with where you can find the JSON schema which\ndefines the format and an example file. They then follow with a\nplain language description of the format.\n\nOne meta-property shared among `files.json` and metadata files is\n`localeKey` which is a non-standard means of pointing to a key\nfor substitution. It may be replaced in the future by the slightly\nmore cumbersome though standards-track\n[JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03)s.\n\n### Work-Specific JSON\n\nJSON data files, the individual JSON schema file against which the data\nfile can be validated (and enhanced in a standard manner with type\ninformation), and our custom JSON metadata format file for indicating\ninformation such as designating fields for browsing ranges, are covered\nin this section.\n\n#### JSON Data\n\nJSON data files to represent your data (e.g.,\n[this file](https://bitbucket.org/brettz9/bahaiwritings/src/6b07fb41d11ed76570f7da03ffc9d11aa8ff0a5d/data/writings/peace.json?at=master&fileviewer=file-view-default))\nexpect 3 fields (per the simple\n[schema](https://github.com/brettz9/textbrowser/blob/master/general-schemas/table-container.jsonschema)\nand its simple\n[array-of-arrays subschema](https://github.com/brettz9/textbrowser/blob/master/general-schemas/array-of-arrays.jsonschema)\nto which they adhere):\n\n1. A `schema` JSON reference pointer to your data's JSON schema.\n See [JSON Schema](#JSON Schema).\n2. A `metadata` JSON reference pointer to your data's JSON metadata.\n See [JSON Metadata](#JSON Metadata).\n3. A `data` property which is an an array of arrays containing your tabular\n text itself. This property must adhere to the specific JSON schema\n referenced in the `schema` property above for this file.\n\n#### JSON Schema\n\nThis document must itself be a valid\n[JSON Schema](http://json-schema.org/documentation.html)\nand must, moreover, adhere to the\n[table format schema](https://github.com/brettz9/textbrowser/blob/master/general-schemas/table.jsonschema).\n\nThis simple document, besides including the text content, designates a more precise JSON schema to indicate precise column types (e.g.,\n[this one](https://bitbucket.org/brettz9/bahaiwritings/src/6b07fb41d11ed76570f7da03ffc9d11aa8ff0a5d/data/writings/schemas/Bible.jsonschema?at=master&fileviewer=file-view-default)).\n\nThis schema is expected to designate an array of arrays, with the items\nof the inner arrays being more flexible JSON schemas representing individual\nfields of your works, but expecting a `type` and `title` in all cases.\n\nIt may, for integers, optionally also have `minimum` and `maximum` properties\nwhich can be used to set numeric inputs (assuming the min or max is not\ndependent on another value, as often will be paragraph numbers within\nchapters).\n\nFor strings, an optional `\"format\": \"html\"` can be present, though raw HTML in\nthe so-designated fields will only be output in the results display as HTML\nif the `TextBrowser` option `trustFormatHTML` is set to `true`. This\nis for security reasons in case an untrusted schema is being deployed, but\none will probably normally wish to set this to `true` for trusted data.\n\nAlso for string type fields may one use `enum`, and its values are\ncurrently used to determine field values (looking in the metadata\nfile under the localized `fieldvalue` object whose key is the column in which\nthe value occurs) which are used in place of the original content within\npull-down menus for selecting verse ranges and in the corresponding\ncolumn for the field of the results display. (The `fieldvalue-aliases`\nproperty of the specific field key of the main `fields` property will\nalso be checked in that file for indicating optional aliases of the given\nfield value.)\n\n#### JSON Metadata\n\n[Meta-data JSON](https://github.com/brettz9/textbrowser/blob/master/general-schemas/metadata.jsonschema) (e.g.,\n[this one](https://bitbucket.org/brettz9/bahaiwritings/src/6b07fb41d11ed76570f7da03ffc9d11aa8ff0a5d/data/writings/metadata/Bible.metadata?at=master&fileviewer=file-view-default))\nis required so as for you to indicate for the app how the multilinear text\nis to be browsed (e.g., which fields can be used as sequential\nchapter/paragraph/verse numbers, how its columns should be translated, etc.).\n\nThis file has two main properties, `table` and `fields`.\n\n`table` has two properties, `browse_fields` and `default_view`.\n\n`browse_fields` is a name-set object or an array of string field names or\nname-set objects. Name-set objects have an optional `name` string, a `set`\narray of field name strings, and an optional `presort` boolean to\nindicate whether the table must first sort the elements (in order of\nlisting); the default is to follow the original array order.\n\nThe keys of `default_view` are field names which point to a string or\ninteger, or array thereof. These are *not currently in use*, but are intended\nto indicate the values that will be used for a default range when a user makes\na form submission without supplying a range.\n\nFor `fields`, the `lang` string property indicates the language code for the\ncontent of this field. It is used for letting the user quickly enable\nfields which match their desired locale language(s). It is also used for\nsetting HTML table column `lang` values to properly display fonts for\nlanguages that leverage it, such as the CJK languages.\n\nOne other set of types for `fields` are `name` and `alias` strings (or\n`localeKey` pointing to strings). The `name` points to the regular\nname for the column, whereas `alias` is currently used to point to an\nalias name of the field (more specifically to an alternate name after\nconverting its values via `fieldvalue-aliases`). The boolean or string\n`prefer_alias` property in turn determines whether this alias will be\nused by default (currently if it is `false`, it is not used at all).\nThis functionality might be moved into a plug-in in the future.\n\nAlso in `fields`, `fieldvalue-aliases` can after any `localeKey` processing,\nbe an object of field name keys pointing to an array of alias names (as\nstrings or integers) or to an object whose keys indicating the type of\nalias and string values. This can provide alternate values for what is\nactually present in the data table (e.g., replacing numeric codes with\nhuman-readable strings).\n\nFor `fields`, the `primary_text_field` and `orig_lang_field` booleans\nand `orig_langs` array of string language codes are *not currently in use*\nbut intended to indicate the main work under consideration (as opposed\nto translations), whether it is the source of translations or a target\ntranslation, and what its source languages are (if not itself marked as\nan original language).\n\nThe `roman` property of `fields` is intended to indicate Roman numerals.\nIt is *not currently in use* and where not automated from Arabic numerals,\nit might be indicated in the future via a language code and more generic\n`numeric` property (so as to support multiple non-Arabic counting systems\nwhich are hard-coded as opposed to built via an automated plug-in).\n\nAs with other files, there is also a `localization-strings` key object, keyed\nto language code, which is keyed to an object of keys (which can be strings\n(e.g., `heading` or `alias`), arrays of strings, or other objects of keys,\nincluding specifically for JSON metadata, `fieldnames`, `fieldaliases`,\n`fieldvalue`, and `fieldvalue-aliases`).\n\n### Application-wide JSON files\n\nBesides the JSON files directly representing your works, you will need the\nfollowing files to indicate behavior for the text-browsing application as a\nwhole.\n\n#### `files.json`\n\nThis format is defined by [this](https://github.com/brettz9/textbrowser/blob/master/general-schemas/files.jsonschema).\nSee [this file](https://bitbucket.org/brettz9/bahaiwritings/src/5f2602f122134d2013e013a477ae94ee29548a13/files.json?at=master&fileviewer=file-view-default) for an example.\n\nIt allows you to point the application to the data files you desire for\ninclusion (e.g., any kept in `data/`).\n\nThe optional string properties `schemaBaseDirectory` and\n`metadataBaseDirectory` at root apply to all groups.\n\n`groups` is a root array property whose items are file group objects whose\nkeys include the `id` string, the `name` string, the `directions` string\n(for indicating instructions), as well as optional, group-scoped,\n`schemaBaseDirectory` and `metadataBaseDirectory` properties.\n\nThe `files` array property contains object items with the following properties:\na `name` string or localization key (or a file group display name),\n`schemaFile` and `metadataFile` string file paths (resolved relative to the\nrespective base path properties), and `file` which is an reference to a\nspecific JSON data file\n[table-container.jsonschema](https://github.com/brettz9/textbrowser/blob/master/general-schemas/table-container.jsonschema)).\nThere can also be a `shortcut` property which is used for indicating the\nkeyword to use when the \"Generate bookmarks\" button in Preferences or\n\"Copy shortcut URL\" is used to build URL keyword shortcuts (what Chrome\nconsiders a custom search engine).\n\nAs with other files, there is also a `localization-strings` key object, keyed\nto language code, which is keyed to an object of keys (which can be strings,\narrays of strings, or other objects of keys, including specifically for\n`files.json`, the object property `workNames` whose keys are work names, and\n`plugins` whose keys are plugins and whose object values have a `fieldname`\nkey).\n\nThe `plugins` object property indicates scripts in metadata.\n\nIts keys are plug-in names and whose value objects have the required property\n`path`, and the optional properties `onByDefault` boolean and `lang` language\ncode string. There may also be a `meta` key which is used to pass data to the\nplug-in. This object currently only allows string keys.\n\nSee [Plugin Format](#Plugin Format) for the structure of the plug-in pointed\nto by the path.\n\nThe `plugin-field-mapping` object property has keys which act as groups and\nwhose object key values include works as keys and whose key values include\nfield names as keys and whose key values includes field arguments, namely:\n\n- `placement` (the string `\"end\"` or a number to indicate placement relative\n to other properties; this might be changed to a string indicating field\n name)\n- `applicable-fields` an object property whose properties are field names\n pointing to an object key value with properties that may vary with plug-in,\n but which specifically reserve a `targetLanguage` language code string\n property (or array of strings or the special string `{locale}` to indicate\n the value will vary be determined by the current locale) and a\n `onByDefault` boolean property. There is also a `meta` property object\n whose key values must currently only be strings.\n\n#### `languages.json` and `locales/en-US.json`, etc.\n\nAlthough we hope you may contribute back to our project any project-independent\nchanges you may need of the generic localizations within `locales/` and\n`appdata/languages.json`, if you need to provide your own interface\nlocalization, you may supply a `languages` property when creating the\n`TextBrowser` object to point to a languages JSON file of your own\nchoosing (see the [JavaScript API](#JavaScript API)).\n\n*TextBrowser* comes with the `languages.json` file at\n[`appdata/languages.json`](https://github.com/brettz9/textbrowser/blob/master/appdata/languages.json) which, as mentioned, is used by default. It adheres to\n[this schema](https://github.com/brettz9/textbrowser/blob/master/general-schemas/languages.jsonschema)\n\nIf you need to implement your own, the properties include the string\n`localeFileBasePath` and the property `languages` which is an array\nof objects containing the properties, `name`, `code`, `direction`,\nand `locale` (the latter leads to a locale file).\n\nAs with other files, there is a `localization-strings` object, keyed to\nlanguage code, which is keyed to an object of keys (which can be strings,\narrays of strings, or other objects of keys).\n\nThe locale files referenced by the `locale` property within `languages.json`\n(by default, those at `locales/`, e.g., `locales/en-US.json`), adhere to\n[this schema](https://github.com/brettz9/textbrowser/blob/master/general-schemas/locale.jsonschema).\n\nLocales are an object of keys (which may be strings, arrays of strings, or\nare themselves objects).\n\nNote that localization of specific file names and content, specific file\ngroups, and for your site navigation, on the other hand, are handled in\nthe other relevant sections of this document (see the `localization-strings`\nproperty within metadata files, `files.json`, and `site.json`, respectively).\n\n#### `site.json`\n\n*(This file is not yet fully utilized in the app)*\n\nThis file expects a top-level `site` array property indicating nesting of the\nsite's page hierarchy (intended to be used for site map generation). The file\nalso expects a `navigation` property (with the same allowable values, or even\na [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03)\npointing to `site`) to indicate the subset of this site\navailable on the navigation bar (an array with strings or nested child\narrays of strings). Besides creating a navigation bar, it is\nalso intended to be used to generate breadcrumbs, `<link rel=next/prev>` links,\nand a sitemap.\n\nAs with other files, there is a `localization-strings` object, keyed to\nlanguage code, which is keyed to an object of keys (which can be strings,\narrays of strings, or other objects of keys).\n\n## Plugin Format\n\nPlugin file designated within `files.json` may have any of the following\nexports. See the subsection below for details on arguments shared by multiple\nmethods.\n\n- `getCellData({tr, tableData, i, j, applicableField, fieldInfo, applicableFieldIdx, applicableFieldText, fieldLang, getLangDir, meta, metaApplicableField, $p, thisObj})` -\n Used to build the plugin field's cell contents. The return value will\n set `tr[j]` unless the return is falsy in which case `applicableFieldText`\n will be used. Invoked for each cell of the data. To return HTML, must use\n in conjunction with `escapeColumn: false`. Besides properties shared with\n other methods, `getCellData` is passed the following:\n - `tableData` - The entire set of table data as an array of arrays (of\n strings and/or integers), containing non-plugin content and any\n already processed plugin contents.\n - `i` - The 0-based row integer.\n - `tr` - Equivalent to `tableData[i]`\n - `fieldInfo` - Array of info about all fields; has the following\n properties if not a plugin:\n - `field` - The schema `title` if not a plugin\n - `fieldAliasOrName` - Obtained by finding alias if present\n or the `field` otherwise\n - `escapeColumn` - `true` if schema `format` is not `\"html\"`\n - `fieldLang` - The `lang` of the metadata object for `field`\n If it is a plugin, will have the following properties:\n - `plugin` - The `files.json` plugin object\n - `meta` - The plugin `meta`\n - `placement` - As with `plugin-field-mapping` `placement` but\n with `\"end\"` replaced with `Infinity`\n - `fieldAliasOrName` - The result of `getFieldAliasOrName` on\n the plugin if present or the localization of the `plugins`'\n `fieldname`\n - `escapeColumn` - `true` if the plugin's `escapeColumn` is not `false`\n - `onByDefault` - The `applicableField`'s `onByDefault` if a boolean,\n the current plugin's if truthy and `false` otherwise\n - `applicableField` - The `applicable-fields` field\n - `metaApplicableField` - The `meta` of the `applicable-fields` field\n - `fieldLang` - The `targetLanguage`\n - `applicableFieldIdx` - The `fieldInfo` item whose `field` property is equal to `applicableField`.\n - `applicableFieldText` - Equivalent to `tr[applicableFieldIdx]`\n - `fieldLang` - The `fieldLang` property of `fieldInfo[j]`\n - `getLangDir` - A method from\n [`rtl-detect`](https://github.com/shadiabuhilal/rtl-detect)\n for determining directionality (\"rtl\" or \"ltr\") for a given\n language code. May be useful with\n `fieldInfo[applicableFieldIdx].fieldLang`\n- `escapeColumn` - Boolean (defaults to `true`). If set to `false`, will avoid\n escaping, though the plugin rendered cell data should be trusted to avoid\n possible cross-site scripting.\n- `done({$p, applicableField, meta, j, thisObj})` - Invoked after all cells of\n the table have been processed.\n- `getTargetLanguage({applicableField, targetLanguage, pluginLang, applicableFieldLang})` -\n Called for each plug-in. The return value will be used for setting the\n `lang` of the plug-in field. May return `{locale}` to indicate the\n language should follow the locale. The supplied `targetLanguage` is any\n `targetLanguage` property found on the `plugin-field-mapping`'s'\n `applicable-fields` field. `pluginLang` is the (default) `lang` for\n the plug-in (from `files.json`). `applicableFieldLang` is the default\n lang when there is no target language or plugin lang; it is the `lang`\n of the applicable field.\n- `getFieldAliasOrName({locales, lf, targetLanguage, applicableField, applicableFieldI18N, meta, metaApplicableField, targetLanguageI18N})` -\n Called for each plug-in (after `getTargetLanguage`). Sets the `fieldInfo`\n `fieldAliasOrName` which is used for labeling the field. Besides\n properties shared with other methods, `getFieldAliasOrName` is passed\n the following:\n - `locales` - The app `lang` array (URL-specified `lang` languages or\n fallback-specified ones from `navigator.languages` that are\n supported by the app)\n - `lf` - An [imf](https://github.com/brettz9/imf) locale formatter based\n on `files.json` locale strings.\n - `applicableFieldI18N` - The localized metadata `fieldnames` `applicableField`\n - `targetLanguageI18N` - The localized name of `targetLanguage`\n - `targetLanguage` - The result of `getTargetLanguage` (or the\n `targetLanguage` argument to it if not present)\n\n### Properties\n\nA number of properties are passed to multiple plug-in methods:\n\n- `$p` - Usable for getting URL parameters\n- `applicableField` - The field indicated in `files.json` as being\n applicable to the plugin.\n- `meta` - See the property from `fieldInfo`\n- `thisObj` - The `TextBrowser` instance\n- `j` (`i` is for column) - The 0-based column integer.\n- `metaApplicableField` - See the property from `fieldInfo`\n\n## Security notes\n\nWhile some mechanisms exist to escape HTML, there are nevertheless some means\nat present by which a malicious data file could perform XSS attacks. Please\nensure the data files (and schemas/metadata files) you indicate are trusted.\n\n## JavaScript API\n\nThe following indicates the JavaScript options that can tweak your\napplication's behavior beyond that determined by your JSON and schema files.\n\nSee `resources/user-sample.js` for an example (where the sample paths\nare assumed to be relative to a package that contains *TextBrowser*\nas a `npm` dependency).\n\n- ***new TextBrowser(options)*** - Constructor which takes an options object\n with the following optional properties:\n\n - `namespace` - Namespace to use as a prefix for all `localStorage`,\n caching, or `indexedDB` usage. Defaults to `\"textbrowser\"` but this\n could clash with other *TextBrowser* projects on the same origin,\n so you should change for your project. (This setting might be used in\n the future for any other namespacing.)\n\n - `files` - Path for the `files.json` containing meta-data on the files\n to be made available via the interface. Defaults to `\"files.json\"`.\n\n - `languages` - Path for the `languages.json` file containing meta-data\n on the languages to be displayed in the interface. Defaults to\n the `TextBrowser` project's `\"appdata/languages.json\"`.\n\n - `site` - Path for the `site.json` containing meta-data on the site.\n Defaults to `site.json`. (Only used currently for localization,\n but may in the future provide surrounding navigation information\n such as breadcrumbs.)\n\n - `userJSON` - Points to the user JSON file, `resources/user.json`\n by default. See the \"User JSON\" subsection below.\n\n - `stylesheets` - Array of stylesheet paths and/or of two-item arrays\n with stylesheet path and\n [loadStylesheets](https://github.com/brettz9/load-stylesheets)\n options. A string path may also be `@builtin` which attempts to load\n the default stylesheet without need for path (but due to current\n browser limitations with a lack of import meta-data, we cannot\n provide this accurately for all configurations at the moment).\n\n - `serviceWorkerPath` - Service worker path which defaults to\n `\"sw.js\"` (which, if you are including *TextBrowser* via npm,\n will be within your own project root). This should probably not\n be adjusted (and if you do want to adjust it, it may be better\n to file an issue or PR to allow us to provide choices among\n various default-available service worker/caching patterns).\n\n - `dynamicBasePath` - Base bath for the server hosting the TextBrowser\n content. Defaults to the current site.\n\n - `localizeParamNames` - Boolean as to whether to localize parameter\n names by default (can be overridden by the user in preferences).\n (This has not been fully tested.)\n\n - `allowPlugins` - Enables `files.json`-specified plugins to be run.\n Defaults to `false` as it causes scripts to be run, but if you trust\n your JSON source files, you will presumably wish to enable this\n to get the full functionality designated within the JSON (and add\n the script files designated in `files.json` to your project).\n\n - `trustFormatHTML` - If `true`, inserts fields designated by your\n JSON schema as `\"format\": \"html\"` as HTML without escaping; this\n option is off by default in case the source is untrusted,\n but if your `files.json`-indicated files are trusted, you will\n probably want to this set to `true`.\n\n - `requestPersistentStorage` - Defaults to `true`. Set this to\n `false` if you don't want to even ask for permission to store\n the data files persistently. Note that this can really degrade\n performance, especially with large data files, as the whole data\n file must otherwise be downloaded for each result display.\n\n - `noDynamic` - If there is no server-side component to expedite\n non-indexedDB queries\n\n - `skipIndexedDB` - If one wishes to force avoiding indexedDB even\n when permitted by user (for testing)\n\n - `hideFormattingSection` - Boolean as to whether to hide the formatting\n section by default (can be overridden by the user in preferences).\n This section might be changed to a plugin in the future in which case\n you'd just avoid designating it within `files.json`.\n\n - `interlinearSeparator` - HTML code to be injected between each\n interlinear entry; this is not exposed to the user for\n security reasons (preventing [cross-site scripting](https://en.wikipedia.org/wiki/Cross-site_scripting)\n attacks); defaults to `<br /><br />` though one may set to\n another string such as `<hr />`. If you need greater control,\n you might consider monkey-patching the simple templating function\n `Templates.resultsDisplayServerOrClient.interlinearTitle` (and\n optionally setting `interlinearSeparator` to an empty string if\n you use that function to handle the separation), but please note\n that this API could change. We may add some predefined choices for\n users in the future.\n\n - `showEmptyInterlinear` - Whether to show empty interlinear entries\n (with a title). We may put this under user control in the future.\n\n - `showTitleOnSingleInterlinear` - If only the main item is present in\n an interlinear-enabled column, this determines whether a title (if\n enabled) will be shown. We may put this under user control in the\n future.\n\nAs per [semantic versioning](http://semver.org/) used by `npm`,\nour API should continue to work until an increment in the major release\nnumber.\n\nThe rest of the API used internally is unstable and should not be relied\nupon for monkey-patching.\n\n### User JSON\n\nWorker config should be placed in a JSON file (see\n[`resources/user-sample.json`](./resources/user-sample.json)).\nThe properties are:\n\n- `namespace` - See above.\n- `files` - See above.\n- `languages` - See above.\n- `basePath` - Base path to `files.json` fetches.\n- `userStaticFiles` - Array of files additional to those of\n *TextBrowser* which you will need offline. Defaults to the minimum\n recommended files:\n `['/', 'index.html', 'files.json', 'site.json', 'resources/user.js', 'resources/user.css']`\n\n## Server API\n\nThe `textbrowser` server API offers the same arguments as the `TextBrowser`\nconstructor (minus `site`, `stylesheets`, `requestPersistentStorage`, `noDynamic`,`skipIndexedDB`, and `hideFormattingSection`). In addition,\nit supports the following arguments:\n\n- `domain` - The domain for hosting the server. Defaults to `localhost`.\n- `port` - The port on which the server will be hosted. Defaults to 8000.\n- `nodeActivate` - This argument must be run once to build the necessary\n database files. While the database files will be SQLite based, they\n are consumed by [IndexedDBShim](https://github.com/axemclion/IndexedDBShim/).\n\n## To-dos (Highest priority)\n\n1. Document and add **screen-casts** along with one for developers showing\n JSON format, metadata, and schemas); also use with shortcuts (including\n Bahá'í Library Online ones)\n1. Fix so as to ignore other items of query string such as `?fbclid=...`\n from Facebook.\n0. Progressive web app? / Electron?\n1. Adapt approach of <https://suttacentral.net/offline> in providing form for\n choice of items to offline (also add to individual work pages).\n1. Mention idea that it works offline\n1. **Default field(s) and default value(s)** for when no text is entered and\n a reasonable sample is desired to be shown. Use `default_view` already\n spec'd in metadata schema and used in files.\n 1. Also have `&checked1=Yes` omitted when generating results display\n (since now defaulting to this)\n 1. Drop unused fields in URL by default\n1. Switch from IMF i18n to [intl-dom](https://github.com/brettz9/intl-dom) and\n as needed [i18nizeElement](https://github.com/brettz9/i18nizeElement)\n1. Ensure works with `pnpm` in all environments (didn't work when deployed,\n but would need to recall the problem and resolve)\n1. Simplify `languages.json` by using `Intl.DisplayNames` (`type: 'language'`)\n to localize language names (and can avoid direction if\n [intl-locale-info proposal](https://github.com/tc39/proposal-intl-locale-info)\n is implemented); consider using with plugins so can, e.g., show language\n visibly into which a targeted content language field was translated\n1. For plugins, allow export of `stylesheets` array to add to\n `loadStylesheets`, so they don't have to do the importing and executing.\n1. **Progress meter** with hidden console to avoid intimidating loading\n messages of service worker; also retrieve latest in `CHANGES.md`!\n1. **Move \"Go\"** to right (or immediate bottom) of paragraph selections\n1. Overflow on cells past a certain height—especially for indexes\n1. In place of passing in `files`, `namespace` and `languages`, pass\n in `userJSON`\n1. If get [MapText](https://github.com/brettz9/maptext) working, could\n actually extract out image portion(s) into table cell to show the\n original Tablet portion alongside commentary, etc. (along with\n MapText tooltips and text copy ability to get at the real text\n from the images; ideally any global search would be able to reach\n into these as well, though that will probably just duplicate what\n is already in the corresponding JSON store as a regular text column).\n1. **Text box parsing**\n 1. Document availability of this parsing\n 1. Fix limitation that 0's don't change to 1's if\n not present as a minimum (e.g., if no 0 for Chapter\n number, then won't show anything).\n 1. Avoid need for separate `<work name>-startEnd` for browse set;\n e.g., parse Rodwell or Sale?\n 1. Ideally work across even book\n 1. Support anchor portion (e.g., `1:2:3-1:2:5#1:2:4`)\n1. **Move plug-in set-up** to run so setting indexedDB within\n `activateCallback.js`\n1. Have **IndexedDB handle all pages** language select, work select, and\n work display be part of too?\n 1. `indexedDB` for JSON data\n1. **Node.js** (or PHP?)\n 1. Delivery of HTML content by same URL so third parties can\n consume without JavaScript and optimized when not offline\n 1. [Progressive enhancement is faster](https://jakearchibald.com/2013/progressive-enhancement-is-faster/)\n 1. Optimize Jamilih to build strings (for performance and also for\n server) and utilize here; also to preprocess files like our\n templates to convert Jamilih to complete string concatenation\n as is somewhat faster\n 1. Serve JSON files immediately and then\n inject config for `index.js` to avoid reloading?\n 1. Use [IndexedDBShim](https://github.com/axemclion/IndexedDBShim)\n (with service worker shim?) to optimize on server\n1. Icon for click/hover to get **interlinear field explanation**\n1. Fix for **local notes storage plugin** when in interlinear column\n1. Fix for **interlinear not showing** when opting for non-default\n \"Field Title\" in pull-down.\n1. Fix for **\"Save settings as URL\"** not properly serializing plug-in\n columns\n1. Allow **localization of URL parameters** to optionally work with any\n language (or at least the locale and default/English)\n1. Fix sometime **obscuring of headings**\n1. **Document**\n 1. Need of setting certain locale strings, including `sites.json`.\n1. Use schema-detection of type for sorting--integer\n parsing only on URL params per schema); see\n `resultsDisplayServerOrClient.js` with to-do by `parseInt` (and\n also see `String()` conversions)\n1. Get file names to be namespaced to group name to avoid name clashes\n1. **Locales**\n 1. Check `localizeParamNames` (preference)?\n 1. Test all locales and works and combos\n1. Allow **all text** to be shown (whether anchored or not)\n1. Indicate min/max as **placeholder text** (`Max: 100`?)\n1. **Rename \"Field\"** to \"Column anchor\"\n1. Renaming/linking to fuller descriptions or graphics explaining\n options/preferences regarding locale, interlinear, CSS\n1. **Plugins/Automated** fields\n 1. **Extensibility** (note: Some below may already be implemented)\n 1. Implement (worker-sandboxed (and parallel async-loading per\n row/cell?)!)\n 1. Admin/files-driven and ideally user-driven (though security issue\n for additive approach); could let plugin itself accept user input\n 1. Additive or reductive (omitting/merging)\n 1. Columns or rows\n 1. Admin-controlled merging/omission of columns like\n interlinear\n 1. Merging rows with same number\n 1. Metadata for default field column placement and table/field\n applicability\n 1. Browse fields or field list\n 1. Modifying existing content or not\n 1. Splitting columns (e.g., by line break)\n 1. Splitting rows by element (e.g., `<hr />`)\n 1. With optional `rowspan`/`colspan` for non-split portions\n of row/column\n 1. Overlays\n 1. Levels of applicability\n 1. Automated whole document/table-level or column-level\n changes (e.g., word counts) or even row-level/cell-level\n (including language code)\n 1. Spans across section\n 1. Provide example plugins of each type for this version if possible\n 1. Define all possible areas as plugins? e.g., Move\n search/CSS/interlinear, advanced formatting, or even browse fields\n and/or field lists and/or search as a whole to plugins?\n If doing so for individual fields in field lists, should support\n adding, e.g., pull-downs, even multiple ones for arguments\n (e.g., a web search plugin could specify the desired search engine)\n 1. Asycnchronous means of retrieving (and then caching, optionally on\n an interval) automated data; use of single Promise to each plug-in\n for whole table (or if necessary `Promise.all` on each row)?\n 1. **Caching for automated field content** like translations (with ability\n to rebuild)\n 1. **Collapsible columns** with click status remembered from last time as\n to whether collapsed or not\n 1. Specific **automated fields**\n 1. Previously implemented:\n 1. Option to show renamed fields (like \"Book #\" -> \"Book Name\"\n for Bible) before renaming (reimplement as additive plug-in\n but with one field on by default and the other off); already\n has placeholder in `files.json` - add to `field-alias.js`;\n already added to new version but need to reimplement as plugin\n 1. Synopsis, Roman numerals, Chinese numbers, word-by-word\n translation, auto-romanized Persian/Arabic, Persian with\n English tooltips, English with Persian/Arabic tooltips, ISBN\n for Collins (use JSON Schema `format` for link detection--might\n also reimplement ISBN to make use of JSON Schema format);\n text-to-(Google search, Google define, Wikipedia, etc.\n edit pages)-links\n 1. Auto-links by verse to relevant forums, wikis, blogs, or personal\n notes pertaining to a given verse; also Q&A and (federated)\n social media\n 1. Offers advantage of not needing to reinvent login control\n 1. Built-in (including offline or only offline) note-taking\n (local/remote and wiki WYSIWYG with Git version control?);\n modular loading of others' notes?\n 1. Back-links for index entries (which needs its own JSON Schema-based\n project for the hierarchical representations (see\n [TEI](http://www.tei-c.org/release/doc/tei-p5-doc/en/html/CO.html#CONOIX)\n for ideas)) including optionally merging them for different books\n 1. Support metadata to omit or combine fields during browsing (like\n checkboxes and interlinear field, but admin-set; also ensure, or\n add option for, no line breaks or indication of original source\n column within interlinear display so not bloating or surfacing\n internal column differences to users); increment counts despite\n some surfacing, as better ensures future compatibility/portability\n 1. Automated field to split up rows based on presence of `<hr />` or\n `<a id=>`, etc., with the ability to browse by such numbers (would\n ideally tap into browsing autocomplete code indicating min/max\n too). Optionally get `rowspan`s (or even `colspan`s) for additional\n columns (e.g., a field spanning by whole pages of a book and\n another field spanning only by paragraphs) - use some kind of\n counter and don't display the HTML until finished cycling??; also\n figure out how to reassemble if the minute fields are not needed\n (e.g., if the user only wants to see the text by paragraph and\n not anything related to by page); will provide a new browsing\n column and also divide certain existing one(s)\n 1. Allow automated algorithm to merge, remove rows (e.g., intro\n section of text with same \"0\" number)\n 1. Splitting columns by line break, etc.\n 1. Means on results display page to highlight (including\n discontiguous) selections and convert this into a new selection\n and/or syntax (generic to *TextBrowser* and/or canonical, ideally\n human-readable based on JSON-supplied information; e.g., for the\n Bible, `Matt. 5:10-12`); use with `postMessage` to-do to supply\n syntax back to another site; see\n [Scroll To Text fragment](https://wicg.github.io/ScrollToTextFragment/);\n [Stack answer](https://stackoverflow.com/a/62162093/271577)\n 1. Correct any field easily by links within TB to editing interface\n 1. Add an \"overlay\" column like interlinear, but which overlays by\n tooltip if any data is present; can also use metadata if the\n overlay is within-cell (and this metadata can also be used for\n putting overlay data in its own column too, albeit with only\n partial mapping to the other columns, e.g., if our \"Baha'i\n translation\" had not already been put into its own column, a\n metadata mapping may only have been for two discontiguous\n sentences out of a paragraph, but could still show such sentences\n reassembled (with some kind of separator) in a paragraph-based\n cell)\n 1. Deal with other metadata/automated (besides overlays) which is\n intended to allow collapsing of ranges (above paragraph cells,\n but may overlap); do as multiple tbodies but needs to be done\n dynamically since may wish alternate (and nestable) collapsing\n (e.g., collection->book->chapter, user-contributed metadata\n sections, etc.); allow collapsing/expanding of all fields by\n one click button outside table (or by level); allow automated\n collapsing based on sequentially exact values (e.g., until\n rows stop having a column with value \"1\")\n 1. Allow collapsing even within cells (as with overlays) (like\n our \"Baha'i Translation\" could have been). Also make\n non-metadata regions collapsible so can hide them from view.\n 1. Allow something to be prefixed to interlinear number to\n indicate the field should be treated as an overlay (tooltip);\n if so, may need tooltip to be in blocks in case multiple\n columns added. But also need to have section for automated\n fields separate from the regular fields for those fields\n which do not map exclusively by cell boundaries (or\n relatively within them).\n 1. Allow types of overlays (or \"mashes\") such as underlays (adding\n invisible metadata), onlays/\"mash ons\" (replacing text in\n place), as well as regular overlays (adding text via\n mouseover); let these be alterable as possible by the user\n (e.g., text might be desirable to replace existing text or\n put it as a mouseover)\n 1. Allow for dynamic addition of JSON overlay sources or metadata\n to work selection/work display files?\n 1. See bahaiwritings project re: using Firefox's\n [Browser API](https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API)\n to allow independent navigation controls for each iframe (and\n side-by-side viewing of verses/lines and commentary)\n\n## To-dos (High Priority)\n\n1. Waiting ([JSON UI Schema](https://github.com/json-schema-org/json-schema-spec/issues/67)\n or [JSON Schema Annotation and Documentation Extension](https://github.com/json-schema-org/json-schema-spec/issues/136)):\n i18n: Utilize more standard mechanism instead of our `localeKey`;\n might also use substitutable JSON References (see\n <https://github.com/whitlockjc/json-refs/issues/54#issuecomment-169169276>\n and <https://github.com/json-schema-org/json-schema-spec/issues/53#issuecomment-257002517>).\n 0. Remove need for separate metadata files per\n <https://github.com/json-schema-org/json-schema-spec/issues/587#issuecomment-389726603>\n by using initial `$`?\n1. Find way to avoid need for `!important` in column CSS\n1. Redirect automatically by accepted language, though have a link or\n preference to change the default\n1. Offer more **border styling** tuning controls (including right/left/top/bottom,\n color, etc.); then offer this along with other styles if we replace CSS\n input box with pop-up styling form (like Advanced Formatting, but for columns)\n1. Refactoring: Try to use `deserialize` of `form-serialization` fork for\n initial population or hash change? (if not `FormData`)\n1. We should try to allow `onByDefault` and `placement` for non-plugin\n fields also\n1. [ES6 Modules in browser](https://jakearchibald.com/2017/es-modules-in-browsers/):\n Complete switch to imports over script tags (by updating dependencies to\n use ES6 modules too and then use them; json-refs is only left); can also\n avoid function-passing main functions as arguments\n 1. For json-refs, build on\n <https://github.com/whitlockjc/json-refs/pull/149> before\n ES dist. (Rollup or webpack CLI?) and `browser`/`module`\n 1. Apply <https://www.gnu.org/software/librejs/free-your-javascript.html>\n labels to provide machine-automated detection of licenses. (Adapt\n [LibreJS](https://www.gnu.org/software/librejs/) to work with\n WebExtensions, to support `<link>` in addition to visible links, and,\n if it is not already, make blocking of sites without open source code\n optional but notify one by icon so that one might know that a page is\n using (or not using) open source.)\n1. Add prior transpose functionality (affects header, footer, and body)\n1. Expose interlinear `showEmptyInterlinear` and\n `showTitleOnSingleInterlinear` to the user interface\n1. Uncomment and complete random code\n 1. random within specific part of browse field range (e.g., within a\n specific book)?\n 1. Have special meta-data for per book/chapter maximums (Bible/Qur'an)\n to allow accurate and also for random verses?\n 1. with context\n 1. Leverage this code for random to implement random feature across\n works within group or across all groups\n1. As with table/array-of-arrays schema, develop schema for\n outlines (and utilize, e.g., with JSONEditor)!\n1. Develop footnote targeting mechanism to hide/reveal footnotes inline\n (based on a `data-footnote` attribute or the like). Utilize JSON\n Schema `links` for indicating footnote location in document then\n allow HTML `<a href>` to point to the scheme designated therein.\n1. Search/Sorting\n 1. Add to preferences system for saved/favorite, recent\n searches/browses, etc.\n 1. Specific filtering by textbox next to checked field selection\n (commented out in workDisplay as not working yet in resultsDisplay)\n 1. Schema-aware and metadata-aware column sorting options (e.g., sort by\n order and ASC/DESC) with user customizability (i.e., presorting along\n with dynamic client-side after-load sorting, with or without search\n filtering; use \"search\" in locale to add this filtering to UI)\n 1. Option for highlighting search terms (with own styles), and/or if\n context is specified, to highlight rows with search results and\n alternatively style context rows (distinguish from random context?)\n 1. Optional links to go to previous/next results if only loading a subset\n of available content (allow customization of size of chunking in\n preferences as well as on the fly)\n 1. Support user-driven or automated (expandable) ellipses for surrounding\n content with option for highlighting these (e.g., to highlight a\n parts of a sentence, including one spanning multiple rows/verses);\n consider range for highlighting if verse range + added context range\n not enough; \"emphasis added\", \"passim\", customization of citations\n (moving caption to bottom)\n 1. Ability to run XPath/`querySelector`-like queries against\n `format: \"html\"` fields relative to specific cells (or against\n original source HTML or XML document); also highlighting as\n part of page anchor ala original XPath schemes (e.g.,\n `&anchor=.myClass` with `text()` from [HTTPQuery](https://github.com/brettz9/httpquery)\n to identify by text content too if not a full blown\n query/transformation language)?\n\n## To-dos (Medium Priority)\n\n1. Remove need for separate metadata\n files per\n <https://github.com/json-schema-org/json-schema-spec/issues/587#issuecomment-389726603>\n1. Remove `form-serialization` in favor of\n [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData)?\n1. Replace comma-separated interlinear approach with a popup dialog\n with multiselect\n1. Preview styling changes (or move all controls to results page for\n immediate real feedback)\n1. Separate **formatting within Jamilih code** to CSS; unit test and\n performance by being able to use a natively stringifying version of Jamilih\n (once complete)\n1. Utilize meta-data properties, `primary_text_field`, `orig_lang_field`,\n `orig_langs`, e.g., to allow for user to display main language and\n originals but not others? Use `hasFieldvalue` and `roman` (for\n non-automated Roman fields--could designate as Latin language, but\n need a way to know are numerals for sorting if Arabic numerals not\n provided)?\n1. URL (sorted) params keyed to `outerHTML` of page for caching\n1. Incorporate speech synthesis from\n <http://bahai.works/MediaWiki:Common.js>, allowing different\n speech voices for different rows or columns (or just let user\n add CSS to columns to mark). Could optionally display speech\n controls on results display page\n1. Callback options to replace or receive the results from each screen for\n further manipulation (e.g., to add navigation, pending or different from\n the intended `sites.json` behavior).\n1. Allow tables to be re-sortable via JavaScript which allows\n sorting by multiple columns with various data, etc.\n1. Build library (for browser or Node) to utilize `site.json` file to add\n site-wide navigation bar headers, breadcrumbs,\n `<link rel=next/prev/contents/etc.>`, sitemap, and page title (supplied\n argument of the current page)? Also about text and removecookies/\n choose a different language, and ability to optionally turn off in\n results display (e.g., so a table's results can be embedded off-site).\n1. Support JSON types for `outputmode`, opening\n new window with content-type set\n1. Node.js (and/or PHP)\n 1. Optionally allow server push and/or WebSockets updates of\n content and software\n 1. Allow centralized copies or distributed versioning,\n including single copy storage\n 1. Make tools to build `languages.json` based on available\n locale files, and build `files.json` based on a target directory.\n 1. [HTTPQuery](https://github.com/brettz9/httpquery) headers\n1. `filetypes.json` (from WebAppFind) for app and schema association?\n (files.json for permitted files - a file which could be auto-created,\n e.g., if server permits all in a directory); especially potentially\n useful with JSONEditor to allow editing of these files, app types\n (replacing assistant.php):\n 1. langs + locale / locale only\n 1. files/dbs->file (supply language choice)->file contents\n 1. schemas\n1. Code to populate locale files with missing localization strings and\n report the missing ones (and sort as such in assistant file); put\n assistant localization keys in own file?\n 1. Find translators to do further localization of the interface\n 1. Assistant file (for translating; needs server for password);\n work optionally with main locales, files, table, and field\n locale info. Use already-existing localization strings.\n 1. Add tooltips and table summaries, etc. back (see locale file for\n these and reapply any other unused) and add any missing ones\n describing how to use the elements\n1. Give option to user (as opposed to admin) for preset interlinear choices\n (e.g., separate by line breaks or page breaks)\n\n## To-dos (Lower priority)\n\n1. Waiting: Avoid superagent warning:\n <https://github.com/whitlockjc/path-loader/issues/17>\n1. **Remember columns enabled**, etc. since last visit, and/or saved as\n preferences.\n1. Allow copy-pasting a search as a custom web protocol (make\n site-configurable), e.g., to support `web+bahaiwritings:` links per\n [bahai-writings-handler](https://github.com/brettz9/bahai-writings-handler)\n ([demo](https://bahai-library.com/test-bahai-web-protocol/test-bahai-web-protocol.html));\n could even use last visit or preferences status to tweak the resulting\n appearance, column selection, etc.\n1. In schema, let `$locale` or `*` indicate all fields to be translated\n where possible?\n1. Preferences\n 1. Change Preferences to be set before work or with work but specific\n to it\n 1. Change Preferences to disallow URL overriding\n 1. Change preferred languages preference to be dynamic with work\n column languages\n 1. Preference to remember enabled checkboxes and formatting\n1. Change to utilize history.pushState?\n <https://developer.mozilla.org/en-US/docs/Web/API/History_API>\n1. Sort file selection listing per locale?\n1. Node.js synchronization of locale files?\n1. Could allow Node to built schemas, optionally allowing or disallowing\n unresolved JSON References.\n1. Might support arbitrary JSON and JSON Reference querying\n (if `files.json` configured to indicate a wildcard or something)\n1. Update \"about\" text and utilize on popup or something?\n1. Change \"Saving settings as URL\" to a redirect if faithfully\n copying everything?\n1. Provide option to skip over `langs.json` with a default language\n (though discourage since the UI translations may help some people).\n1. Allow user to pass array of language codes that can be checked\n at the beginning of the string without need for `lang=` (or for\n the i18n of \"lang\"?).\n1. `window.postMessage` API (since CORS is only for Ajax and\n `document.domain` is only for subdomains).\n1. Restore `tabindex` usage\n1. Restore option from work page to have a checkbox on whether to go to\n \"Advanced mode\", opening the styling options by default or not.\n\n## Testing\n\nIf you instead merely wish to test the current repository, you can:\n\n1. Clone the repository. Note, however, that we may periodically\nrebase the code, making it harder for one to keep up to date in this manner.\n2. Install the package's dependencies via:\n```shell\nnpm install\n```\n3. Test via:\n```shell\nnpm test\n```\n\nNote, however, that much of testing will depend on a particular\napplication. The [bahaiwritings](https://bitbucket.org/brettz9/bahaiwritings/)\nproject hosts validation of specific files expected by TextBrowser, such as\n`files.json` and specific schemas and meta-data files needed for that project.\n\nIf you merely wish to see the app running in a server, you can run:\n\n```shell\nnpm start\n```\n\nIf you do not wish to automatically open a tab each time the command is\nrun, use:\n\n```shell\nnpm run start-no-open\n```\n\nYou can also use this latter option to run the browser tests\n(from <http://127.0.0.1:8080/test/>).\n\n## Contributing\n\nPRs are most welcome, including for additional languages/locales.\n\nTests will ideally be run before submission of a PR.\n\nAt present we only have schema validation and lack UI and unit\ntesting coverage (PR's welcome for this too!).\n\nNote that we hope to create an extensible plug-in system, so\nenhancements to the core ought to be confined to the\nmain project goals and be oriented toward reuse across all\nprojects, relegating any specialized tools to plugins (though\nwe can set up the wiki to point to your plugins once a plugin\nsystem may be in place).\n\n## History\n\nOne PHP/MySQL-based version was released in 2005-12-22 and was my\nfirst project used in aiding my learning programming.\n\nIt was hosted at <http://bahai-library.com/browser/> and\n<https://bahai9.com/browse0.php>\n\nOn Bahá'í Libary Online, the Web Archive indicates its presence as far back\nas 17 May 2006:\n\n- <http://web.archive.org/web/20060517012851/http://bahai-library.com:80/browser/browse0.php>\n- <http://web.archive.org/web/20060505010948/http://bahai-library.com:80/browser/browse0.php?langu=en>\n- <http://web.archive.org/web/20060430170322/http://bahai-library.com:80/browser/browse.php?langu=en&file=Bible>\n\nIt was broken (or offline) for long periods of time after an upgrade of PHP\napplied to the server broke the old code and for which I did not find time\nto work around.\n\n## About\n\nThis initiative is associated with the\n[BADI](https://groups.yahoo.com/neo/groups/badi/info)\nmailing list created to foster collaboration among open source projects\nand initiatives such as this which are Baha'i-inspired but will or may be\nof interest to the wider software community as well.\n"
102
+ }
@@ -137,7 +137,7 @@ async function requestPermissions (langs, l) {
137
137
  // rememberRefusal();
138
138
  resolve();
139
139
  return;
140
- // eslint-disable-next-line radar/no-duplicated-branches
140
+ // eslint-disable-next-line sonarjs/no-duplicated-branches
141
141
  case 'default':
142
142
  resolve();
143
143
  return;
@@ -33,9 +33,14 @@ export const getMetaProp = function getMetaProp (lang, metadataObj, properties,
33
33
  // file.anyOf.splice(1, 1, {$ref: schemaFile});
34
34
  // Todo: Allow use of dbs and fileGroup together in base directories?
35
35
  export const getMetadata = async (file, property, basePath) => {
36
+ const url = new URL(basePath || getCurrDir());
37
+ url.search = ''; // Clear out query string, e.g., `?fbclid` from Facebook
38
+ url.pathname = file;
39
+ url.hash = property ? '#/' + property : '';
40
+
36
41
  return (await JsonRefs
37
42
  .resolveRefsAt(
38
- (basePath || getCurrDir()) + file + (property ? '#/' + property : ''),
43
+ url.toString(),
39
44
  {
40
45
  loaderOptions: {
41
46
  processContent (res, callback) {
@@ -252,7 +252,9 @@ export const registerServiceWorker = async ({
252
252
  let r;
253
253
  try {
254
254
  r = await navigator.serviceWorker.register(
255
- serviceWorkerPath
255
+ serviceWorkerPath, {
256
+ type: 'module'
257
+ }
256
258
  );
257
259
  } catch (err) {
258
260
  console.log('serviceWorkerPath', serviceWorkerPath);
@@ -41,7 +41,6 @@ export default async function workDisplay ({
41
41
  ? key => l(['params', 'indexed', key])
42
42
  : key => key;
43
43
 
44
- // eslint-disable-next-line unicorn/prefer-prototype-methods -- Convenient
45
44
  const localeFromLangData = languages.localeFromLangData.bind(languages);
46
45
  const imfLang = IMF({
47
46
  locales: lang.map(localeFromLangData),
@@ -13,14 +13,9 @@ function ownKeys(object, enumerableOnly) {
13
13
 
14
14
  if (Object.getOwnPropertySymbols) {
15
15
  var symbols = Object.getOwnPropertySymbols(object);
16
-
17
- if (enumerableOnly) {
18
- symbols = symbols.filter(function (sym) {
19
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
20
- });
21
- }
22
-
23
- keys.push.apply(keys, symbols);
16
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
17
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
18
+ })), keys.push.apply(keys, symbols);
24
19
  }
25
20
 
26
21
  return keys;
@@ -28,19 +23,12 @@ function ownKeys(object, enumerableOnly) {
28
23
 
29
24
  function _objectSpread2(target) {
30
25
  for (var i = 1; i < arguments.length; i++) {
31
- var source = arguments[i] != null ? arguments[i] : {};
32
-
33
- if (i % 2) {
34
- ownKeys(Object(source), true).forEach(function (key) {
35
- _defineProperty(target, key, source[key]);
36
- });
37
- } else if (Object.getOwnPropertyDescriptors) {
38
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
39
- } else {
40
- ownKeys(Object(source)).forEach(function (key) {
41
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
42
- });
43
- }
26
+ var source = null != arguments[i] ? arguments[i] : {};
27
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
28
+ _defineProperty(target, key, source[key]);
29
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
30
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
31
+ });
44
32
  }
45
33
 
46
34
  return target;
@@ -2182,7 +2170,12 @@ const getMetaProp = function getMetaProp(lang, metadataObj, properties, allowObj
2182
2170
  // Todo: Allow use of dbs and fileGroup together in base directories?
2183
2171
 
2184
2172
  const getMetadata = async (file, property, basePath) => {
2185
- return (await JsonRefs$1.resolveRefsAt((basePath || getCurrDir()) + file + (property ? '#/' + property : ''), {
2173
+ const url = new URL(basePath || getCurrDir());
2174
+ url.search = ''; // Clear out query string, e.g., `?fbclid` from Facebook
2175
+
2176
+ url.pathname = file;
2177
+ url.hash = property ? '#/' + property : '';
2178
+ return (await JsonRefs$1.resolveRefsAt(url.toString(), {
2186
2179
  loaderOptions: {
2187
2180
  processContent(res, callback) {
2188
2181
  callback(undefined, JSON.parse(res.text || // `.metadata` not a recognized extension, so
@@ -3699,6 +3692,176 @@ const setServiceWorkerDefaults = (target, source) => {
3699
3692
  return target;
3700
3693
  }; // (Unless skipped in code, will wait between install
3701
3694
 
3695
+ /* eslint-env worker */
3696
+ const {
3697
+ ceil
3698
+ } = Math;
3699
+
3700
+ const arrayChunk = (arr, size) => {
3701
+ return [...Array.from({
3702
+ length: ceil(arr.length / size)
3703
+ })].map((_, i) => {
3704
+ const offset = i * size;
3705
+ return arr.slice(offset, offset + size);
3706
+ });
3707
+ }; // Todo: If fetching fails here (or in install), e.g., because activate event
3708
+ // never completed
3709
+ // to cache, de-register and re-register (?); how to detect if all
3710
+ // files in cache?
3711
+ // Todo: Check `oldVersion` and run this first if still too old
3712
+
3713
+ /**
3714
+ * @callback Logger
3715
+ * @param {...any} args
3716
+ * @returns {void}
3717
+ */
3718
+
3719
+ /**
3720
+ * @param {PlainObject} cfg
3721
+ * @param {string} cfg.namespace
3722
+ * @param {string[]} cfg.files
3723
+ * @param {Logger} cfg.log
3724
+ * @param {string} [cfg.basePath=""]
3725
+ * @returns {Promise<void>}
3726
+ */
3727
+
3728
+
3729
+ async function activateCallback({
3730
+ namespace,
3731
+ files,
3732
+ log,
3733
+ basePath = ''
3734
+ }) {
3735
+ // Now we know we have the files cached, we can postpone
3736
+ // the `indexedDB` processing (which will work offline
3737
+ // anyways); also important to avoid conflicts with
3738
+ // already-running versions upon future sw updates
3739
+ log('Activate: Callback called');
3740
+ const r = await fetch(files);
3741
+ const {
3742
+ groups
3743
+ } = await r.json();
3744
+
3745
+ const addJSONFetch = (arr, path) => {
3746
+ arr.push((async () => (await fetch(basePath + path)).json())());
3747
+ };
3748
+
3749
+ const dataFileNames = [];
3750
+ const dataFiles = [];
3751
+ const schemaFiles = [];
3752
+ const metadataFiles = [];
3753
+ groups.forEach(({
3754
+ files: fileObjs,
3755
+ metadataBaseDirectory,
3756
+ schemaBaseDirectory
3757
+ }) => {
3758
+ fileObjs.forEach(({
3759
+ file: {
3760
+ $ref: filePath
3761
+ },
3762
+ metadataFile,
3763
+ schemaFile,
3764
+ name
3765
+ }) => {
3766
+ // We don't i18nize the name here
3767
+ dataFileNames.push(name);
3768
+ addJSONFetch(dataFiles, filePath);
3769
+ addJSONFetch(metadataFiles, metadataBaseDirectory + '/' + metadataFile);
3770
+ addJSONFetch(schemaFiles, schemaBaseDirectory + '/' + schemaFile);
3771
+ });
3772
+ });
3773
+ const promises = await Promise.all([...dataFiles, ...schemaFiles, ...metadataFiles]);
3774
+ const chunked = arrayChunk(promises, dataFiles.length);
3775
+ const [dataFileResponses, schemaFileResponses, metadataFileResponses] = chunked;
3776
+ log('Activate: Files fetched');
3777
+ const dbName = namespace + '-textbrowser-cache-data';
3778
+ indexedDB.deleteDatabase(dbName);
3779
+ return new Promise((resolve, reject) => {
3780
+ const req = indexedDB.open(dbName);
3781
+ req.addEventListener('upgradeneeded', ({
3782
+ target: {
3783
+ result: db
3784
+ }
3785
+ }) => {
3786
+ db.onversionchange = () => {
3787
+ db.close();
3788
+ const err = new Error('versionchange');
3789
+ err.type = 'versionchange';
3790
+ reject(err);
3791
+ };
3792
+
3793
+ dataFileResponses.forEach(({
3794
+ data: tableRows
3795
+ }, i) => {
3796
+ const dataFileName = dataFileNames[i];
3797
+ const store = db.createObjectStore('files-to-cache-' + dataFileName);
3798
+ const schemaFileResponse = schemaFileResponses[i];
3799
+ const metadataFileResponse = metadataFileResponses[i];
3800
+ const fieldItems = schemaFileResponse.items.items;
3801
+ let browseFields = metadataFileResponse.table.browse_fields;
3802
+ browseFields = Array.isArray(browseFields) ? browseFields : [browseFields];
3803
+ const columnIndexes = [];
3804
+ browseFields.forEach(browseFieldSetObj => {
3805
+ if (typeof browseFieldSetObj === 'string') {
3806
+ browseFieldSetObj = {
3807
+ set: [browseFieldSetObj]
3808
+ };
3809
+ }
3810
+
3811
+ if (!browseFieldSetObj.name) {
3812
+ browseFieldSetObj.name = browseFieldSetObj.set.join(',');
3813
+ }
3814
+
3815
+ const browseFieldSetName = browseFieldSetObj.name;
3816
+ const browseFieldSetIndexes = browseFieldSetObj.set.map(browseField => {
3817
+ // Need to convert to columns for numbers
3818
+ // to become valid key paths
3819
+ return 'c' + fieldItems.findIndex(item => item.title === browseField);
3820
+ });
3821
+ columnIndexes.push(...browseFieldSetIndexes);
3822
+ log('Activate: Creating index:', dataFileName, 'browseFields-' + browseFieldSetName, browseFieldSetIndexes); // No need for using `presort` as our index will sort anyways
3823
+
3824
+ store.createIndex('browseFields-' + browseFieldSetName, browseFieldSetIndexes);
3825
+ });
3826
+ const uniqueColumnIndexes = [...new Set(columnIndexes)];
3827
+ tableRows.forEach((tableRow, j) => {
3828
+ // Todo: Optionally send notice when complete
3829
+ // To take advantage of indexes on our arrays, we
3830
+ // need to transform them to objects! See https://github.com/w3c/IndexedDB/issues/209
3831
+ const objRow = {
3832
+ value: tableRow
3833
+ };
3834
+ uniqueColumnIndexes.forEach(colIdx => {
3835
+ objRow[colIdx] = tableRow[colIdx.slice(1)];
3836
+ }); // log('objRow', objRow);
3837
+
3838
+ store.put(objRow, j);
3839
+ });
3840
+ });
3841
+ });
3842
+ req.addEventListener('success', ({
3843
+ target: {
3844
+ result: db
3845
+ }
3846
+ }) => {
3847
+ log('Activate: Database set-up complete', db); // Todo: Replace this with `ready()` check
3848
+ // in calling code?
3849
+
3850
+ resolve();
3851
+ });
3852
+
3853
+ const onerr = ({
3854
+ error = new Error('dbError')
3855
+ }) => {
3856
+ error.type = 'dbError';
3857
+ reject(error);
3858
+ };
3859
+
3860
+ req.addEventListener('blocked', onerr);
3861
+ req.addEventListener('error', onerr);
3862
+ });
3863
+ }
3864
+
3702
3865
  /* eslint-disable import/no-commonjs */
3703
3866
 
3704
3867
  const http = require('http');
@@ -3818,10 +3981,7 @@ setGlobalVars(null, {
3818
3981
  }); // Adds `indexedDB` and `IDBKeyRange` to global in Node
3819
3982
 
3820
3983
  if (userParams.nodeActivate) {
3821
- global.fetch = fetch$1; // const activateCallback = require('../resources/activateCallback.js');
3822
-
3823
- const activateCallback = require('../dist/activateCallback-umd.js'); // eslint-disable-line node/global-require
3824
-
3984
+ global.fetch = fetch$1;
3825
3985
 
3826
3986
  (async () => {
3827
3987
  await activateCallback(_objectSpread2(_objectSpread2({}, userParamsWithDefaults), {}, {
package/server/main.js CHANGED
@@ -7,7 +7,7 @@ import getIMFFallbackResults from '../resources/utils/getIMFFallbackResults.js';
7
7
  import {setServiceWorkerDefaults} from '../resources/utils/ServiceWorker.js';
8
8
  // import setGlobalVars from 'indexeddbshim/src/node-UnicodeIdentifiers.js';
9
9
  import {Languages} from '../resources/utils/Languages.js';
10
- // import activateCallback from '../resources/activateCallback.js';
10
+ import activateCallback from '../resources/activateCallback.js';
11
11
 
12
12
  /* eslint-disable import/no-commonjs */
13
13
  const http = require('http');
@@ -94,8 +94,6 @@ setGlobalVars(null, {
94
94
 
95
95
  if (userParams.nodeActivate) {
96
96
  global.fetch = fetch;
97
- // const activateCallback = require('../resources/activateCallback.js');
98
- const activateCallback = require('../dist/activateCallback-umd.js'); // eslint-disable-line node/global-require
99
97
  (async () => {
100
98
  await activateCallback({...userParamsWithDefaults, basePath});
101
99
  console.log('Activated');