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.

+

+ Using its "AllSubstringsIndexStrategy". + So "c", "ca", "cat", "a", "at", and "t" will all match the term "cat". +

+

+ This search is constrained to the + list + of API documentation endpoints. +

+
+ diff --git a/_includes/column-2-search.html b/_includes/column-2-search.html index 425662d4..0aa924b7 100644 --- a/_includes/column-2-search.html +++ b/_includes/column-2-search.html @@ -5,15 +5,13 @@

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
    +
    + +## Other information + +See [Search other places](/search-other/) for other search and report facilities such as for GitHub, FOLIO Wiki, etc. + diff --git a/search_data.json b/search_data.json index 437681b1..b6a767bc 100644 --- a/search_data.json +++ b/search_data.json @@ -11,6 +11,7 @@ layout: null {%- assign docId = page.url | slugify -%} {%- endif -%} {%- if docId == "search-data-json" -%}{%- continue -%}{%- endif -%} + {%- if docId == "search-endpoints-json" -%}{%- continue -%}{%- endif -%} {%- if docId == "assets-main-css" -%}{%- continue -%}{%- endif -%} {%- if docId == "assets-main-css-map" -%}{%- continue -%}{%- endif -%} {%- if docId == "banner-area-html" -%}{%- continue -%}{%- endif -%} diff --git a/search_endpoints.json b/search_endpoints.json new file mode 100644 index 00000000..e4eabfc6 --- /dev/null +++ b/search_endpoints.json @@ -0,0 +1,22 @@ +--- +layout: null +--- +[ + {%- assign sortedEndpoints = site.data.config-api-endpoints | sort:"path" -%} + {%- assign counter = 0 -%} + {%- for endpoint in sortedEndpoints -%} + {%- assign counter = counter | plus: 1 -%} + {%- assign docId = endpoint.path | append: "-" | append: counter | slugify -%} + { + "id": "{{ docId }}", + "moduleName": "{{ endpoint.name }}", + "path": "{{ endpoint.path }}", + "interface": "{{ endpoint.interface }}", + "methods": "{{ endpoint.methods }}", + "apiDescription": "{{ endpoint.apiDescription }}", + "apiType": "{{ endpoint.apiType | upcase }}" + } + {%- unless forloop.last -%},{%- endunless -%} + {%- endfor -%} +] +