Skip to content

Commit

Permalink
Dynamically Load Search
Browse files Browse the repository at this point in the history
  • Loading branch information
Jieiku committed Aug 1, 2022
1 parent 0e57376 commit cf95ee5
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 21 deletions.
70 changes: 66 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,58 @@ By default abridge uses `highlight_theme = "css"`.

This allows the code block light/dark mode to change with the rest of the site, this also prevents unsafe-inline for style-src in our CSP.

**IMPORTANT!** by default abridge dynamically loads the js related to the search when the search box is clicked, this allows for a faster page load and saved bandwidth. (not everyone needs or will use the search!)

This feature uses a bundle that has all js related to the search in a single js file, this ensures that the files are in the proper order, and that once downloaded the search is ready to use.

to generate this file you have to do this:

```shell
zola build
npm run abridge
zola build
```

or if testing/running the theme directly:

```shell
zola build
npm run abridge-demo
zola build
```

I completely understand that this makes configuration a bit complicated. Zola does not have any built-in facilities for bundling javascript so we are using uglifyjs, shasum, openssl, etc (all defined in package.json) If you find this too difficult then I highly suggest just disabling the facade and loading the search index with the rest of the page:

To disable the facade (dynamic loading of search), you can do this by commenting out the facade line in the config.toml.
You also need to change the bundle that you use:

```toml
#js_search_facade = "search_facade.js" # Do not load search until user interaction with search. [comment out to disable]
js_bundle = "abridge-nofacade.min.js"
```

The Abridge demo uses netlify, and the included package.json and netlify.toml files handle this extra bundle step for us automatically.

An overview of this logic is this:

```shell
zola build # just to generate search_index.en.js
uglifyjs to create search_bundle.min.js # all search related files
update sha256 hash and base64 encoded sha384 hash in search_facade.js file for cachebust and subresource integrity
uglifyjs to create abridge-bundle.min.js to include search_facade.js with the new hashes.
zola build to update the hashes for abridge-bundle.min.js
```

If you plan to use the included netlify.toml file you should change the following:
```toml
command = "zola build && npm run abridge-demo && zola build"
```

to this:
```toml
command = "zola build && npm run abridge && zola build"
```

### Step 4: Add new content

You can copy the content from the theme directory to your project:
Expand Down Expand Up @@ -153,20 +205,30 @@ These are the javascript files currently used by Abridge:

- search_index.en.js: search index generated by zola at each build for elasticlunr.
- elasticlunr.min.js: search library for client side searching.
- email.js: uses javascript to obfuscate your real email address for the mail icon at the bottom of the page.
- search.js: to make use of elasticlunr from our sites search box for both suggestions and the results page.
- search_facade.js: used to dynamically load a bundle containing all search related js ONLY when the search box is clicked.
- codecopy.js: add a Copy Button to code blocks, to copy contents of the code block to clipboard.
- theme.js: very tiny script to facilitate local storage for the theme switcher. (never bundle, gets loaded separate)
- theme_button.js: tiny script for the theme switcher function when you click the theme switch button.
- prestyle.js: Used to preload css files `<link rel="preload"` - this script changes these to `<link rel="stylesheet"` once the page has finished loading, this allows us to load stylesheets for external fonts, fontawesome, or katex in a non blocking fashion.

js_bundle is set to a javascript file with a bundle of multiple javascript files, this allows us to serve fewer javascript files (only the search index and the bundle). Included are a few of the likely most commonly used combinations, but you can generate these yourself using uglifyjs if you need to, there are examples in the config.toml, eg:

`uglifyjs prestyle.js theme_button.js elasticlunr.min.js search.js -o abridge-switcher.min.js -c -m`
`uglifyjs prestyle.js theme_button.js elasticlunr.min.js search.js -c -m -o abridge-nofacade.min.js`

Abridge Default Bundle:
- abridge-bundle.min.js: includes: prestyle, theme_button, search_facade, email, codecopy

- search.min.js - includes: elasticlunr, search.
- abridge.min.js - includes: prestyle, elasticlunr, search.
- abridge-switcher.min.js: includes: prestyle, theme_button, elasticlunr, search.
Abridge Alternate Bundles:
- abridge-searchonly.min.js - includes: elasticlunr, search
- abridge-noswitcher.min.js - includes: prestyle, email, codecopy, elasticlunr, search
- abridge-nofacade.min.js: includes: prestyle, theme_button, email, codecopy, elasticlunr, search

Support Files:
- theme.min.js (not a bundle, just a minification of theme.js)
- katexbundle.min.js - includes: katex.min.js mathtex-script-type.min.js auto-render.min.js katexoptions.js
- search_bundle.min.js: includes: search_index.en, elasticlunr, search

### Global Configuration

Expand Down
11 changes: 5 additions & 6 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,14 @@ integrity = true # setting this to false is useful for developing, should normal
js_search_index = "search_index.en.js" # Separate Always, generated each build
js_prestyle = "prestyle.js"# Bundleable - used to preload: FontAwesome, Katex, external Google Fonts
js_search = [ "elasticlunr.min.js", "search.js" ]# Bundleable
js_search_facade = "search_facade.js" # Do not load search until user interaction with search. [comment out to disable]
js_codecopy = "codecopy.js"# Bundleable
js_email = "email.js"# Bundleable

########## Switcher ########## (comment this block out if NOT using switcher):
js_theme = "theme.min.js" # Separate Always, comment out if using -auto/-light/-dark stylesheet. (required for switcher)
js_themeButton = "theme_button.js"# Bundleable
js_bundle = "abridge-switcher.min.js"# Bundle JS File, comment out to disable (includes switcher)
js_bundle = "abridge-bundle.min.js"# Bundle JS File, comment out to disable (includes switcher)
stylesheets = [ "abridge-switcher.css" ] # Orange Automatic Dark/Light Theme based on browser/system preference with switcher
#stylesheets = [ "abridge-blue-switcher.css" ] # Blue Automatic Night/Light Theme based on browser/system preference with switcher
#stylesheets = [ "abridge-blueshade-switcher.css" ] # BlueShade Automatic Night/Light Theme based on browser/system preference with switcher
Expand All @@ -130,11 +131,9 @@ stylesheets = [ "abridge-switcher.css" ] # Orange Automatic Dark/Light Theme bas
# If you have js_bundle set, then Bundleable js files are ignored (it's assumed you bundled them).
# You can include whatever js you want in your bundle. just generate your file like below and place in your sites root static directory:
# cd mysite/themes/abridge/static
# search: uglifyjs elasticlunr.min.js search.js -o search.min.js -c -m
# noswitcher: uglifyjs prestyle.js email.js codecopy.js elasticlunr.min.js search.js -o abridge.min.js -c -m
# ALL: uglifyjs prestyle.js theme_button.js email.js codecopy.js elasticlunr.min.js search.js -o abridge-switcher.min.js -c -m
# theme: uglifyjs theme.js -o theme.min.js -c -m
# katex_bundle: uglifyjs katex.min.js mathtex-script-type.min.js auto-render.min.js katexoptions.js -o katexbundle.min.js -c -m
# searchonly: uglifyjs elasticlunr.min.js search.js -c -m -o abridge-searchonly.min.js
# noswitcher: uglifyjs prestyle.js email.js codecopy.js elasticlunr.min.js search.js -c -m -o abridge-noswitcher.min.js
# nofacade: uglifyjs prestyle.js theme_button.js email.js codecopy.js elasticlunr.min.js search.js -c -m -o abridge-nofacade.min.js

banner = "banner.png" # Used as default image for OpenGraph/Twitter if page specific image is undefined.
# favicons, comment out a line to disable loading some or all of these.
Expand Down
2 changes: 1 addition & 1 deletion content/pages/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Abridge was created by [Jake G (jieiku)](https://github.com/Jieiku) to be fast a
Some fun facts about the theme:

* Perfect score on Google's Lighthouse audit
* Only ~6 KB of CSS before enabling the SVG CSS icons.
* Only ~6 KB of CSS before enabling the SVG CSS icons and syntax highlighting.
* No mandatory JavaScript.
* Now with SEO!

Expand Down
6 changes: 3 additions & 3 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[build]
publish = "public"
command = "zola build"
command = "zola build && npm run abridge-demo && zola build"

[build.environment]
ZOLA_VERSION = "0.15.3"
ZOLA_VERSION = "0.16.0"

[context.deploy-preview]
command = "zola build --base-url $DEPLOY_PRIME_URL"
command = "zola build --base-url $DEPLOY_PRIME_URL && npm run abridge-demo && zola build --base-url $DEPLOY_PRIME_URL"

[[headers]]
for = "/*"
Expand Down
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "abridge-bundle",
"version": "1.1.0",
"description": "Abridge - bundle and minify js",
"author": "Jake G <106644+Jieiku@users.noreply.github.com>",
"license": "MIT",
"homepage": "https://github.com/Jieiku/abridge",
"scripts": {
"searchonly": "uglifyjs static/elasticlunr.min.js static/search.js -c -m -o static/abridge-searchonly.min.js",
"noswitcher": "uglifyjs static/prestyle.js static/email.js static/codecopy.js static/elasticlunr.min.js static/search.js -c -m -o static/abridge-noswitcher.min.js",
"nofacade": "uglifyjs static/prestyle.js static/theme_button.js static/email.js static/codecopy.js static/elasticlunr.min.js static/search.js -c -m -o static/abridge-nofacade.min.js",
"theme": "uglifyjs static/theme.js -c -m -o static/theme.min.js",
"katex-bundle": "uglifyjs static/katex.min.js static/mathtex-script-type.min.js static/auto-render.min.js static/katexoptions.js -c -m -o static/katexbundle.min.js",
"search-bundle": "uglifyjs public/search_index.en.js public/elasticlunr.min.js public/search.js -c -m -o static/search_bundle.min.js",
"sha256": "sha256=$(shasum -b -a 256 'static/search_bundle.min.js' | awk '{ print $1 }') && echo $sha256 && sed -i \"s|sha256='.*'|sha256='$sha256'|\" 'themes/abridge/static/search_facade.js'",
"sha256-demo": "sha256=$(shasum -b -a 256 'static/search_bundle.min.js' | awk '{ print $1 }') && echo $sha256 && sed -i \"s|sha256='.*'|sha256='$sha256'|\" 'static/search_facade.js'",
"sha384": "sha384=$(openssl dgst -sha384 -binary 'static/search_bundle.min.js' | openssl base64) && echo $sha384 && sed -i \"s|sha384='.*'|sha384='$sha384'|\" 'themes/abridge/static/search_facade.js'",
"sha384-demo": "sha384=$(openssl dgst -sha384 -binary 'static/search_bundle.min.js' | openssl base64) && echo $sha384 && sed -i \"s|sha384='.*'|sha384='$sha384'|\" 'static/search_facade.js'",
"abridge-bundle": "uglifyjs themes/abridge/static/prestyle.js themes/abridge/static/theme_button.js themes/abridge/static/search_facade.js themes/abridge/static/email.js themes/abridge/static/codecopy.js -c -m -o static/abridge-bundle.min.js",
"abridge-bundle-demo": "uglifyjs static/prestyle.js static/theme_button.js static/search_facade.js static/email.js static/codecopy.js -c -m -o static/abridge-bundle.min.js",
"abridge-demo": "npm run search-bundle && npm run sha256-demo && npm run sha384-demo && npm run abridge-bundle-demo",
"abridge": "npm run search-bundle && npm run sha256 && npm run sha384 && npm run abridge-bundle",
"all": "npm run searchonly && npm run noswitcher && npm run nofacade && npm run theme && npm run katex-bundle && npm run abridge-demo"
},
"dependencies": {
"uglify-js": "^3.15.4"
}
}
1 change: 1 addition & 0 deletions static/abridge-bundle.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion static/abridge.min.js → static/abridge-noswitcher.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion static/search.min.js → static/abridge-searchonly.min.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion static/elasticlunr_search.min.js

This file was deleted.

1 change: 1 addition & 0 deletions static/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,4 +333,5 @@ Source:
teaser.push("…");
return teaser.join("");
}
document.body.contains(document.goSearch) && (document.goSearch.onsubmit = function() { return goSearchNow() })
}());
1 change: 1 addition & 0 deletions static/search_bundle.min.js

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions static/search_facade.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var sha256='b00061ff14234bb637b048af272163401458e658b12d3a7d440fff38f54d309c';
var sha384='S1U+nC05HTi/o4S13KbBlxk4d4/HoWRXeZmGy8QPTLs1SM5QjdDaxUsyBEvG850D';
function loadSearchNow() {
var loadSearch = document.createElement('script');
loadSearch.src = '/search_bundle.min.js?h=' + sha256;
loadSearch.setAttribute('integrity', 'sha384-' + sha384);
document.head.appendChild(loadSearch);
document.getElementById('userinput').onclick = '';
}
window.onload = function() {
document.getElementById('userinput').onclick = function() { return loadSearchNow() }
};
16 changes: 13 additions & 3 deletions templates/macros/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@

{%- if config.build_search_index and config.extra.js_bundle %}

{%- if config.extra.js_search_index %}
{%- if config.extra.js_search_facade %}
{# dont load the index #}
{%- elif config.extra.js_search_index %}
<script defer src="{{ get_url(path=config.extra.js_search_index, trailing_slash=false, cachebust=true) | safe }}"{%- if config.extra.integrity %} integrity="sha384-{{ get_file_hash(path=config.extra.js_search_index, sha_type=384, base64=true) | safe }}"{%- endif %}></script>
{%- endif %}

Expand Down Expand Up @@ -106,10 +108,18 @@
<script defer src="{{ get_url(path=config.extra.js_codecopy, trailing_slash=false, cachebust=true) | safe }}"{%- if config.extra.integrity %} integrity="sha384-{{ get_file_hash(path=config.extra.js_codecopy, sha_type=384, base64=true) | safe }}"{%- endif %}></script>
{%- endif %}

{%- if config.extra.js_search_index %}
{%- if config.extra.js_search_facade %}
<script defer src="{{ get_url(path='search_facade.js', trailing_slash=false, cachebust=true) | safe }}"{%- if config.extra.integrity %} integrity="sha384-{{ get_file_hash(path='search_facade.js', sha_type=384, base64=true) | safe }}"{%- endif %}></script>
{%- endif %}

{%- if config.extra.js_search_facade %}
<script defer src="{{ get_url(path=config.extra.js_search_facade, trailing_slash=false, cachebust=true) | safe }}"{%- if config.extra.integrity %} integrity="sha384-{{ get_file_hash(path=config.extra.js_search_facade, sha_type=384, base64=true) | safe }}"{%- endif %}></script>
{%- elif config.extra.js_search_index %}
<script defer src="{{ get_url(path=config.extra.js_search_index, trailing_slash=false, cachebust=true) | safe }}"{%- if config.extra.integrity %} integrity="sha384-{{ get_file_hash(path=config.extra.js_search_index, sha_type=384, base64=true) | safe }}"{%- endif %}></script>
{%- endif %}
{%- if config.extra.js_search %}{%- for i in config.extra.js_search %}
{%- if config.extra.js_search_facade %}
{# dont load the index/search #}
{%- elif config.extra.js_search %}{%- for i in config.extra.js_search %}
<script defer src="{{ get_url(path=i, trailing_slash=false, cachebust=true) | safe }}"{%- if config.extra.integrity %} integrity="sha384-{{ get_file_hash(path=i, sha_type=384, base64=true) | safe }}"{%- endif %}></script>
{%- endfor %}{%- endif %}

Expand Down

0 comments on commit cf95ee5

Please sign in to comment.