Skip to content

Commit

Permalink
add search functionality to ds (#2977)
Browse files Browse the repository at this point in the history
* update

* implement

* update as per PR comment

* remove file added to git ignore

* Update src/layout/_dsTemplate.njk

Co-authored-by: rmccar <[email protected]>

* update template

* revert

* update

* update

* add placeholder

* Update src/layout/_dsTemplate.njk

Co-authored-by: rmccar <[email protected]>

* update label text

* Update src/layout/_dsTemplate.njk

Co-authored-by: rmccar <[email protected]>

---------

Co-authored-by: rmccar <[email protected]>
Co-authored-by: Alessio Venturini <[email protected]>
  • Loading branch information
3 people authored Dec 18, 2023
1 parent 49880bb commit c54d06c
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ secrets.yml

# Local Netlify folder
.netlify

# search index data
search-index.json
70 changes: 70 additions & 0 deletions lib/build-search-index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import fs from 'fs';
import path from 'path';
import { globSync } from 'glob';
import frontMatter from 'front-matter';
import nunjucks from 'nunjucks';

function buildEntries(templatePath, type) {
templatePath = path.resolve(templatePath);

return {
title: path.basename(templatePath, '.njk'),
uri: templatePath.replace('.njk', '.html').substring(templatePath.indexOf(`/${type}`)),
};
}

export default async function buildSearchIndex() {
let types = ['components', 'patterns', 'foundations'];
const pages = [];
types.forEach((type) => {
const hasExample = globSync(`./src/${type}/**/*example-*`).sort();
const templatePath = Array.from(new Set(hasExample.map((filePath) => path.dirname(filePath))));

if (templatePath.length) {
pages.push(...templatePath.map((folderPath) => buildEntries(folderPath, type)));
}
});
const result = pages.map((page) => {
const path = [];

return {
en: page.title,
url: page.uri,
category: path.join(' › '),
tags: page.searchTerms?.map((term) => term.title),
};
});
const filePath = process.cwd();
const searchIndexJson = JSON.stringify(result);
fs.writeFile(`${filePath}/src/static/examples/data/search-index.json`, searchIndexJson, (err) => {
if (err) console.log(err);
});
}

export function renderSearch(templatePath, nunjucksEnvironment) {
try {
const data = frontMatter(fs.readFileSync(templatePath, { encoding: 'utf8' }));
const layout = data.attributes.layout;
nunjucksEnvironment.addGlobal('isDesignSystemExample', true);

let template;
if (layout === null) {
template = data.body;
} else {
template = `
{% extends 'layout/_template.njk' %}
{% block body %}
${data.body}
{% endblock %}
`;
}

const compiledTemplate = nunjucks.compile(template, nunjucksEnvironment, templatePath);

return compiledTemplate.render(templatePath);
} catch (err) {
console.error(`An error occurred whilst rendering: ${templatePath}`);
throw err;
}
}
9 changes: 8 additions & 1 deletion lib/config.indexPage.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { renderSearch } from './build-search-index';
import createNunjucksEnvironment from './create-nunjucks-environment';

export const pages = [
{ title: 'Components', uri: '/components' },
{ title: 'Patterns', uri: '/patterns' },
{ title: 'Foundations', uri: '/foundations' },
];

export const pagesWithIndex = pages.map(page => ({ ...page, uri: `${page.uri}/index.html` }));
export const pagesWithIndex = pages.map((page) => ({ ...page, uri: `${page.uri}/index.html` }));

export const title = 'ONS Design System';

const nunjucksEnvironment = createNunjucksEnvironment();
const PROJECT_PATH = process.cwd();
export const pageSearch = renderSearch(`${PROJECT_PATH}/src/layout/_dsTemplate.njk`, nunjucksEnvironment);
7 changes: 4 additions & 3 deletions lib/dev-server.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import cors from 'cors';
import express from 'express';

import renderPageList from './render-page-list';
import { handleTypeRoute, handleExamplesRoute } from './handle-routes';
import { pages, title } from './config.indexPage';
import { pages, title, pageSearch } from './config.indexPage';
import buildSearchIndex from './build-search-index';

process.env.IS_DEV_SERVER = true;
const port = process.env.TEST_PORT ?? 3010;
Expand All @@ -30,7 +30,8 @@ const port = process.env.TEST_PORT ?? 3010;
});

app.get('/', async (req, res) => {
const output = renderPageList(pages, title);
const output = renderPageList(pages, title, pageSearch);
await buildSearchIndex();
res.send(output);
});

Expand Down
3 changes: 2 additions & 1 deletion lib/render-page-list.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function renderPageList(pages, title) {
export default function renderPageList(pages, title, pageSearch = '') {
return `
<!doctype html>
<html lang="en">
Expand All @@ -9,6 +9,7 @@ export default function renderPageList(pages, title) {
</head>
<body class="ons-u-p-m">
<h1>${title}</h1>
${pageSearch}
<ul class="ons-list ons-list--dashed ons-u-pb-l">
${pages
.map(
Expand Down
33 changes: 33 additions & 0 deletions src/layout/_dsTemplate.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{% from "components/autosuggest/_macro.njk" import onsAutosuggest %}

{% set inputWithSearch = {
"id": 'search-field',
"width": '20',
"label": {
"text": "Search",
"id": "search-field-label",
"classes": "ons-u-pl-m"
},
"classes": "ons-input-search ons-input-search--icon ons-input-search--dark ons-u-mb-s",
"accessiblePlaceholder": true,
"autocomplete": "off"
}
%}

{{ onsAutosuggest({
"id": "search-input-autosuggest",
"input": inputWithSearch,
"containerClasses": "ons-autosuggest--header",
"instructions": "Use up and down keys to navigate suggestions once you\'ve typed more than two characters. Use the enter key to select a suggestion. Touch device users, explore by touch or with swipe gestures.",
"ariaYouHaveSelected": "You have selected",
"ariaMinChars": "Enter 3 or more characters for suggestions.",
"ariaOneResult": "There is one suggestion available.",
"ariaNResults": "There are {n} suggestions available.",
"ariaLimitedResults": "Results have been limited to 10 suggestions. Type more characters to improve your search",
"moreResults": "Continue entering to improve suggestions",
"resultsTitle": "Suggestions",
"resultsTitleId": "results-suggestions",
"autosuggestData": "/examples/data/search-index.json",
"noResults": "No suggestions found",
"typeMore": "Continue entering to get suggestions"
}) }}

0 comments on commit c54d06c

Please sign in to comment.