diff --git a/.gitignore b/.gitignore
index 47a0f302..264b5390 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@ _site
.bundle
tmp/
vendor
+node_modules
+package-lock.json
diff --git a/_config.yml b/_config.yml
index 23f5a66c..96a5f57c 100644
--- a/_config.yml
+++ b/_config.yml
@@ -26,7 +26,7 @@ plugins:
- jekyll-gist
- jekyll-feed
-exclude: [bin, CONTRIBUTING.md, README.md, tmp, work]
+exclude: [bin, CONTRIBUTING.md, README.md, tmp, work, assets/js/node_modules, assets/js/package-lock.json]
collections:
faqs:
diff --git a/_includes/column-2-search-endpoints.html b/_includes/column-2-search-endpoints.html
new file mode 100644
index 00000000..5f645ab3
--- /dev/null
+++ b/_includes/column-2-search-endpoints.html
@@ -0,0 +1,19 @@
+
+
+{%- comment -%}{%- endcomment %}
+
Search terms are combined with 'AND'.
Using js-search.
-
See its assistance notes.
+
See its assistance notes.
- Using its prefix-based search.
+ Using its "PrefixIndexStrategy".
So term "cat" is indexed as "c", "ca", and "cat".
This search is constrained to dev.folio.org only.
- See other search facilities
- for GitHub, FOLIO Wiki, etc.
A specific set of important other documents are also indexed.
diff --git a/assets/js/eslint.config.mjs b/assets/js/eslint.config.mjs
new file mode 100644
index 00000000..39435747
--- /dev/null
+++ b/assets/js/eslint.config.mjs
@@ -0,0 +1,10 @@
+import globals from "globals";
+import pluginJs from "@eslint/js";
+
+
+/** @type {import('eslint').Linter.Config[]} */
+export default [
+ {files: ["**/*.js"], languageOptions: {sourceType: "script"}},
+ {languageOptions: { globals: globals.browser }},
+ pluginJs.configs.recommended,
+];
\ No newline at end of file
diff --git a/assets/js/package.json b/assets/js/package.json
new file mode 100644
index 00000000..bce79584
--- /dev/null
+++ b/assets/js/package.json
@@ -0,0 +1,11 @@
+{
+ "license": "Apache-2.0",
+ "devDependencies": {
+ "@eslint/js": "^9.18.0",
+ "eslint": "^8.57.1",
+ "eslint-config-airbnb-base": "latest",
+ "eslint-config-jquery": "^3.0.2",
+ "eslint-plugin-import": "^2.25.2",
+ "globals": "^15.14.0"
+ }
+}
diff --git a/assets/js/search-dev.js b/assets/js/search-dev.js
index fe94e75d..90161bae 100644
--- a/assets/js/search-dev.js
+++ b/assets/js/search-dev.js
@@ -1,51 +1,55 @@
var debug = false;
-jQuery(function() {
- window.data = $.getJSON('/search_data.json', function() {
- if (debug) { console.log('Okay'); }
- })
- .done(function(searchData) {
- if (debug) { console.log('Got JSON data'); }
- window.idx = new JsSearch.Search('id');
- window.idx.addIndex('id');
- window.idx.addIndex('title');
- window.idx.addIndex('content');
- window.idx.addIndex('categories');
- if (debug) { console.log('Processing'); }
- if (debug) { console.time('Build index'); }
- window.idx.addDocuments(searchData);
- if (debug) { console.timeEnd('Build index'); }
- var idxCount = searchData.length;
- if (debug) { console.log('Ready: idx: ' + idxCount); }
- JsSearch.StopWordsMap.issue = false;
- JsSearch.StopWordsMap.environment = false;
- })
- .fail(function() {
- console.log('Error with getting search data');
- })
- .always(function() {
- if (debug) { console.log('Complete'); }
- });
+let idx = [];
+$( (searchDev) => {
+ window.data = $.getJSON( "/search_data.json", () => {
+ if ( debug ) { console.log( "Setup okay." ); }
+ } )
+ .done( ( searchData ) => {
+ if ( debug ) { console.log( "Loaded JSON data." ); }
+ idx = new JsSearch.Search( "id" );
+ idx.indexStrategy = new JsSearch.PrefixIndexStrategy();
+ idx.addIndex( "title" );
+ idx.addIndex( "content" );
+ idx.addIndex( "categories" );
+ if ( debug ) { console.log( "Processing ..." ); }
+ if ( debug ) { console.time( "Build index" ); }
+ idx.addDocuments( searchData );
+ if ( debug ) { console.timeEnd( "Build index" ); }
+ const idxCount = searchData.length;
+ if ( debug ) { console.log( `Ready: idx: ${ idxCount } items` ); }
+ JsSearch.StopWordsMap.issue = false;
+ JsSearch.StopWordsMap.environment = false;
+ } )
+ .fail( () => {
+ console.log( "Error with getting search data." );
+ } )
+ .always( () => {
+ if ( debug ) { console.log( "Complete." ); }
+ } );
- $('#searchDev').submit(function(event) {
- event.preventDefault();
- var query = $('#searchInput').val();
- if (debug) { console.log('Query: ' + query); }
- var results = window.idx.search(query);
- displayResults(results);
- });
-
- function displayResults(results) {
- var $searchResults = $('#searchResults');
- if (debug) { console.log('Hits: ' + results.length); }
- if (results.length) {
- $searchResults.empty();
- results.forEach(function(result) {
- if (debug) { console.log('Result: ' + result.url); }
- var appendString = '
' + result.title + '';
- $searchResults.append(appendString);
- });
+ function displayResults( results ) {
+ const searchResults = $( "#searchResults" );
+ const hits = $( "#hits" );
+ if ( debug ) { console.log( `Hits: ${ results.length }` ); }
+ if ( results.length ) {
+ searchResults.empty();
+ hits.html( `Hits: ${ results.length }` );
+ results.forEach( ( result ) => {
+ if ( debug ) { console.log( `Result: ${ result.url }` ); }
+ const appendString = `
${ result.title }`;
+ searchResults.append(appendString);
+ } );
} else {
- $searchResults.html('
No results found.');
+ hits.html( `Hits: 0` );
+ searchResults.html( "
No results found." );
}
}
-});
+
+ $( "#searchDev" ).submit( ( event ) => {
+ event.preventDefault();
+ const query = $( "#searchInput" ).val();
+ if ( debug ) { console.log( `Query: ${ query }` ); }
+ const results = idx.search( query );
+ displayResults( results );
+ } );
+} );
diff --git a/assets/js/search-endpoints.js b/assets/js/search-endpoints.js
new file mode 100644
index 00000000..9edc59e9
--- /dev/null
+++ b/assets/js/search-endpoints.js
@@ -0,0 +1,95 @@
+const debug = true;
+let idx = [];
+$( (searchEndpoints) => {
+ window.data = $.getJSON( "/search_endpoints.json", () => {
+ if ( debug ) { console.log( "Setup okay." ); }
+ } )
+ .done( ( searchData ) => {
+ if ( debug ) { console.log( "Loaded JSON data." ); }
+ idx = new JsSearch.Search( "id" );
+ idx.indexStrategy = new JsSearch.AllSubstringsIndexStrategy();
+ idx.addIndex( "id" );
+ idx.addIndex( "moduleName" );
+ idx.addIndex( "path" );
+ idx.addIndex( "interface" );
+ idx.addIndex( "methods" );
+ idx.addIndex( "apiDescription" );
+ idx.addIndex( "apiType" );
+ if ( debug ) { console.log( "Processing ..." ); }
+ if ( debug ) { console.time( "Build index" ); }
+ idx.addDocuments( searchData );
+ if ( debug ) { console.timeEnd( "Build index" ); }
+ const idxCount = searchData.length;
+ if ( debug ) { console.log( `Ready: idx: ${ idxCount } items` ); }
+ JsSearch.StopWordsMap.issue = false;
+ JsSearch.StopWordsMap.environment = false;
+ } )
+ .fail( () => {
+ console.log( "Error with getting search data." );
+ } )
+ .always( () => {
+ if ( debug ) { console.log( "Complete." ); }
+ } );
+
+ function displayResults( results ) {
+ const searchResults = $( "#searchResults" );
+ const hits = $( "#hits" );
+ const urlRepoBase = "https://github.com/folio-org/";
+ const urlS3Base = "https://s3.amazonaws.com/foliodocs/api/";
+ if ( debug ) { console.log( `Hits: ${ results.length }` ); }
+ if ( results.length ) {
+ searchResults.empty();
+ hits.html( `Hits: ${ results.length }` );
+ results.forEach( ( result ) => {
+ if ( debug ) { console.log( `Result: ${ result.path }` ); }
+ const urlRepo = `${ urlRepoBase }${ result.moduleName }`;
+ const urlS3Repo = `${ urlS3Base }${ result.moduleName }`;
+ const apath = result.apiDescription;
+ const filenameDoc = apath.substring( apath.lastIndexOf( "/" ) + 1 );
+ const basenameDoc = filenameDoc.replace( /\.[^/.]+$/, "" );
+ const urlApiDesc = `${ urlRepo }/blob/master/${ result.apiDescription }`;
+ const methods = result.methods.split( " " );
+ let methodsList = "";
+ methods.forEach( ( method ) => {
+ const opParts = method.split( ":" );
+ let nullNote = "";
+ if ( opParts[ 1 ] === "null" ) {
+ nullNote = " (missing operationId)"
+ }
+ let urlS3 = `${ urlS3Repo }/`;
+ if ( result.apiType === "RAML" ) {
+ urlS3 += "p/";
+ }
+ urlS3 += `${ basenameDoc }.html#${ opParts[ 1 ] }`;
+ methodsList += `
${ opParts[ 0 ] } ${nullNote}`;
+ } );
+ const appendString = `
+
${ result.path }
+
+
+ `;
+ searchResults.append( appendString );
+ } );
+ } else {
+ hits.html( `Hits: 0` );
+ searchResults.html( "
No results found." );
+ }
+ }
+
+ $( "#searchEndpoints" ).submit( ( event ) => {
+ event.preventDefault();
+ const query = $( "#searchInput" ).val();
+ if ( debug ) { console.log( `Query: ${ query }` ); }
+ const results = idx.search( query );
+ displayResults( results );
+ } );
+} );
diff --git a/reference/api/endpoints.md b/reference/api/endpoints.md
index 4f58eec6..e8809e33 100644
--- a/reference/api/endpoints.md
+++ b/reference/api/endpoints.md
@@ -13,7 +13,7 @@ menuSubIndex: 3
This API documentation is automatically [generated](#gathered-lists) from each repository's API description files.
-Use the web browser "Find in page" facility.
+Use the web browser "Find in page" facility to locate items in this table. Also [search endpoints](/search-endpoints/).
Each link in the "API documentation" column goes directly to the relevant entry in the tables of the [API documentation](/reference/api/).
Each link in the "Methods" column goes directly to that section of the relevant API documentation.
@@ -119,7 +119,7 @@ $("[data-column]").on("click", function () {
The list of endpoints (also known as "entry-points") is gathered and published during the CI [generation](/reference/api/#generated-during-ci) of each module's API documentation, when there is a merge to their mainline branch.
A daily Workflow [assembles](/reference/api/#explain-gather-config) the published lists of endpoints.
-### Some missing links
+### Some missing method links
For some OpenAPI-based modules, there might be missing links in the "Methods" column.
That is because their API description has omitted the "`operationId`" property for that method.
diff --git a/reference/glossary.md b/reference/glossary.md
index a0aa5af6..a12f16f2 100644
--- a/reference/glossary.md
+++ b/reference/glossary.md
@@ -5,7 +5,7 @@ permalink: /reference/glossary/
menuInclude: yes
menuTopTitle: Reference
menuSubTitle: Glossary
-menuSubIndex: 5
+menuSubIndex: 6
---
FOLIO is a new open source, cloud hostable, app-store based library platform,
diff --git a/reference/index.md b/reference/index.md
index efb3c6d4..4b56558a 100644
--- a/reference/index.md
+++ b/reference/index.md
@@ -8,10 +8,13 @@ menuTopIndex: 3
menuSubTitle: Reference introduction
menuSubIndex: 1
menuSubs:
+- title: Search API endpoints
+ url: /search-endpoints/
+ index: 4
- title: Reference environments
url: /guides/automation/
anchorId: reference-environments
- index: 4
+ index: 5
---
Standards and reference documentation.
@@ -19,3 +22,8 @@ Standards and reference documentation.
- The set of automatically generated [API documentation](/reference/api/) and list of [endpoints](/reference/api/endpoints/).
- The [reference environments](/guides/automation/#reference-environments) resulting from the continuous integration automated [builds](/guides/automation/#software-build-pipeline).
- A [FOLIO glossary](/reference/glossary/) of some terms and technologies used in FOLIO.
+
+## Search facilities
+
+* [API documentation endpoints](/search-endpoints/)
+
diff --git a/search-endpoints.md b/search-endpoints.md
new file mode 100644
index 00000000..896782af
--- /dev/null
+++ b/search-endpoints.md
@@ -0,0 +1,50 @@
+---
+layout: page
+title: Search API endpoints
+titleLeader: "Search |"
+permalink: /search-endpoints/
+menuInclude: yes
+menuLink: yes
+menuTopTitle: Search
+menuSubTitle: "Search API endpoints"
+menuSubIndex: 3
+tertiary-column: present
+tertiary-column-content: column-2-search-endpoints.html
+---
+
+
+
+
+
+
+
+
+
+
+
+
+## Other information
+
+### Some missing method links
+
+As [explained](/reference/api/endpoints/#some-missing-method-links) at the Endpoints documentation, a small set of OpenAPI-based modules are missing links for the "Methods".
+These will be marked in the search results with "(missing operationId)".
+
+Some of these are unimplemented "stub" endpoints (do a search for "stub" to find them).
+
+Others are actual endpoints, but their API description has omitted the "operationId" property for that method.
+
+### Interfaces
+
+Some "interface" properties might be missing. See the [explanation](/reference/api/endpoints/#interfaces) at the Endpoints documentation.
+
+### Other documentation
+
+* [API documentation](/reference/api/)
+* [API documentation endpoints](/reference/api/endpoints/)
+
+
+
diff --git a/search-other.md b/search-other.md
index dd9adb3d..8c30fb60 100644
--- a/search-other.md
+++ b/search-other.md
@@ -7,7 +7,7 @@ menuInclude: yes
menuLink: yes
menuTopTitle: Search
menuTopIndex: 100
-menuSubTitle: "Search other"
+menuSubTitle: "Search other places"
menuSubIndex: 2
menuSubs:
-
diff --git a/search.md b/search.md
index 0e40568a..921f48c9 100644
--- a/search.md
+++ b/search.md
@@ -17,8 +17,14 @@ tertiary-column-content: column-2-search.html
+