Skip to content

Commit

Permalink
chore: move OpenSearchDescription out of the ./src/index.js
Browse files Browse the repository at this point in the history
  • Loading branch information
h.u.g.u.rp committed Jul 26, 2023
1 parent 4cbe198 commit 1cd1882
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 112 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"dev": "serve -p 8000 || python3 -m http.server --directory .",
"test": "ava",
"opensearch": "node ./src/scripts/opensearch-xml.js",
"opensearch": "node ./src/scripts/opensearch-xml.js ?generate=true",
"find": "node ./src/scripts/i4k-find.js"
},
"bin": {
Expand Down
61 changes: 0 additions & 61 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,78 +321,17 @@ export class I4kFindSymbols {
/* a list of the default symbols */
export const DEFAULT_SYMBOLS = new I4kFindSymbols().default

/* find's default OSD */
export const DEFAULT_OSD = {
shortName: "Find",
description: "Find anything anywhere",
image: "https://example.org/i4k-find/assets/favicon.ico",
templateHTML: "https://example.org/i4k-find/#q={searchTerms}",
templateXML: "https://example.org/i4k-find/assets/opensearch.xml",
templateSuggestions: "https://example.org/i4k-find/api/suggestions/#q={searchTerms}",
};

/* generate the OSD needed to register as a browser search engine */
export class OpenSearchDescription {
get attributes() {
return [
"shortName",
"description",
"templateHTML",
"templateXML",
"templateSuggestions",
"image",
];
}
get config() {
return this.attributes.reduce((acc, val) => {
acc[val] = this[val];
return acc;
}, {});
}
constructor(config) {
this.attributes.forEach((attr) => {
const isSet = config.hasOwnProperty(attr);
const val = isSet ? config[attr] : DEFAULT_OSD[attr];
this[attr] = val;
});
}
exportJSON() {
return JSON.stringify({ ...this.config }, null, 2);
}
exportXML() {
const config = { ...this.config };
return `<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<InputEncoding>UTF-8</InputEncoding>
<ShortName>${config.shortName}</ShortName>
<Description>${config.description}</Description>
<Image height="64" width="64" type="image/png">${config.image}</Image>
<Url type="text/html" template="${config.templateHTML}" method="GET"/>
<Url type="application/opensearchdescription+xml" rel="search" template="${config.templateXML}" method="GET"/>
<Url type="application/x-suggestions+json" rel="suggestions" template="${config.templateSuggestions}" method="GET"/>
</OpenSearchDescription>`;
/* <moz:SearchForm>${config.templateHTML}</moz:SearchForm> */
}
}

/* the logic for search engines and actions */
export class I4kFind {
constructor({
symbols,
queryParamName,
localStorageKey,
templateHTML,
templateXML,
templateSuggestions,
} = {}) {
this.localStorageKey = localStorageKey || "i4find";
this.queryParamName = queryParamName || "q";
// default I4KSymbol map of available symbols
this.symbols = symbols || new I4kFindSymbols().default;

/* use default OSD and overwritte with the user's defined keys */
const osd = { templateHTML, templateXML, templateSuggestions };
this.osd = new OpenSearchDescription({...DEFAULT_OSD, ...osd});
}

/* add a new user engine to the list of user symbols' engines */
Expand Down
52 changes: 52 additions & 0 deletions src/open-search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export const DEFAULT_OSD = {
shortName: "Find",
description: "Find Search",
image: "https://example.org/i4k-find/assets/favicon.ico",
templateHTML: "https://example.org/i4k-find/#q={searchTerms}",
templateXML: "https://example.org/i4k-find/assets/opensearch.xml",
templateSuggestions: "https://example.org/i4k-find/api/suggestions/#q={searchTerms}",
};

/* generate the OSD needed to register as a browser search engine */
export class OpenSearchDescription {
get attributes() {
return [
"shortName",
"description",
"templateHTML",
"templateXML",
"templateSuggestions",
"image",
];
}
get config() {
return this.attributes.reduce((acc, val) => {
acc[val] = this[val];
return acc;
}, {});
}
constructor(config) {
this.attributes.forEach((attr) => {
const isSet = config.hasOwnProperty(attr);
const val = isSet ? config[attr] : DEFAULT_OSD[attr];
this[attr] = val;
});
}
exportJSON() {
return JSON.stringify({ ...this.config }, null, 2);
}
exportXML() {
const config = { ...this.config };
return `<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<InputEncoding>UTF-8</InputEncoding>
<ShortName>${config.shortName}</ShortName>
<Description>${config.description}</Description>
<Image height="64" width="64" type="image/png">${config.image}</Image>
<Url type="text/html" template="${config.templateHTML}" method="GET"/>
<Url type="application/opensearchdescription+xml" rel="search" template="${config.templateXML}" method="GET"/>
<Url type="application/x-suggestions+json" rel="suggestions" template="${config.templateSuggestions}" method="GET"/>
</OpenSearchDescription>`;
/* <moz:SearchForm>${config.templateHTML}</moz:SearchForm> */
}
}
63 changes: 49 additions & 14 deletions src/scripts/opensearch-xml.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { I4kFind } from "../index.js";
import { OpenSearchDescription } from "../open-search.js";
import packageJson from "../../package.json" assert { type: "json" };

import fs from "fs/promises";
import path from "path";

Expand Down Expand Up @@ -41,27 +40,63 @@ const newUserConfig = async (baseUrl) => {

const openSearchXml = async () => {
const { I4K_FIND_URL } = process.env;
if (!I4K_FIND_URL) {
throw "missing I4K_FIND_URL=https://example.org/my-find"
}
let newConfig;
try {
newConfig = await newUserConfig(I4K_FIND_URL);
} catch (e) {
console.error(e);
newConfig = config;
}
const find = new I4kFind(newConfig);
const xmlOutput = find.osd.exportXML();
const {
shortName,
description,
image,
templateHTML,
templateXML,
templateSuggestions,
} = config
const osd = new OpenSearchDescription({
shortName,
description,
image,
templateHTML,
templateXML,
templateSuggestions,
});
const xmlOutput = osd.exportXML();
return xmlOutput
};

if (OSD_PATH) {
try {
const localPath = path.join(process.cwd(), OSD_PATH);
await path.resolve(localPath);
await fs.writeFile(localPath, xmlOutput);
} catch (e) {
console.error("Unable to write opensearch.xml", e);
}
const init = async () => {
const argumementsUrlHash = process.argv[2]
let userArgs
try {
userArgs = new URLSearchParams(argumementsUrlHash)
} catch(e) {
/* console.log("No user scrip 'URL arguments'", process.argv) */
}
};

openSearchXml().catch((e) => console.error(e));
const {
generate = false
} = userArgs

const osdXml = await openSearchXml()
if (generate) {
if (outputPath) {
try {
const localPath = path.join(process.cwd(), OSD_PATH);
await path.resolve(localPath);
await fs.writeFile(localPath, osdXml);
} catch (e) {
throw(e);
}
}
}
return osdXml
}
init()

export default openSearchXml;
48 changes: 48 additions & 0 deletions src/tests/open-search-xml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import test from "ava";
import find, { I4kFind } from "../index.js";
import { OpenSearchDescription } from "../open-search.js"
import openSearchXml from '../scripts/opensearch-xml.js'

const TEST_JSON = {
shortName: "Find",
description: "Find search",
image: "https://test.local/my-other-find/assets/favicon.ico",
templateHTML: "https://test.local/my-other-find/#q={searchTerms}",
templateXML: "https://test.local/my-other-find/assets/opensearch.xml",
templateSuggestions:
"https://test.local/my-other-find/api/suggestions/#q={searchTerms}",
};

const TEST_XML = `<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<InputEncoding>UTF-8</InputEncoding>
<ShortName>Find</ShortName>
<Description>Find search</Description>
<Image height="64" width="64" type="image/png">https://test.local/my-find/assets/favicon.ico</Image>
<Url type="text/html" template="https://test.local/my-find/#q={searchTerms}" method="GET"/>
<Url type="application/opensearchdescription+xml" rel="search" template="https://test.local/my-find/assets/opensearch.xml" method="GET"/>
<Url type="application/x-suggestions+json" rel="suggestions" template="https://test.local/my-find/api/suggestions/#q={searchTerms}" method="GET"/>
</OpenSearchDescription>`;

test.afterEach(() => {
process.env.I4K_FIND_URL = '';
})

test("Not setting I4K_FIND_URL screams error", async (t) => {
process.env.I4K_FIND_URL = '';
t.throws(() => {
await openSearchXml()
});
})

test("Setting I4K_FIND_URL generates the OpenSearch XML", async (t) => {
process.env.I4K_FIND_URL = 'https://test.local/my-find';
const osdXml = await openSearchXml()
t.deepEqual(osdXml, TEST_XML);
})

test("Setting I4K_FIND_URL generates the OpenSearch JSON", async (t) => {
process.env.I4K_FIND_URL = 'https://test.local/my-other-find';
const osdJson = await openSearchJson()
t.deepEqual(osdJson, TEST_JSON);
})
58 changes: 22 additions & 36 deletions src/tests/open-search.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,35 @@
import test from "ava";
import find, { I4kFind, OpenSearchDescription } from "../../src/index.js";
import find, { I4kFind } from "../index.js";
import { OpenSearchDescription } from "../open-search.js"

const CONFIG_EXPORT = {
const TEST_CONFIG = {
shortName: "Find",
description: "Find anything anywhere",
image: "https://internet4000.github.io/find/assets/favicon.ico",
templateHTML: "https://internet4000.github.io/find/#q={searchTerms}",
templateXML: "https://internet4000.github.io/find/assets/opensearch.xml",
description: "Find search",
image: "https://example.local/test-find/assets/favicon.ico",
templateHTML: "https://example.local/test-find/#q={searchTerms}",
templateXML: "https://example.local/test-find/assets/opensearch.xml",
templateSuggestions:
"https://internet4000.github.io/find/api/suggestions/#q={searchTerms}",
"https://example.local/test-find/api/suggestions/#q={searchTerms}",
};

let CONFIG_EMPTY = { ...CONFIG_EXPORT }
CONFIG_EMPTY.templateHTML = undefined
CONFIG_EMPTY.templateXML = undefined
CONFIG_EMPTY.templateSuggestions = undefined

const XML_EXPORT = `<?xml version="1.0" encoding="UTF-8"?>
const TEST_XML = `<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<InputEncoding>UTF-8</InputEncoding>
<ShortName>Find</ShortName>
<Description>Find anything anywhere</Description>
<Image height="64" width="64" type="image/png">https://internet4000.github.io/find/assets/favicon.ico</Image>
<Url type="text/html" template="https://internet4000.github.io/find/#q={searchTerms}" method="GET"/>
<Url type="application/opensearchdescription+xml" rel="search" template="https://internet4000.github.io/find/assets/opensearch.xml" method="GET"/>
<Url type="application/x-suggestions+json" rel="suggestions" template="https://internet4000.github.io/find/api/suggestions/#q={searchTerms}" method="GET"/>
<Description>Find search</Description>
<Image height="64" width="64" type="image/png">https://example.local/test-find/assets/favicon.ico</Image>
<Url type="text/html" template="https://example.local/test-find/#q={searchTerms}" method="GET"/>
<Url type="application/opensearchdescription+xml" rel="search" template="https://example.local/test-find/assets/opensearch.xml" method="GET"/>
<Url type="application/x-suggestions+json" rel="suggestions" template="https://example.local/test-find/api/suggestions/#q={searchTerms}" method="GET"/>
</OpenSearchDescription>`;
/* <moz:SearchForm>https://internet4000.github.io/find/#q={searchTerms}</moz:SearchForm> */
/* <moz:SearchForm>https://example.local/test-find/#q={searchTerms}</moz:SearchForm> */

test("OpenSearchDescription is in Find with a config", (t) => {
t.like(CONFIG_EMPTY, find.osd.config);
});
test("OpenSearch can export to JSON", (t) => {
const myFind = new I4kFind({
templateHTML:CONFIG_EXPORT.templateHTML,
templateXML: CONFIG_EXPORT.templateXML,
templateSuggestions: CONFIG_EXPORT.templateSuggestions,
})
t.like(JSON.parse(myFind.osd.exportJSON()), CONFIG_EXPORT);
test("OpenSearch can export to JSON data", (t) => {
const myOsd = new OpenSearchDescription({...TEST_CONFIG})
t.like(JSON.parse(myOsd.exportJSON()), TEST_CONFIG);
});
test("OpenSearch can export to XML", (t) => {
const myFind = new I4kFind({
templateHTML:CONFIG_EXPORT.templateHTML,
templateXML: CONFIG_EXPORT.templateXML,
templateSuggestions: CONFIG_EXPORT.templateSuggestions,
})
t.deepEqual(myFind.osd.exportXML(), XML_EXPORT);

test("OpenSearch can export to XML data", (t) => {
const myOsd = new OpenSearchDescription({...TEST_CONFIG})
t.deepEqual(myOsd.exportXML(), TEST_XML);
});

0 comments on commit 1cd1882

Please sign in to comment.