bahai-indexes
Advanced tools
Comparing version 0.10.0 to 0.11.0
# CHANGES to `bahai-indexes` | ||
## 0.11.0 | ||
BREAKING: Requires Node 14 | ||
- feat: index links | ||
- fix: bug with Aqdas index parsing | ||
- fix: bug with Iqan seeAlso | ||
- fix: parser paths | ||
- fix: button width | ||
- chore: update `httpquery`, devDeps and lint | ||
- docs: add missing index | ||
## 0.10.0 | ||
@@ -4,0 +16,0 @@ |
@@ -87,3 +87,7 @@ { | ||
"$book": "Kitáb-i-Íqán", | ||
"$seeAlso": "I43" | ||
"$seeAlso": [ | ||
{ | ||
"id": "Imám 'Alí" | ||
} | ||
] | ||
}, | ||
@@ -377,3 +381,7 @@ "Alif": { | ||
"$book": "Kitáb-i-Íqán", | ||
"$seeAlso": "I48" | ||
"$seeAlso": [ | ||
{ | ||
"id": "Jesus" | ||
} | ||
] | ||
}, | ||
@@ -414,3 +422,7 @@ "Clerics": { | ||
}, | ||
"$seeAlso": "I29" | ||
"$seeAlso": [ | ||
{ | ||
"id": "Divines" | ||
} | ||
] | ||
}, | ||
@@ -595,3 +607,7 @@ "Clouds": { | ||
}, | ||
"$seeAlso": "I101" | ||
"$seeAlso": [ | ||
{ | ||
"id": "Tablet of Faṭimih" | ||
} | ||
] | ||
}, | ||
@@ -1030,3 +1046,7 @@ "Gabriel": { | ||
}, | ||
"$seeAlso": "I46" | ||
"$seeAlso": [ | ||
{ | ||
"id": "Israel" | ||
} | ||
] | ||
}, | ||
@@ -1572,3 +1592,7 @@ "John the Baptist": { | ||
"$book": "Kitáb-i-Íqán", | ||
"$seeAlso": "I78" | ||
"$seeAlso": [ | ||
{ | ||
"id": "Prayer" | ||
} | ||
] | ||
}, | ||
@@ -1575,0 +1599,0 @@ "Oppression": { |
@@ -1,5 +0,72 @@ | ||
import {$, httpquery} from './utils.js'; | ||
import {$, $$, httpquery, populateFullIndex} from './utils.js'; | ||
import searchEntriesFormSubmit from './searchEntriesFormSubmit.js'; | ||
import searchEntriesPagesFormSubmit from './searchEntriesPagesFormSubmit.js'; | ||
/** | ||
* @param {Event} e | ||
* @returns {void} | ||
*/ | ||
async function linkOpener (e) { | ||
e.preventDefault(); | ||
$$('#linkList a').forEach((a) => { | ||
a.classList.remove('selected-link'); | ||
}); | ||
e.target.classList.add('selected-link'); | ||
const book = e.target.textContent; | ||
$('#chosenIndex').textContent = book; | ||
if (e.manuallyTriggered !== false) { | ||
const queryParams = new URLSearchParams(location.search); | ||
queryParams.delete('entry'); | ||
queryParams.set('book', book); | ||
history.pushState(null, null, '?' + queryParams.toString()); | ||
} | ||
const jsonataQuery = `*[${`book="${book}"`}].index`; | ||
const results = await httpquery( | ||
'books.json', | ||
{ | ||
query: jsonataQuery, | ||
bindings: {} | ||
} | ||
); | ||
const resultsHolder = $('#indexView'); | ||
resultsHolder.textContent = ''; | ||
const newResultsHolder = resultsHolder.cloneNode(true); | ||
resultsHolder.replaceWith(newResultsHolder); | ||
newResultsHolder.addEventListener('click', (ev) => { | ||
if (ev.target.nodeName.toLowerCase() !== 'a' || !ev.target.dataset.id) { | ||
return; | ||
} | ||
ev.preventDefault(); | ||
const targetedEntry = $('#' + CSS.escape(ev.target.dataset.id)); | ||
if (e.manuallyTriggered !== false) { | ||
const params = new URLSearchParams(location.search); | ||
params.set('entry', ev.target.dataset.id); | ||
history.pushState(null, null, '?' + params.toString()); | ||
} | ||
targetedEntry.scrollIntoView(); | ||
}); | ||
const ul = document.createElement('ul'); | ||
Object.entries(results).forEach(([ | ||
id, | ||
result | ||
/* { | ||
$links, | ||
$seeAlso, | ||
$text, | ||
$children | ||
} */ | ||
]) => { | ||
populateFullIndex({result, ul, id}); | ||
}); | ||
newResultsHolder.append(ul); | ||
} | ||
(await httpquery('books.json', { | ||
@@ -9,2 +76,3 @@ query: '*.book[]', | ||
})).forEach((book) => { | ||
// OPTIONS | ||
const option = document.createElement('option'); | ||
@@ -14,2 +82,11 @@ option.textContent = book; | ||
$('#booksPages').append(option.cloneNode(true)); | ||
// LINKS | ||
const a = document.createElement('a'); | ||
a.href = '#'; | ||
a.addEventListener('click', linkOpener); | ||
a.textContent = book; | ||
const li = document.createElement('li'); | ||
li.append(a); | ||
$('#linkList').append(li); | ||
}); | ||
@@ -115,2 +192,8 @@ | ||
expandAll.addEventListener('click', changeSubmitter); | ||
const linkViewer = $('#linkViewer'); | ||
const openLinkList = $('#openLinkList'); | ||
openLinkList.addEventListener('click', changeSubmitter); | ||
collapseSearchEntries.addEventListener('click', changeSubmitter); | ||
@@ -122,12 +205,45 @@ collapseSearchEntriesPages.addEventListener('click', changeSubmitter); | ||
const url = new URL(location.href); | ||
let url = new URL(location.href); | ||
const setCollapseState = () => { | ||
const setCollapseState = async () => { | ||
const param = url.searchParams.get('collapse'); | ||
switch (param) { | ||
case 'collapseSearchEntriesPages': | ||
case 'openLinkList': { | ||
searchEntriesPagesForm.classList.add('hidden'); | ||
searchEntriesForm.classList.add('hidden'); | ||
linkViewer.classList.remove('hidden'); | ||
const book = url.searchParams.get('book'); | ||
if (book) { | ||
let lastA; | ||
if ($$('#linkList a').some((a) => { | ||
if (a.textContent === book) { | ||
lastA = a; | ||
return true; | ||
} | ||
return false; | ||
})) { | ||
await linkOpener({ | ||
manuallyTriggered: false, | ||
preventDefault () { | ||
// Dummy | ||
}, | ||
target: lastA | ||
}); | ||
const entry = url.searchParams.get('entry'); | ||
if (entry) { | ||
const targetedEntry = $('#' + CSS.escape(entry)); | ||
if (targetedEntry) { | ||
targetedEntry.scrollIntoView(); | ||
} | ||
} | ||
} | ||
} | ||
break; | ||
} case 'collapseSearchEntriesPages': | ||
searchEntriesForm.classList.remove('hidden'); | ||
searchEntriesForm.classList.add('shownAlone'); | ||
searchEntriesPagesForm.classList.add('hidden'); | ||
linkViewer.classList.add('hidden'); | ||
searchEntriesPagesForm.classList.remove('shownAlone'); | ||
@@ -141,2 +257,3 @@ collapseSearchEntries.style.display = 'block'; | ||
searchEntriesForm.classList.add('hidden'); | ||
linkViewer.classList.add('hidden'); | ||
searchEntriesPagesForm.classList.add('shownAlone'); | ||
@@ -192,3 +309,3 @@ searchEntriesPagesForm.classList.remove('hidden'); | ||
setCollapseState(); | ||
await setCollapseState(); | ||
selectMenus.forEach((id) => setSelect(id)); | ||
@@ -206,1 +323,9 @@ selectMenusPages.forEach((id) => setSelect(id)); | ||
}); | ||
window.addEventListener('popstate', (e) => { | ||
// Use fresh copy of location as will otherwise use stale info | ||
url = new URL(location.href); | ||
setTimeout(async () => { | ||
await setCollapseState(); | ||
}); | ||
}); |
/* eslint-disable no-unsanitized/property -- Source must be trusted as | ||
we want its HTML */ | ||
import {$, httpquery} from './utils.js'; | ||
import {appendLinks, appendLinksToHolder} from './appendLinks.js'; | ||
import {$, httpquery, populateFullIndex} from './utils.js'; | ||
import {appendLinksToHolder} from './appendLinks.js'; | ||
import traverse from './traverse.js'; | ||
@@ -149,2 +149,14 @@ | ||
const ul = document.createElement('ul'); | ||
resultsHolder.addEventListener('click', (ev) => { | ||
if (ev.target.nodeName.toLowerCase() !== 'a' || !ev.target.dataset.id) { | ||
return; | ||
} | ||
ev.preventDefault(); | ||
const a = ev.target; | ||
location.href = `./?collapse=openLinkList&book=${ | ||
a.dataset.book | ||
}&entry=${a.dataset.id}`; | ||
}, true); | ||
const bookUl = book ? null : document.createElement('ul'); | ||
@@ -169,24 +181,12 @@ const visited = {}; | ||
} | ||
traverse(result, bookUlInner || ul, (obj, parent) => { | ||
const li = document.createElement('li'); | ||
li.innerHTML = obj.$text; | ||
const links = obj.$links || []; | ||
if (entriesOrLinks === 'both') { | ||
if (links.length) { | ||
li.append(' - '); | ||
appendLinks(links, li, result.$book); | ||
} | ||
} | ||
parent.append(li); | ||
if (obj.$children) { | ||
const innerUl = document.createElement('ul'); | ||
li.append(innerUl); | ||
return innerUl; | ||
} | ||
return li; | ||
populateFullIndex({ | ||
result, | ||
ul: bookUlInner || ul | ||
}); | ||
}); | ||
if (!bookUl) resultsHolder.append(ul); | ||
if (!bookUl) { | ||
resultsHolder.append(ul); | ||
} | ||
} | ||
@@ -193,0 +193,0 @@ } |
@@ -89,3 +89,3 @@ /* eslint-disable no-unsanitized/property -- Source must be trusted as | ||
})])][] | ||
`.replace(/\n/gu, ' '); | ||
`.replaceAll('\n', ' '); | ||
@@ -92,0 +92,0 @@ const results = await httpquery( |
/** | ||
* @typedef {PlainObject} IndexObject | ||
* @typedef {object} IndexObject | ||
* @property {string} $text | ||
@@ -14,6 +14,10 @@ * @property {Object<string,IndexObject>} $children | ||
/** | ||
* @typedef {any} AnyResult | ||
*/ | ||
/** | ||
* @param {IndexObject} obj | ||
* @param {any} lastResult | ||
* @param {AnyResult} lastResult | ||
* @param {IndexHandler} handler | ||
* @param {string[]} [paths=[]] | ||
* @param {string[]} [paths] | ||
* @returns {void} | ||
@@ -20,0 +24,0 @@ */ |
@@ -0,1 +1,7 @@ | ||
/* eslint-disable no-unsanitized/property -- Source must be trusted as | ||
we want its HTML */ | ||
import {appendLinks} from './appendLinks.js'; | ||
import traverse from './traverse.js'; | ||
/** | ||
@@ -10,2 +16,10 @@ * @param {string} sel | ||
/** | ||
* @param {string} sel | ||
* @returns {Element} | ||
*/ | ||
const $$ = (sel) => { | ||
return [...document.querySelectorAll(sel)]; | ||
}; | ||
/** | ||
* @typedef {null|boolean|number|string|Array<JSON>|Object<string,JSON>} JSON | ||
@@ -16,3 +30,3 @@ */ | ||
* @param {string} url | ||
* @param {PlainObject} cfg | ||
* @param {object} cfg | ||
* @param {string} cfg.query | ||
@@ -39,2 +53,83 @@ * @param {JSON} cfg.bindings | ||
export {$, httpquery}; | ||
/** | ||
* @typedef {any} IndexResult | ||
* @todo Specify | ||
*/ | ||
/** | ||
* @param {object} cfg | ||
* @param {IndexResult} cfg.result | ||
* @param {HTMLElement} cfg.ul | ||
* @param {string} cfg.id | ||
* @param {string} cfg.entriesOrLinks | ||
* @returns {void} | ||
*/ | ||
function populateFullIndex ({result, ul, id, entriesOrLinks = 'both'}) { | ||
traverse(result, ul, (obj, parent) => { | ||
const li = document.createElement('li'); | ||
li.id = id; | ||
li.innerHTML = obj.$text; | ||
const links = obj.$links || []; | ||
if (entriesOrLinks === 'both') { | ||
if (links.length) { | ||
li.append(' - '); | ||
appendLinks(links, li, result.$book); | ||
} | ||
} | ||
parent.append(li); | ||
if (obj.$children) { | ||
const innerUl = document.createElement('ul'); | ||
li.append(innerUl); | ||
return innerUl; | ||
} | ||
if (obj.$seeAlso) { | ||
// None with `obj.$children`? | ||
if (links.length) { | ||
const innerUl = document.createElement('ul'); | ||
li.append(innerUl); | ||
const innerLi = document.createElement('li'); | ||
innerUl.append(innerLi); | ||
const i = document.createElement('i'); | ||
i.textContent = 'See also '; | ||
innerLi.append(i); | ||
obj.$seeAlso.forEach((see, idx) => { | ||
const a = document.createElement('a'); | ||
a.href = '#'; | ||
a.dataset.book = result.$book; | ||
a.dataset.id = see.id; | ||
a.textContent = see.text || see.id; | ||
innerLi.append( | ||
idx ? ', ' : '', | ||
see.headings ? 'the headings under ' : '', | ||
a | ||
); | ||
}); | ||
} else { | ||
const i = document.createElement('i'); | ||
i.textContent = ' See '; | ||
li.append(i); | ||
obj.$seeAlso.forEach((see, idx) => { | ||
const a = document.createElement('a'); | ||
a.href = '#'; | ||
a.dataset.book = result.$book; | ||
a.dataset.id = see.id; | ||
a.textContent = see.text || see.id; | ||
li.append( | ||
idx ? ', ' : '', | ||
see.headings ? 'the headings under ' : '', | ||
a | ||
); | ||
}); | ||
} | ||
} | ||
return li; | ||
}); | ||
} | ||
export {$, $$, httpquery, populateFullIndex}; |
{ | ||
"name": "bahai-indexes", | ||
"type": "module", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "Indexes to the Bahá'í Writings in JSON form", | ||
"main": "src/buildFlattenedJSONAndJS.js", | ||
"scripts": { | ||
"addBook": "node indexes/addBook.js", | ||
"start": "httpquery --path=indexes/json --debug", | ||
"eslint": "eslint --ext=js,md,html .", | ||
"lint": "npm run eslint --", | ||
"build-books": "node indexes/books.js", | ||
"build": "node src/buildFlattenedJSONAndJS.js", | ||
"parse": "npm run parse-aqdas", | ||
"parse-aqdas": "node parsers/html/aqdas.js", | ||
"parse-iqan": "node parsers/html/iqan.js", | ||
"test": "npm run eslint && echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
@@ -21,44 +33,31 @@ "type": "git", | ||
"dependencies": { | ||
"httpquery": "^0.8.2" | ||
"httpquery": "^0.8.3" | ||
}, | ||
"engines": { | ||
"node": ">=12" | ||
"node": ">=14" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.17.8", | ||
"@babel/eslint-parser": "^7.17.0", | ||
"@babel/core": "^7.23.2", | ||
"@babel/eslint-parser": "^7.22.15", | ||
"@brettz9/eslint-plugin": "^1.0.4", | ||
"eslint": "^8.12.0", | ||
"eslint-config-ash-nazg": "^32.7.1", | ||
"eslint-config-standard": "^16.0.3", | ||
"eslint-plugin-array-func": "^3.1.7", | ||
"eslint-plugin-compat": "^4.0.2", | ||
"eslint": "^8.52.0", | ||
"eslint-config-ash-nazg": "^34.18.0", | ||
"eslint-config-standard": "^17.1.0", | ||
"eslint-plugin-array-func": "^4.0.0", | ||
"eslint-plugin-compat": "^4.2.0", | ||
"eslint-plugin-eslint-comments": "^3.2.0", | ||
"eslint-plugin-html": "^6.2.0", | ||
"eslint-plugin-import": "^2.25.4", | ||
"eslint-plugin-jsdoc": "^38.1.6", | ||
"eslint-plugin-markdown": "^2.2.1", | ||
"eslint-plugin-no-unsanitized": "^4.0.1", | ||
"eslint-plugin-html": "^7.1.0", | ||
"eslint-plugin-import": "^2.29.0", | ||
"eslint-plugin-jsdoc": "^46.8.2", | ||
"eslint-plugin-markdown": "^3.0.1", | ||
"eslint-plugin-no-unsanitized": "^4.0.2", | ||
"eslint-plugin-no-use-extend-native": "^0.5.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^6.0.0", | ||
"eslint-plugin-sonarjs": "^0.13.0", | ||
"eslint-plugin-promise": "^6.1.1", | ||
"eslint-plugin-sonarjs": "^0.22.0", | ||
"eslint-plugin-standard": "^4.1.0", | ||
"eslint-plugin-unicorn": "^42.0.0", | ||
"eslint-plugin-unicorn": "^49.0.0", | ||
"handle-node": "^0.2.1", | ||
"jsdom": "^19.0.0" | ||
}, | ||
"scripts": { | ||
"addBook": "node indexes/addBook.js", | ||
"start": "httpquery --path=indexes/json --debug", | ||
"eslint": "eslint --ext=js,md,html .", | ||
"lint": "npm run eslint --", | ||
"build-books": "node indexes/books.js", | ||
"build": "node src/buildFlattenedJSONAndJS.js", | ||
"parse": "npm run parse-aqdas", | ||
"parse-aqdas": "node html-parsers/aqdas.js", | ||
"parse-iqan": "node html-parsers/iqan.js", | ||
"test": "npm run eslint && echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"readme": "# bahai-indexes\n\nIndexes to the Bahá'í Writings in JSON format, along with some\ntools to convert from the original (idiosyncratic) HTML versions.\n\n```shell\nnpm i bahai-indexes\n```\n\nNote that any copyright that applies for the original indexes follows its own\ncopyright.\n\nYou can see a [**Demo**](https://bahai-browser.org/indexes/json/?indexTerm=God&entriesOrLinks=2).\n\n**NOTE: This project only has an index for the following files at present!**\n\n## Sources\n\n- *Kitáb-i-Aqdas* (`aqdas`) - From <http://bahai-library.com/writings/bahaullah/aqdas/aqdas2/aqdas-allindex.html>;\n view within queries against the following (currently Chrome only:\n <https://bahai-browser.org/#lang=en-US&work=aqdas>).\n\n- *Kitáb-i-Íqán* (`aqdas`) - From <https://bahai-library.com/writings/bahaullah/iqan/iq-indx.htm>.\n\n## Higher priority to-dos\n\n1. Add more books (see <https://bahai-library.com/zamir_temp_indexes>)\n\n## Medium priority to-dos\n\n1. Delete unused URL params\n1. Merging of entries option\n1. Could make agnostic to application, with user supplying JSON as config\n files.\n1. Ideally add categories, even to each entry level, and allow merging\n1. Editing\n 1. Add category mechanism for adding categories (and categories for these\n categories) to top-level index items (for a completely subject-based\n sorting, as with\n <http://bahai-library.com/hornby_lights_guidance#topicalcontents>).\n 1. Ability to mark-up any two entries as identical, e.g.,\n \"Hair, does not invalidate prayer\" and\n \"Prayer, hair does not invalidate\", so that could optionally avoid\n showing duplicates (though admittedly not exactly duplicates based\n on difference of emphasis)\n\n## Lower priority to-dos\n\n1. Offline ability (and reactive web components like uce(-template)?)\n1. Add JSON Schema for each schema and any fixed rules into an abstract schema\n" | ||
} | ||
"jsdom": "^22.1.0" | ||
} | ||
} |
@@ -19,11 +19,14 @@ # bahai-indexes | ||
- *Kitáb-i-Aqdas* (`aqdas`) - From <http://bahai-library.com/writings/bahaullah/aqdas/aqdas2/aqdas-allindex.html>; | ||
- *Kitáb-i-Aqdas* - From <http://bahai-library.com/writings/bahaullah/aqdas/aqdas2/aqdas-allindex.html>; | ||
view within queries against the following (currently Chrome only: | ||
<https://bahai-browser.org/#lang=en-US&work=aqdas>). | ||
- *Kitáb-i-Íqán* (`aqdas`) - From <https://bahai-library.com/writings/bahaullah/iqan/iq-indx.htm>. | ||
- *Kitáb-i-Íqán* - From <https://bahai-library.com/writings/bahaullah/iqan/iq-indx.htm>. | ||
- *Gleanings* - From <https://bahai-library.com/zamir/indexes/gleaningsindex.html>. | ||
## Higher priority to-dos | ||
1. Add more books (see <https://bahai-library.com/zamir_temp_indexes>) | ||
1. Option to search word boundaries | ||
@@ -33,2 +36,3 @@ ## Medium priority to-dos | ||
1. Delete unused URL params | ||
1. Fix individual broken "See also" entries | ||
1. Merging of entries option | ||
@@ -35,0 +39,0 @@ 1. Could make agnostic to application, with user supplying JSON as config |
@@ -34,3 +34,3 @@ // Todo: It would be ideal if this could be made generic to other books, but | ||
* @callback SeeAlsoCallback | ||
* @param {SeeAlsoMeta} $seeAlso | ||
* @param {SeeAlsoMeta[]} $seeAlso | ||
* @param {string} key | ||
@@ -44,3 +44,3 @@ * @param {string} basePath | ||
/** | ||
* @typedef {PlainObject} IterateKeysCallbackObject | ||
* @typedef {object} IterateKeysCallbackObject | ||
* @property {KeysCallback} [keys] | ||
@@ -52,27 +52,29 @@ * @property {LinksCallback} [links] | ||
/** | ||
* @typedef {PlainObject} SeeAlsoMeta | ||
* @property {string} id | ||
* @property {string} [text] | ||
* @property {boolean} [headings] | ||
*/ | ||
* @typedef {object} SeeAlsoMeta | ||
* @property {string} id Refers to `WritingsJSON` key | ||
* @property {string} [text] The full text of the index entry | ||
* @property {boolean} [headings] Whether this meta to be shown as | ||
* "See additional headings under" | ||
*/ | ||
/** | ||
* @typedef {GenericArray} LinksMetaArray | ||
* @property {string} 0 | ||
* @property {string} 1 | ||
*/ | ||
* A range of pages/paragraphs/verses. | ||
* @typedef {GenericArray} LinksMetaArray | ||
* @property {string} 0 | ||
* @property {string} 1 | ||
*/ | ||
/** | ||
* @typedef {GenericArray} LinksMeta | ||
* @property {string|LinksMetaArray} * | ||
*/ | ||
* @typedef {GenericArray} LinksMeta | ||
* @property {string|LinksMetaArray} * | ||
*/ | ||
/** | ||
* @typedef {string} TextMeta | ||
*/ | ||
* @typedef {string} TextMeta | ||
*/ | ||
/** | ||
* @typedef {PlainObject} WritingsMeta | ||
* @typedef {object} WritingsMeta | ||
* @property {LinksMeta} [$links] | ||
* @property {SeeAlsoMeta} [$seeAlso] | ||
* @property {SeeAlsoMeta[]} [$seeAlso] | ||
* @property {TextMeta} [$text] | ||
@@ -83,3 +85,4 @@ * @property {WritingsMeta} [$children] | ||
/** | ||
* @typedef {PlainObject<string, WritingsMeta>} WritingsJSON | ||
* Keyed by id. | ||
* @typedef {Object<string, WritingsMeta>} WritingsJSON | ||
*/ | ||
@@ -306,3 +309,2 @@ | ||
(async () => { | ||
const aqdas = JSON.parse( | ||
@@ -316,2 +318,1 @@ await readFile( | ||
console.log('Complete!'); | ||
})(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2944750
117152
55
Updatedhttpquery@^0.8.3