A JavaScript library to add search functionality to any Jekyll blog.
You have a blog, built with Jekyll, and want a lightweight search functionality on your blog, purely client-side?
No server configurations or databases to maintain.
Just 5 minutes to have a fully working searchable blog.
npm install simple-jekyll-search
search.json
Place the following code in a file called search.json
in the root of your Jekyll blog. (You can also get a copy from here)
This file will be used as a small data source to perform the searches on the client side:
---
layout: none
---
[
{
"title" : "Boat and Drone Testing",
"category" : "",
"tags" : "",
"url" : "/2021/04/19/outdoor-testing/",
"date" : "2021-04-19 00:00:00 +0000"
} ,
{
"title" : "Boat Build Process",
"category" : "",
"tags" : "",
"url" : "/2021/04/18/boat-build-process/",
"date" : "2021-04-18 00:00:00 +0000"
} ,
{
"title" : "Minecraft Social Nights",
"category" : "",
"tags" : "",
"url" : "/2021/04/03/minecraft/",
"date" : "2021-04-03 00:00:00 +0000"
} ,
{
"title" : "TED Talks",
"category" : "",
"tags" : "",
"url" : "/2021/03/31/ted-talks/",
"date" : "2021-03-31 00:00:00 +0000"
} ,
{
"title" : "Burger Night",
"category" : "",
"tags" : "",
"url" : "/2020/11/25/burger-night/",
"date" : "2020-11-25 00:00:00 +0000"
}
]
SimpleJekyllSearch needs two DOM
elements to work:
Here is the code you can use with the default configuration:
You need to place the following code within the layout where you want the search to appear. (See the configuration section below to customize it)
For example in _layouts/default.html:
<!-- HTML elements for search -->
<input type="text" id="search-input" placeholder="Search blog posts..">
<ul id="results-container"></ul>
<!-- or without installing anything -->
<script src="https://unpkg.com/simple-jekyll-search@latest/dest/simple-jekyll-search.min.js"></script>
Customize SimpleJekyllSearch by passing in your configuration options:
var sjs = SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json'
})
A new instance of SimpleJekyllSearch returns an object, with the only property search
.
search
is a function used to simulate a user input and display the matching results.
E.g.:
var sjs = SimpleJekyllSearch({ ...options })
sjs.search('Hello')
💡 it can be used to filter posts by tags or categories!
Here is a list of the available options, usage questions, troubleshooting & guides.
The input element on which the plugin should listen for keyboard event and trigger the searching and rendering for articles.
The container element in which the search results should be rendered in. Typically a <ul>
.
You can either pass in an URL to the search.json
file, or the results in form of JSON directly, to save one round trip to get the data.
The template of a single rendered search result.
The templating syntax is very simple: You just enclose the properties you want to replace with curly braces.
E.g.
The template
var sjs = SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
searchResultTemplate: '<li><a href="https://umautonomy.com{url}">{title}</a></li>'
})
will render to the following
<li><a href="/jekyll/update/2014/11/01/welcome-to-jekyll.html">Welcome to Jekyll!</a></li>
If the search.json
contains this data
[
{
"title" : "Welcome to Jekyll!",
"category" : "",
"tags" : "",
"url" : "/jekyll/update/2014/11/01/welcome-to-jekyll.html",
"date" : "2014-11-01 21:07:22 +0100"
}
]
A function that will be called whenever a match in the template is found.
It gets passed the current property name, property value, and the template.
If the function returns a non-undefined value, it gets replaced in the template.
This can be potentially useful for manipulating URLs etc.
Example:
SimpleJekyllSearch({
...
templateMiddleware: function(prop, value, template) {
if (prop === 'bar') {
return value.replace(/^\//, '')
}
}
...
})
See the tests for an in-depth code example
A function that will be used to sort the filtered results.
It can be used for example to group the sections together.
Example:
SimpleJekyllSearch({
...
sortMiddleware: function(a, b) {
var astr = String(a.section) + "-" + String(a.caption);
var bstr = String(b.section) + "-" + String(b.caption);
return astr.localeCompare(bstr)
}
...
})
The HTML that will be shown if the query didn’t match anything.
You can limit the number of posts rendered on the page.
Enable fuzzy search to allow less restrictive matching.
Pass in a list of terms you want to exclude (terms will be matched against a regex, so URLs, words are allowed).
A function called once the data has been loaded.
Limit how many times the search function can be executed over the given time window. This is especially useful to improve the user experience when searching over a large dataset (either with rare terms or because the number of posts to display is large). If no debounceTime
(milliseconds) is provided a search will be triggered on each keystroke.
remove_chars
as a filter.For example: in search.json, replace
"content": "# [Simple-Jekyll-Search](https://www.npmjs.com/package/simple-jekyll-search)[](https://travis-ci.org/christian-fei/Simple-Jekyll-Search)[](https://david-dm.org/christian-fei/Simple-Jekyll-Search)[](https://david-dm.org/christian-fei/Simple-Jekyll-Search?type=dev)A JavaScript library to add search functionality to any Jekyll blog.## Use caseYou have a blog, built with Jekyll, and want a **lightweight search functionality** on your blog, purely client-side?*No server configurations or databases to maintain*.Just **5 minutes** to have a **fully working searchable blog**.---## Installation### npm```shnpm install simple-jekyll-search```## Getting started### Create `search.json`Place the following code in a file called `search.json` in the **root** of your Jekyll blog. (You can also get a copy [from here](/example/search.json))This file will be used as a small data source to perform the searches on the client side:```yaml---layout: none---[ {% for post in site.posts %} { "title" : "{{ post.title | escape }}", "category" : "{{ post.category }}", "tags" : "{{ post.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ post.url }}", "date" : "{{ post.date }}" } {% unless forloop.last %},{% endunless %} {% endfor %}]```## Preparing the plugin### Add DOM elementsSimpleJekyllSearch needs two `DOM` elements to work:- a search input field- a result container to display the results#### Give me the codeHere is the code you can use with the default configuration:You need to place the following code within the layout where you want the search to appear. (See the configuration section below to customize it)For example in **_layouts/default.html**:```html```## UsageCustomize SimpleJekyllSearch by passing in your configuration options:```jsvar sjs = SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), json: '/search.json'})```### returns { search }A new instance of SimpleJekyllSearch returns an object, with the only property `search`.`search` is a function used to simulate a user input and display the matching results. E.g.:```jsvar sjs = SimpleJekyllSearch({ ...options })sjs.search('Hello')```💡 it can be used to filter posts by tags or categories!## OptionsHere is a list of the available options, usage questions, troubleshooting & guides.### searchInput (Element) [required]The input element on which the plugin should listen for keyboard event and trigger the searching and rendering for articles.### resultsContainer (Element) [required]The container element in which the search results should be rendered in. Typically a ``.### json (String|JSON) [required]You can either pass in an URL to the `search.json` file, or the results in form of JSON directly, to save one round trip to get the data.### searchResultTemplate (String) [optional]The template of a single rendered search result.The templating syntax is very simple: You just enclose the properties you want to replace with curly braces.E.g.The template```jsvar sjs = SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), json: '/search.json', searchResultTemplate: '{title}'})```will render to the following```htmlWelcome to Jekyll!```If the `search.json` contains this data```json[ { "title" : "Welcome to Jekyll!", "category" : "", "tags" : "", "url" : "/jekyll/update/2014/11/01/welcome-to-jekyll.html", "date" : "2014-11-01 21:07:22 +0100" }]```### templateMiddleware (Function) [optional]A function that will be called whenever a match in the template is found.It gets passed the current property name, property value, and the template.If the function returns a non-undefined value, it gets replaced in the template.This can be potentially useful for manipulating URLs etc.Example:```jsSimpleJekyllSearch({ ... templateMiddleware: function(prop, value, template) { if (prop === 'bar') { return value.replace(/^\//, '') } } ...})```See the [tests](https://github.com/christian-fei/Simple-Jekyll-Search/blob/master/tests/Templater.test.js) for an in-depth code example### sortMiddleware (Function) [optional]A function that will be used to sort the filtered results.It can be used for example to group the sections together.Example:```jsSimpleJekyllSearch({ ... sortMiddleware: function(a, b) { var astr = String(a.section) + "-" + String(a.caption); var bstr = String(b.section) + "-" + String(b.caption); return astr.localeCompare(bstr) } ...})```### noResultsText (String) [optional]The HTML that will be shown if the query didn't match anything.### limit (Number) [optional]You can limit the number of posts rendered on the page.### fuzzy (Boolean) [optional]Enable fuzzy search to allow less restrictive matching.### exclude (Array) [optional]Pass in a list of terms you want to exclude (terms will be matched against a regex, so URLs, words are allowed).### success (Function) [optional]A function called once the data has been loaded.### debounceTime (Number) [optional]Limit how many times the search function can be executed over the given time window. This is especially useful to improve the user experience when searching over a large dataset (either with rare terms or because the number of posts to display is large). If no `debounceTime` (milliseconds) is provided a search will be triggered on each keystroke.---## If search isn't working due to invalid JSON- There is a filter plugin in the _plugins folder which should remove most characters that cause invalid JSON. To use it, add the simple_search_filter.rb file to your _plugins folder, and use `remove_chars` as a filter.For example: in search.json, replace```json"content": "{{ page.content | strip_html | strip_newlines }}"```with```json"content": "{{ page.content | strip_html | strip_newlines | remove_chars | escape }}"```If this doesn't work when using Github pages you can try `jsonify` to make sure the content is json compatible:```js"content": {{ page.content | jsonify }}```**Note: you don't need to use quotes `"` in this since `jsonify` automatically inserts them.**## Enabling full-text searchReplace `search.json` with the following code:```yaml---layout: none---[ {% for post in site.posts %} { "title" : "{{ post.title | escape }}", "category" : "{{ post.category }}", "tags" : "{{ post.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ post.url }}", "date" : "{{ post.date }}", "content" : "{{ post.content | strip_html | strip_newlines }}" } {% unless forloop.last %},{% endunless %} {% endfor %} , {% for page in site.pages %} { {% if page.title != nil %} "title" : "{{ page.title | escape }}", "category" : "{{ page.category }}", "tags" : "{{ page.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ page.url }}", "date" : "{{ page.date }}", "content" : "{{ page.content | strip_html | strip_newlines }}" {% endif %} } {% unless forloop.last %},{% endunless %} {% endfor %}]```## Development- `npm install`- `npm test`#### Acceptance tests```bashcd example; jekyll serve# in another tabnpm run cypress -- run```## ContributorsThanks to all [contributors](https://github.com/christian-fei/Simple-Jekyll-Search/graphs/contributors) over the years! You are the best :)> [@daviddarnes](https://github.com/daviddarnes)[@XhmikosR](https://github.com/XhmikosR)[@PeterDaveHello](https://github.com/PeterDaveHello)[@mikeybeck](https://github.com/mikeybeck)[@egladman](https://github.com/egladman)[@midzer](https://github.com/midzer)[@eduardoboucas](https://github.com/eduardoboucas)[@kremalicious](https://github.com/kremalicious)[@tibotiber](https://github.com/tibotiber)and many others!## Stargazers over time[](https://starchart.cc/christian-fei/Simple-Jekyll-Search)"
with
"content": "# [Simple-Jekyll-Search](https://www.npmjs.com/package/simple-jekyll-search)[](https://travis-ci.org/christian-fei/Simple-Jekyll-Search)[](https://david-dm.org/christian-fei/Simple-Jekyll-Search)[](https://david-dm.org/christian-fei/Simple-Jekyll-Search?type=dev)A JavaScript library to add search functionality to any Jekyll blog.## Use caseYou have a blog, built with Jekyll, and want a **lightweight search functionality** on your blog, purely client-side?*No server configurations or databases to maintain*.Just **5 minutes** to have a **fully working searchable blog**.---## Installation### npm```shnpm install simple-jekyll-search```## Getting started### Create `search.json`Place the following code in a file called `search.json` in the **root** of your Jekyll blog. (You can also get a copy [from here](/example/search.json))This file will be used as a small data source to perform the searches on the client side:```yaml---layout: none---[ {% for post in site.posts %} { "title" : "{{ post.title | escape }}", "category" : "{{ post.category }}", "tags" : "{{ post.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ post.url }}", "date" : "{{ post.date }}" } {% unless forloop.last %},{% endunless %} {% endfor %}]```## Preparing the plugin### Add DOM elementsSimpleJekyllSearch needs two `DOM` elements to work:- a search input field- a result container to display the results#### Give me the codeHere is the code you can use with the default configuration:You need to place the following code within the layout where you want the search to appear. (See the configuration section below to customize it)For example in **_layouts/default.html**:```html```## UsageCustomize SimpleJekyllSearch by passing in your configuration options:```jsvar sjs = SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), json: '/search.json'})```### returns { search }A new instance of SimpleJekyllSearch returns an object, with the only property `search`.`search` is a function used to simulate a user input and display the matching results. E.g.:```jsvar sjs = SimpleJekyllSearch({ ...options })sjs.search('Hello')```💡 it can be used to filter posts by tags or categories!## OptionsHere is a list of the available options, usage questions, troubleshooting & guides.### searchInput (Element) [required]The input element on which the plugin should listen for keyboard event and trigger the searching and rendering for articles.### resultsContainer (Element) [required]The container element in which the search results should be rendered in. Typically a ``.### json (String|JSON) [required]You can either pass in an URL to the `search.json` file, or the results in form of JSON directly, to save one round trip to get the data.### searchResultTemplate (String) [optional]The template of a single rendered search result.The templating syntax is very simple: You just enclose the properties you want to replace with curly braces.E.g.The template```jsvar sjs = SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), json: '/search.json', searchResultTemplate: '{title}'})```will render to the following```htmlWelcome to Jekyll!```If the `search.json` contains this data```json[ { "title" : "Welcome to Jekyll!", "category" : "", "tags" : "", "url" : "/jekyll/update/2014/11/01/welcome-to-jekyll.html", "date" : "2014-11-01 21:07:22 +0100" }]```### templateMiddleware (Function) [optional]A function that will be called whenever a match in the template is found.It gets passed the current property name, property value, and the template.If the function returns a non-undefined value, it gets replaced in the template.This can be potentially useful for manipulating URLs etc.Example:```jsSimpleJekyllSearch({ ... templateMiddleware: function(prop, value, template) { if (prop === 'bar') { return value.replace(/^\//, '') } } ...})```See the [tests](https://github.com/christian-fei/Simple-Jekyll-Search/blob/master/tests/Templater.test.js) for an in-depth code example### sortMiddleware (Function) [optional]A function that will be used to sort the filtered results.It can be used for example to group the sections together.Example:```jsSimpleJekyllSearch({ ... sortMiddleware: function(a, b) { var astr = String(a.section) + "-" + String(a.caption); var bstr = String(b.section) + "-" + String(b.caption); return astr.localeCompare(bstr) } ...})```### noResultsText (String) [optional]The HTML that will be shown if the query didn't match anything.### limit (Number) [optional]You can limit the number of posts rendered on the page.### fuzzy (Boolean) [optional]Enable fuzzy search to allow less restrictive matching.### exclude (Array) [optional]Pass in a list of terms you want to exclude (terms will be matched against a regex, so URLs, words are allowed).### success (Function) [optional]A function called once the data has been loaded.### debounceTime (Number) [optional]Limit how many times the search function can be executed over the given time window. This is especially useful to improve the user experience when searching over a large dataset (either with rare terms or because the number of posts to display is large). If no `debounceTime` (milliseconds) is provided a search will be triggered on each keystroke.---## If search isn't working due to invalid JSON- There is a filter plugin in the _plugins folder which should remove most characters that cause invalid JSON. To use it, add the simple_search_filter.rb file to your _plugins folder, and use `remove_chars` as a filter.For example: in search.json, replace```json"content": "{{ page.content | strip_html | strip_newlines }}"```with```json"content": "{{ page.content | strip_html | strip_newlines | remove_chars | escape }}"```If this doesn't work when using Github pages you can try `jsonify` to make sure the content is json compatible:```js"content": {{ page.content | jsonify }}```**Note: you don't need to use quotes `"` in this since `jsonify` automatically inserts them.**## Enabling full-text searchReplace `search.json` with the following code:```yaml---layout: none---[ {% for post in site.posts %} { "title" : "{{ post.title | escape }}", "category" : "{{ post.category }}", "tags" : "{{ post.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ post.url }}", "date" : "{{ post.date }}", "content" : "{{ post.content | strip_html | strip_newlines }}" } {% unless forloop.last %},{% endunless %} {% endfor %} , {% for page in site.pages %} { {% if page.title != nil %} "title" : "{{ page.title | escape }}", "category" : "{{ page.category }}", "tags" : "{{ page.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ page.url }}", "date" : "{{ page.date }}", "content" : "{{ page.content | strip_html | strip_newlines }}" {% endif %} } {% unless forloop.last %},{% endunless %} {% endfor %}]```## Development- `npm install`- `npm test`#### Acceptance tests```bashcd example; jekyll serve# in another tabnpm run cypress -- run```## ContributorsThanks to all [contributors](https://github.com/christian-fei/Simple-Jekyll-Search/graphs/contributors) over the years! You are the best :)> [@daviddarnes](https://github.com/daviddarnes)[@XhmikosR](https://github.com/XhmikosR)[@PeterDaveHello](https://github.com/PeterDaveHello)[@mikeybeck](https://github.com/mikeybeck)[@egladman](https://github.com/egladman)[@midzer](https://github.com/midzer)[@eduardoboucas](https://github.com/eduardoboucas)[@kremalicious](https://github.com/kremalicious)[@tibotiber](https://github.com/tibotiber)and many others!## Stargazers over time[](https://starchart.cc/christian-fei/Simple-Jekyll-Search)"
If this doesn’t work when using Github pages you can try jsonify
to make sure the content is json compatible:
"content": "# [Simple-Jekyll-Search](https://www.npmjs.com/package/simple-jekyll-search)\n\n[](https://travis-ci.org/christian-fei/Simple-Jekyll-Search)\n[](https://david-dm.org/christian-fei/Simple-Jekyll-Search)\n[](https://david-dm.org/christian-fei/Simple-Jekyll-Search?type=dev)\n\nA JavaScript library to add search functionality to any Jekyll blog.\n\n## Use case\n\nYou have a blog, built with Jekyll, and want a **lightweight search functionality** on your blog, purely client-side?\n\n*No server configurations or databases to maintain*.\n\nJust **5 minutes** to have a **fully working searchable blog**.\n\n---\n\n## Installation\n\n### npm\n\n```sh\nnpm install simple-jekyll-search\n```\n\n## Getting started\n\n### Create `search.json`\n\nPlace the following code in a file called `search.json` in the **root** of your Jekyll blog. (You can also get a copy [from here](/example/search.json))\n\nThis file will be used as a small data source to perform the searches on the client side:\n\n```yaml\n---\nlayout: none\n---\n[\n {% for post in site.posts %}\n {\n \"title\" : \"{{ post.title | escape }}\",\n \"category\" : \"{{ post.category }}\",\n \"tags\" : \"{{ post.tags | join: ', ' }}\",\n \"url\" : \"{{ site.baseurl }}{{ post.url }}\",\n \"date\" : \"{{ post.date }}\"\n } {% unless forloop.last %},{% endunless %}\n {% endfor %}\n]\n```\n\n\n## Preparing the plugin\n\n### Add DOM elements\n\nSimpleJekyllSearch needs two `DOM` elements to work:\n\n- a search input field\n- a result container to display the results\n\n#### Give me the code\n\nHere is the code you can use with the default configuration:\n\nYou need to place the following code within the layout where you want the search to appear. (See the configuration section below to customize it)\n\nFor example in **_layouts/default.html**:\n\n```html\n<!-- HTML elements for search -->\n<input type=\"text\" id=\"search-input\" placeholder=\"Search blog posts..\">\n<ul id=\"results-container\"></ul>\n\n<!-- or without installing anything -->\n<script src=\"https://unpkg.com/simple-jekyll-search@latest/dest/simple-jekyll-search.min.js\"></script>\n```\n\n\n## Usage\n\nCustomize SimpleJekyllSearch by passing in your configuration options:\n\n```js\nvar sjs = SimpleJekyllSearch({\n searchInput: document.getElementById('search-input'),\n resultsContainer: document.getElementById('results-container'),\n json: '/search.json'\n})\n```\n\n### returns { search }\n\nA new instance of SimpleJekyllSearch returns an object, with the only property `search`.\n\n`search` is a function used to simulate a user input and display the matching results. \n\nE.g.:\n\n```js\nvar sjs = SimpleJekyllSearch({ ...options })\nsjs.search('Hello')\n```\n\n💡 it can be used to filter posts by tags or categories!\n\n## Options\n\nHere is a list of the available options, usage questions, troubleshooting & guides.\n\n### searchInput (Element) [required]\n\nThe input element on which the plugin should listen for keyboard event and trigger the searching and rendering for articles.\n\n\n### resultsContainer (Element) [required]\n\nThe container element in which the search results should be rendered in. Typically a `<ul>`.\n\n\n### json (String|JSON) [required]\n\nYou can either pass in an URL to the `search.json` file, or the results in form of JSON directly, to save one round trip to get the data.\n\n\n### searchResultTemplate (String) [optional]\n\nThe template of a single rendered search result.\n\nThe templating syntax is very simple: You just enclose the properties you want to replace with curly braces.\n\nE.g.\n\nThe template\n\n```js\nvar sjs = SimpleJekyllSearch({\n searchInput: document.getElementById('search-input'),\n resultsContainer: document.getElementById('results-container'),\n json: '/search.json',\n searchResultTemplate: '<li><a href=\"{{ site.url }}{url}\">{title}</a></li>'\n})\n```\n\nwill render to the following\n\n```html\n<li><a href=\"/jekyll/update/2014/11/01/welcome-to-jekyll.html\">Welcome to Jekyll!</a></li>\n```\n\nIf the `search.json` contains this data\n\n```json\n[\n {\n \"title\" : \"Welcome to Jekyll!\",\n \"category\" : \"\",\n \"tags\" : \"\",\n \"url\" : \"/jekyll/update/2014/11/01/welcome-to-jekyll.html\",\n \"date\" : \"2014-11-01 21:07:22 +0100\"\n }\n]\n```\n\n\n### templateMiddleware (Function) [optional]\n\nA function that will be called whenever a match in the template is found.\n\nIt gets passed the current property name, property value, and the template.\n\nIf the function returns a non-undefined value, it gets replaced in the template.\n\nThis can be potentially useful for manipulating URLs etc.\n\nExample:\n\n```js\nSimpleJekyllSearch({\n ...\n templateMiddleware: function(prop, value, template) {\n if (prop === 'bar') {\n return value.replace(/^\\//, '')\n }\n }\n ...\n})\n```\n\nSee the [tests](https://github.com/christian-fei/Simple-Jekyll-Search/blob/master/tests/Templater.test.js) for an in-depth code example\n\n### sortMiddleware (Function) [optional]\n\nA function that will be used to sort the filtered results.\n\nIt can be used for example to group the sections together.\n\nExample:\n\n```js\nSimpleJekyllSearch({\n ...\n sortMiddleware: function(a, b) {\n var astr = String(a.section) + \"-\" + String(a.caption);\n var bstr = String(b.section) + \"-\" + String(b.caption);\n return astr.localeCompare(bstr)\n }\n ...\n})\n```\n\n### noResultsText (String) [optional]\n\nThe HTML that will be shown if the query didn't match anything.\n\n\n### limit (Number) [optional]\n\nYou can limit the number of posts rendered on the page.\n\n\n### fuzzy (Boolean) [optional]\n\nEnable fuzzy search to allow less restrictive matching.\n\n### exclude (Array) [optional]\n\nPass in a list of terms you want to exclude (terms will be matched against a regex, so URLs, words are allowed).\n\n### success (Function) [optional]\n\nA function called once the data has been loaded.\n\n### debounceTime (Number) [optional]\n\nLimit how many times the search function can be executed over the given time window. This is especially useful to improve the user experience when searching over a large dataset (either with rare terms or because the number of posts to display is large). If no `debounceTime` (milliseconds) is provided a search will be triggered on each keystroke.\n\n---\n\n## If search isn't working due to invalid JSON\n\n- There is a filter plugin in the _plugins folder which should remove most characters that cause invalid JSON. To use it, add the simple_search_filter.rb file to your _plugins folder, and use `remove_chars` as a filter.\n\nFor example: in search.json, replace\n\n```json\n\"content\": \"{{ page.content | strip_html | strip_newlines }}\"\n```\n\nwith\n\n```json\n\"content\": \"{{ page.content | strip_html | strip_newlines | remove_chars | escape }}\"\n```\n\nIf this doesn't work when using Github pages you can try `jsonify` to make sure the content is json compatible:\n\n```js\n\"content\": {{ page.content | jsonify }}\n```\n\n**Note: you don't need to use quotes `\"` in this since `jsonify` automatically inserts them.**\n\n\n## Enabling full-text search\n\nReplace `search.json` with the following code:\n\n```yaml\n---\nlayout: none\n---\n[\n {% for post in site.posts %}\n {\n \"title\" : \"{{ post.title | escape }}\",\n \"category\" : \"{{ post.category }}\",\n \"tags\" : \"{{ post.tags | join: ', ' }}\",\n \"url\" : \"{{ site.baseurl }}{{ post.url }}\",\n \"date\" : \"{{ post.date }}\",\n \"content\" : \"{{ post.content | strip_html | strip_newlines }}\"\n } {% unless forloop.last %},{% endunless %}\n {% endfor %}\n ,\n {% for page in site.pages %}\n {\n {% if page.title != nil %}\n \"title\" : \"{{ page.title | escape }}\",\n \"category\" : \"{{ page.category }}\",\n \"tags\" : \"{{ page.tags | join: ', ' }}\",\n \"url\" : \"{{ site.baseurl }}{{ page.url }}\",\n \"date\" : \"{{ page.date }}\",\n \"content\" : \"{{ page.content | strip_html | strip_newlines }}\"\n {% endif %}\n } {% unless forloop.last %},{% endunless %}\n {% endfor %}\n]\n```\n\n\n\n## Development\n\n- `npm install`\n- `npm test`\n\n#### Acceptance tests\n\n```bash\ncd example; jekyll serve\n\n# in another tab\n\nnpm run cypress -- run\n```\n\n## Contributors\n\nThanks to all [contributors](https://github.com/christian-fei/Simple-Jekyll-Search/graphs/contributors) over the years! You are the best :)\n\n> [@daviddarnes](https://github.com/daviddarnes)\n[@XhmikosR](https://github.com/XhmikosR)\n[@PeterDaveHello](https://github.com/PeterDaveHello)\n[@mikeybeck](https://github.com/mikeybeck)\n[@egladman](https://github.com/egladman)\n[@midzer](https://github.com/midzer)\n[@eduardoboucas](https://github.com/eduardoboucas)\n[@kremalicious](https://github.com/kremalicious)\n[@tibotiber](https://github.com/tibotiber)\nand many others!\n\n## Stargazers over time\n\n[](https://starchart.cc/christian-fei/Simple-Jekyll-Search)\n"
Note: you don’t need to use quotes "
in this since jsonify
automatically inserts them.
Replace search.json
with the following code:
---
layout: none
---
[
{
"title" : "Boat and Drone Testing",
"category" : "",
"tags" : "",
"url" : "/2021/04/19/outdoor-testing/",
"date" : "2021-04-19 00:00:00 +0000",
"content" : "After an entire year of mostly remote work, UM::Autonomy organized our first in-person event to test out the boat and drone we built. As this year’s competition is virtual, the testing event was a great opportunity for us to celebrate the effort and time we have put in as a team the past year.While we had some successes (the boat floated!), we found areas for improvement. We needed to work more on drone calibration before take-off and had some challenges with connecting the boat to our autonomous software component.Nevertheless, it was extremely satisfying to see the results of our hard work and for the team to be able to have a socially-distanced gathering before the end of the academic year.Drone TestingDate: 17th April 2021Location: M-AirBoat TestingDate: 18th April 2021Location: Music PondQuestions, comments, or concerns? Email us at umautonomy@umich.edu."
} ,
{
"title" : "Boat Build Process",
"category" : "",
"tags" : "",
"url" : "/2021/04/18/boat-build-process/",
"date" : "2021-04-18 00:00:00 +0000",
"content" : "It all started with a 3D design of the hulls by the Hulls and Systems team. This year, our team decided to use a trimaran (3 hulls) hull design to improve boat stability.We then prepared the hulls by using a carbon fiber vacuum resin infusion process. Each demi-hull was fabricated using a machine-milled high-density foam mold produced for the team by the Ford Motor Company.Once ready, we carefully broke open the molds containing the hulls.Next, we trimmed the hulls. As there was a lot of carbon fiber dust involved in the trimming process, we wore respirators and worked at a special area of the Wilson Center, periodically using a vacuum to remove the dust.To build the boat frame, we first measured and cut carbon fiber tubes (real-life application of trigonometry). We then used resin to stick the tubes together, using Zip Ties and G‑Clamps to hold them together, and left it for a few days for the resin to harden.We then worked on cutting out our plywood boat deck.And on attaching the boat hulls to the frame using more resin.… Then it all fell apart. Resin wasn’t strong enough to hold the boat structure together so we had to think of another method.Our solution? We drilled holes through the carbon fiber tubes and bolted them to other tubes, to the hulls and to the deck.The results? A sturdy boat. :)Finally, we attached our electrical box and thrusters to our boat.After cleaning our workspace, we were good to go test our boat!Questions, comments, or concerns? Email us at umautonomy@umich.edu."
} ,
{
"title" : "Minecraft Social Nights",
"category" : "",
"tags" : "",
"url" : "/2021/04/03/minecraft/",
"date" : "2021-04-03 00:00:00 +0000",
"content" : "After an entire year of Skribbl.io, online Uno, Among Us and Jackbox Games, we were running low on ideas for virtual social activities. Then, one of our team members suggested having Minecraft game nights.Not everyone on the team has Minecraft accounts. With the generous support from the University of Michigan’s Central Student Government (CSG), we purchased Minecraft accounts that our team members could borrow to participate in the game nights and a month’s worth of Minecraft Realms subscription.Some landmarks in UMA’s Minecraft Realm you won’t want to miss:Questions, comments, or concerns? Email us at umautonomy@umich.edu."
} ,
{
"title" : "TED Talks",
"category" : "",
"tags" : "",
"url" : "/2021/03/31/ted-talks/",
"date" : "2021-03-31 00:00:00 +0000",
"content" : "In our effort to improve remote engagement, we introduced the idea of biweekly informal TED talks, alternated with Game Nights. The idea was simple: anyone on the team could give a small presentation on any topic of their choice at 8pm EST Saturday night. This was also an effort to recreate impromptu whiteboard-type explanations we typically have during non-covid times in-person gatherings.Some of the TED talks that we had:1/23/21: wTF2 by Ryan DravesROS::TF2, a ROS library that manages and transforms between coordinate frames2/6/21: Git Good by Eric MaGitting good at using Git version control2/20/21: A Guide to React for Monke by Rimaz KhanReactJS, a frontend JavaScript framework for web development3/6/21: Boats In Motion by Cyrus AndersonHow do boats move?3/28/21: Docking at Docker by Ryan DravesA peek under the hood of the team’s AI environmentQuestions, comments, or concerns? Email us at umautonomy@umich.edu."
} ,
{
"title" : "Burger Night",
"category" : "",
"tags" : "",
"url" : "/2020/11/25/burger-night/",
"date" : "2020-11-25 00:00:00 +0000",
"content" : "In a typical non-covid semester, our team has burger nights where members would hang out together after team meetings/build sessions. With it being remote, we continued our tradition of having burger nights on Wednesdays 8-9pm. The Central Student Government (CSG) generously granted us the opportunity to refund members for one of our burger nights.Questions, comments, or concerns? Email us at umautonomy@umich.edu."
}
,
{
"title" : "The Phoenix: 2023 Boat",
"category" : "",
"tags" : "",
"url" : "/history/2023/",
"date" : "",
"content" : " 2023: The Phoenix Competition strategy and team progress Learn more ▼ The Phoenix Detailed Technical Report ↓ Rising from the ashes of defeat and disorder following the pandemic, the phoenix soars to competition this year with renewed pride, a greater sense of togetherness, and a singular focus: to compete hard while having fun. After a hard-fought competition the previous year, the team chose to focus on four principles for this year: decoupling, reliability, maintainability, and performance. Not only was the AI pipeline decoupled and tested separately, but nearly all major components of the boat could be separated, making it extremely modular and maintainable. It was the first year that the team tested in the Marine Hydrodynamics Laboratory, and did so for over 100 hours. In addition, it was the first year that the boat was made out of carbon fiber from scratch - from the painstaking mold making, preparation, and vacuum resin infusion - in order to produce a boat that weighed less than 60 pounds while still delivering impeccable results. Mechanical Details The Phoenix weighs 55 pounds, has a length of 56”, a beam (width) of 30”, and has an overall height of 26”. It can generate thrusts of more than 25 pounds. A hull and superstructure made of carbon fiber allows for weight reduction which has the benefits of an increased thrust to weight ratio and ease of transportability. Electrical Details An AMD Ryzen 5 5600X on a ASUS ROG Strix X570-I motherboard with 32 GB RAM provides the main logic of the boat. A Ubiquiti Rocket point-to-point transceiver allows for a reliable, fast data connection to land control. An Arduino Mega is used for computer control of the two Blue Robotics T500 thrusters. A Velodyne Puck LiDAR paired with a Logitech webcam is used for the boat's sensing. Software Details A Docker-based software environment configured with ROS 1 Noetic ensures that the exact same software is present when testing on a computer and on the boat—allowing team members to use their choice of Linux, Windows, or macOS on their personal computers without differences. The team uses Git as our version control system. Most of the team's code is written in C++, with several Python scripts for small tasks. Computer Vision is done with the YOLOv4 object detection system, and an upgrade to YOLOv8 is planned for the 2023-2024 year. The team plans to migrate to ROS 2 as well this year. "
} ,
{
"title" : "The Team",
"category" : "",
"tags" : "",
"url" : "/team/2024/",
"date" : "",
"content" : " The Team Get to know our talented members from 2022-23! Leadership Asheya Ashok Naik President linkedIn Graduating Winter 2024 Ben Bruick Vice President LinkedIn Graduating Winter 2026 Aayush Shah Electrical Lead Graduating Winter 2025 Gordon Fream Chief Naval Architect LinkedIn Graduating Winter 2025 Ben Schattinger AI Lead linkedIn Graduating Winter 2026 Murphy Justian Task Planning Co-Lead linkedIn Graduating Winter 2024 Christopher Briggs Navigation & Controls Co-Lead linkedIn Graduating Fall 2024 Georgia Zender Navigation & Controls Co-Lead Email Graduating Winter 2023 Elaina Mann Treasurer Graduating Winter 2026 Isabella Minkin Business Lead linkedIn Graduating Winter 2023 Kyle Gross Task Planning Co-Lead Graduating Winter 2025 Hevwar Shahab Computer Vision Lead linkedIn Graduating Winter 2024 Artificial Intelligence Ben Schattinger AI Lead linkedIn Graduating Winter 2026 Murphy Justian Task Planning Co-Lead linkedIn Graduating Winter 2024 Christopher Briggs Navigation & Controls Co-Lead linkedIn Graduating Fall 2024 Georgia Zender Navigation & Controls Co-Lead Email Graduating Winter 2023 Arya Patil Navigation & Controls Member linkedIn Graduating Winter 2024 Kyle Gross Task Planning Co-Lead Graduating Winter 2025 Hevwar Shahab Computer Vision Lead linkedIn Graduating Winter 2024 Advanced Capabilities Business Elaina Mann Treasurer Graduating Winter 2026 Isabella Minkin Business Lead linkedIn Graduating Winter 2023 Electrical Aayush Shah Electrical Lead Graduating Winter 2025 Mechanical Gordon Fream Chief Naval Architect LinkedIn Graduating Winter 2025 "
} ,
{
"title" : "Contact",
"category" : "",
"tags" : "",
"url" : "/contact/",
"date" : "",
"content" : " Contact Us We would love to hear from you! Learn more ▼ Contact Information General Contact: umautonomy@umich.edu Our team is divided into five main sub-teams each focusing on different aspects of the vehicle. Currently, we have both in-person and remote opportunities for members. Feel free to send us an email or contact any officer for more information. Looking to Join UM::Autonomy? Join Our Mailing List to Learn More Join our mailing list and we'll let you know when our next meeting is! We'll also offer one-on-one meetings with teams you're interested in. Team Officers for 2023-24 Administration President: Asheya Naik | user = 'asheya'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Vice-President: Ben Bruick | user = 'bruick'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Artificial Intelligence Team Lead Ben Schattinger | user = 'bencs'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Business Team Leads Head of Marketing and Design: Isabella Minkin | user = 'iminkin'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Treasurer: Elaina Mann | user = 'elainamn'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Electrical Team Lead Aayush Shah | user = 'shahaay'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Chief Naval Architect Gordon Fream | user = 'gfream'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Social Media Facebook Twitter LinkedIn Instagram "
} ,
{
"title" : "FAQ",
"category" : "",
"tags" : "",
"url" : "/faq/",
"date" : "",
"content" : " FAQ Frequently Asked Questions Learn more ▼ FAQs Do I need any experience or technical background to join? Nope! We welcome everyone to build and learn together—no matter if you are a freshman or a graduate student; majoring in economics or engineering. Come check us out! What is the time commitment? We are flexible: commit as much as you are willing and able to. Generally, members commit around 2-4 hours a week but we definitely understand that throughout the semester, priorities and workload could change. When does the team recruit? How do I become a member? We recruit all year round! Just join our mailing list to get periodic updates on team activity or send us an email to get added to our Slack channel if you're interested in contributing to the team as a member. Feel free to send us an email if you want to learn more about the projects we do or have any questions. Is the team active during the summer? Yes we are! We are less active than during the Fall/Winter semesters but we typically do have some projects for members to work on throughout the summer. Can I earn credit through UM::Autonomy? Yes! Starting your second semester of involvement in our project team, the work you do can be counted towards MDP Academic Credit. Read more about MDP here: https://mdp.engin.umich.edu Are there any fees to join? Nope. Nada. $0. Our team obtains materials and equipment from the generous support of the college, industry sponsors, alumni and friends. View the list of our sponsors here: https://umautonomy.com/sponsors How do I support the team? Send us an email at umautonomy@umich.edu! Some ways you can support the team include providing funding, mentorship, materials or equipment. We greatly appreciate any support our team gets. Did we miss a question you had? Send us an email at umautonomy@umich.edu! "
} ,
{
"title" : "Team History",
"category" : "",
"tags" : "",
"url" : "/history/",
"date" : "",
"content" : " Our History See UMA's past achievements and accomplishments! Learn more ▼ 2023: The Phoenix Rising from the ashes of defeat and disorder following the pandemic, the phoenix soars to competition this year with renewed pride, a greater sense of togetherness, and a singular focus: to compete hard while having fun. After a hard-fought competition the previous year, the team chose to focus on four principles for this year: decoupling, reliability, maintainability, and performance. Not only was the AI pipeline decoupled and tested separately, but nearly all major components of the boat could be separated, making it extremely modular and maintainable. It was the first year that the team tested in the Marine Hydrodynamics Laboratory, and did so for over 100 hours. In addition, it was the first year that the boat was made out of carbon fiber from scratch - from the painstaking mold making, preparation, and vacuum resin infusion - in order to produce a boat that weighed less than 60 pounds while still delivering impeccable results. Learn More Technical Design Report Video 2022: Flying Sloth 2 The team’s monumental return to the RoboBoat Competition following the COVID-19 pandemic was met with triumphs as well as hardships. The team decided to refurbish the Flying Sloth from the 2017 competition in order to focus on testing and learning skills that were lost due to the lack of in-person opportunities. With the Flying Sloth providing a strong foundation for the accommodation of new software and hardware development thanks to the new water blast and skeeball challenges, a new superstructure made of carbon fiber was fitted onto the boat. The goal was to use the strong foundation to design a fast system that provided lots of room for mounting electronics and hardware while being easily accessible. Technical Design Report 2021: C-3PO Joined by our drone, R2-D2 C-3PO is named in reference to the trimaran (three hulls) design of our boat. In previous years, our boat has typically used a monohull design but this year, the trimaran design is used to improve boat stability. With the continuation of the current roboboat competition virtual format and the uncertainty of the global pandemic, the team wanted to revise the previous iteration of the boat/drone which was unfortunately never completed due to Covid-19. This meant keeping and making small improvements to areas of strength such as the sensor suite, electrical box system, carbon fiber fiber infusion process, and much of our software while also experimenting with more innovative approaches such as the new hull form, hydrophone system, and addition of a CV/Lidar Deep learning approach. These changes allowed the team to better tackle the RoboBoat competitions challenges and ultimately push the organization to greater heights. Technical Design Report 2020: Pass Joined by our drone, “No Record COVID” Due to the COVID-19 pandemic, we experienced a shutdown and saw a shift in the 2020 RoboBoat competition format to a virtual one. Although our development cycle and competition period was disappointedly cut short, we believe we have made many important improvements to our design. With new hardware, a reworked sensor suite, and a modified hull form, we looked to bring our autonomous boat design to the next level of professional design. We believe these changes have greatly improved our ability to tackle the challenges of the RoboBoat competition and have enabled future improvements and successes. Technical Design Report Video 2019: Daedelus First Carbon Fiber boat, joined by our first custom drone, Icarus We came out of 2018 with the right balance of optimism and frustration with the result of competition. We wanted to make a change and Daedalus is the culmination of every sub team going above and beyond anything we have ever attempted on this team. Daedalus is the first Carbon Fiber boat in the team’s history, it’s the first time we have used a custom implementation of Robot Operation System (ROS), and the first time overhauling almost every piece of hardware we have both on, and inside the boat. Joined by the team’s first entirely custom drone, Icarus, our entry into RoboBoat 2019 is perhaps our most daring attempt yet. Detroit as whole, and our biggest supporters in Michigan are making a comeback, we’ve stepped up to do our part too. Technical Design Report Video 2018: John Sea Na 3rd among American Universities 2018 gave our team a glimpse of our potential for the future. As a predominantly Sophomore and Junior team we recognized the need to target specific areas in order to return the team to success. We focused on team organization, system engineering and collaboration across groups. By making targeted improvements as a team, we were able to make significant progress at competition. After previously not making it into finals the year prior, we were headed into finals in 4th and finished 3rd among American Universities. We see this year as an incredible opportunity to build on the experience of a majority upperclassmen team and strive to win the 2019 RoboBoat competition. Technical Design Report Video 2017: Flying Sloth First trimaran and first entirely SLAM dependent system The 2017 competition was a year of firsts for UM::Autonomy: first trimaran, first entirely SLAM dependent system and first total overhaul of our code base. Our team, almost entirely composed of underclassmen, was awarded 2nd place in the static competition. We achieved this result despite constant hardware breakdowns, which prevented the AI team from doing adequate testing before the preliminary competition. As a result, we could not effectively tune our boat’s thrusters for the strong competition winds and were forced to manually tune during competition runs. Moving forward we look to simplify the electrical box in order to make processing signal data more efficient, and avoid time-intensive repairs. Technical Design Report Video 2016: Thurman Change from catamaran to monohull design Thurman took home 6th place in the 9th annual AUVSI RoboBoat competition. In a departure from previous designs, Thurman has a monohull instead of a catamaran design. This change provided a large internal volume, which was able to house all of the electronics. The thrusters were mounted to outriggers which were added for increased stability with the change in hull design. One addition to the docking challenge this year was attaching a velcro strip to the dock, the ramming mechanism on the front of the hull was designed to deposit this velcro strip. This year the hull was done especially early which allowed for greater testing time before mock competition. Technical Design Report Video 2015: Sharkbyte Waterproofing and water cooling system After a strong qualifying run, SharkByte qualified for the finals of the 8th annual RoboBoat competition in first place. "SharkByte took home 3rd place in the finals. A major design change between SharkByte and previous boats was waterproofing. By using fully waterproof electrical connectors and a water cooling system, SharkByte was more than just splash-proof. The electrical system was new this year to accommodate this. After moving Hugh Jackman’s (Sharkbyte's predecessor) deck higher off the water with its taller hulls, it was decided that the waterproofing of the electrical systems would allow the deck to sit much lower to the water. This lowered center of gravity provided increased stability. The main goals of UM::Autonomy this year were the waterproofing and improved hull design. Technical Design Report 2014: Hugh Jackman Taller hulls for protection from water splash Hugh Jackman, named after the equally impressive actor, acquired 8th place in the 2014 RoboBoat competition. Even though Hugh Jackman’s performance did not reach our high standards, this boat had several improvements. Hugh has completely new, taller hulls which allows our electronics to be more protected from water splash. Additionally, with a brand new electric box, Hugh is more organized and more efficient than ever. With all of these revisions, Hugh has successfully paved the way for future iterations to perform exceedingly well. UM::Autonomy’s 2014 goal was to practice multiple, full-scale tests including our own mock competition and general testing in the Lurie Fountain. Technical Design Report Video 2013: Eve Accompanied by WALL-E, a small land vehicle Eve took 4th place in the 6th annual RoboBoat competition. The main differences between Eve and her predecessors include a major camera upgrade, as well as a new hull shape and propulsion configuration that allowed for much greater maneuverability, though she used the same electrical system as her predecessor Serenity. Eve was also accompanied by a small land vehicle named WALL-E who was designed to handle the amphibious landing challenge. Eve also featured a NERF gun that was to be used for a shooting challenge. The main focus of UM::Autonomy during this year was quality manufacturing and thorough testing. Technical Design Report 2012: Serenity 1st place at the 5th annual RoboBoat competition Serenity consistently completed the entire buoy course with some major software upgrades and attempted the “Hot Sign” and “Poker Chip” challenges. At 106 Lbs Serenity weighed in as UM::Autonomy’s heaviest boat to date. Serenity’s most notable differences from her predecessor Wolvemarine include an entirely new electrical system and vision system. Serenity did however use the same hulls as her predecessor Wolvemarine. Serenity was equipped with an Infrared Camera as well as a Water Cannon. The main focus of the team this year was the completion of the buoy course. Technical Design Report 2011: Wolvemarine First boat to create 3D Point Clouds of its environment Wolvemarine was built to compete in the 4th annual RoboBoat competition. Distinctive for its innovative panning Panning Lidar, Wolvemarine was the first boat in competition history to create 3D Point Clouds of its environment. Wolvemarine also featured a new Hull shape that allowed for greater speed through the water. Although UM::Autonomy took 1st place in the static judging portion of the competition we experienced several technical issues, causing us to do very poorly during the rest of the competition. However, the team did receive the “Edge of the Envelope” award for the major technological advances that were developed. Technical Design Report 2010: Mjolnir First boat to feature custom made fiberglass hulls and Lidar Mjolnir was created to compete in the 3rd annual RoboBoat competition and succeeded in claiming 1st place in the Static Judging as well as competition as a whole. Named after the hammer of the Norse god Thor; Mjolnir was a major achievement for UM::Autonomy. Mjolnir was the first boat made by UM::Autonomy to feature custom made fiberglass hulls and the electrical system was created entirely from scratch. Mjolnir was the first boat in RoboBoat history to feature a laser range finder, AKA Lidar. "
} ,
{
"title" : "Blog",
"category" : "",
"tags" : "",
"url" : "/blog/",
"date" : "",
"content" : " The latest news Hear our latest activities, events and progress! ✎ Add Post Boat and Drone Testing April 19, 2021 Read More Boat Build Process April 18, 2021 Read More Minecraft Social Nights April 03, 2021 Read More TED Talks March 31, 2021 Read More Burger Night November 25, 2020 Read More "
} ,
{
"title" : "Home",
"category" : "",
"tags" : "",
"url" : "/",
"date" : "",
"content" : " Looking to Join UM::Autonomy? Join Our Mailing List to Learn More Join our mailing list and we'll let you know when our next meeting is! We'll also offer one-on-one meetings with teams you're interested in. UM::Autonomy is an award-winning student project team from the University of Michigan. Each year we build an autonomous boat to participate in the RoboNation RoboBoat competition. The boat is completely designed and programmed by students and must complete a wide range of challenges that are designed to test its autonomous abilities. We aim to further the study of autonomous robotics at the University of Michigan by providing students with hands-on multidisciplinary design experience in artificial intelligence, image processing, navigation, naval architecture, and mechanical design. Each year we strive to push the physical and conceptual bounds of our autonomous vehicle. The Competition The RoboBoat competition is an international competition where students design, build, and compete with self-driving robotic boats, in a series of tests aimed at challenging teams through a variety autonomous (self-driving) tasks. In 2023, we were joined by 22 other teams from 4 continents. UM::Autonomy placed 6th overall, and 3rd among American Universities. The Boat Rising from the ashes of defeat and disorder following the pandemic, UM::Autonomy's 2023 boat, the Phoenix, soared to competition with renewed pride, a greater sense of togetherness, and a singular focus: to compete hard while having fun. Made entirely out of carbon fiber to reduce weight, the boat features two large thrusters for speed and a Ryzen 5600X CPU to make autonomous decisions. After a hard-fought competition the previous year, the team chose to focus on four principles for this year: decoupling, reliability, maintainability, and performance. Not only was the AI pipeline decoupled and tested separately, but nearly all major components of the boat could be separated, making it extremely modular and maintainable. It was the first year that the team tested in the Marine Hydrodynamics Laboratory, and did so for over 100 hours. In addition, it was the first year that the boat was made out of carbon fiber from scratch—from the painstaking mold making, preparation, and vacuum resin infusion—in order to produce a boat that weighed less than 60 pounds while still delivering impeccable results. The Team UM::Autonomy has around 60 members across many different majors, including Computer Science, Electrical Engineering, Robotics, Naval Architecture, Art & Design, and Business. We are organized into several teams: Artificial Intelligence, Electrical, Mechanical, Advanced Capabilities, and Business. The Artificial Intelligence team is broken up into distinct subteams, which are Navigation & Controls, Task Planning, and Computer Vision. Interested in joining? Each year we look for motivated, talented individuals looking to make a splash in the world of autonomous vehicles. UMA has no selection process or time commitment requirements. This year, we have bite-sized projects for new members to onboard more smoothly and get a glimpse on the type of work we do. If our team and our opportunities float your boat, sign up for our mailing list, and we'll provide you with more information about our meetings! If you have any more questions, don't be afraid to reach out to us at umautonomy@umich.edu! Join Our Mailing List to Learn More Join our mailing list and we'll let you know when our next meeting is! We'll also offer one-on-one meetings with teams you're interested in. "
} ,
{
"title" : "Projects",
"category" : "",
"tags" : "",
"url" : "/projects/",
"date" : "",
"content" : " Projects See what our teams have been up to! Learn more ▼ Artificial Intelligence Building off of a Robot Operating System architecture, AI tasks range from integrating COTS peripherals, to object detection, navigation, top-level task reasoning, and simulating the boat’s performance in a virtual competition course. Tech stack: Docker-based environment, Git for version-control, ROS Noetic (with an upgrade planned) for the architecture, and C++ & Python for the majority of the source code. Upgrade to ROS 2 Currently, the team uses ROS 1 Noetic, the final version in the ROS 1 series. Because it will be End-of-Life in 2025, it's important to plan a migration to a newer, supported version. CV/LIDAR deep learning The goal for CV deep learning is to implement deep learning models to accurately assign various classifications to objects detected by our boat’s camera. Upon completion, this new detection method will be integrated into our boat’s architecture, along with the development of a streamlined process for creating and training new models. Members will gain hands-on experience with one or more steps of the deep learning process, including model selection, design, training, and validation, as well as data annotation and preprocessing. Additionally, members may optionally also seek to gain a more theoretical understanding of deep learning models (and by extension, machine learning as a whole). LIDAR quantification The Lidar quantification project’s goal is to explore metrics to evaluate our current LIDAR detection algorithm. These metrics give a more precise, fine-grained measure on the quality of the LIDAR detection than our current method of using a visualizer to holistically observe the results of the detection. Members will gain experience with researching and conceptualizing various evaluation metrics, then evaluating the “informativeness” of each metric using a small, annotated 3D point cloud dataset. Potential metrics include those typically used in the fields of machine learning or data science, as well as custom metrics that we may formulate ourselves. Task Planning The task planning team acts as the brains of our boat - it analyzes perception data in order to direct the movements of path-planning and controls. This will include creating an advanced movement library that interfaces with the path-planner/controller, enabling our boat to strafe, activate anchor mode, maneuver the boat relative to an obstacle, and circle around an obstacle. Expanding the boat’s current high-level logic capabilities, this new library interfaces with perception, path-planning, controls, and simulation. Task-planning members will achieve a broad understanding of all of the boat’s sub-teams. This team is great for someone who likes abstract, critical thinking without having to spend lots of team reading through ROS documentation, academic articles, or complicated math. Task Sim team The Task Sim team’s goal is to build a simulated version of the RoboBoat competition tasks with Gazebo in order to test our boat code without an actual boat or water. This will involve testing the boat code as a single unit in its ability to traverse course obstacles, as well as constructing metrics to quantify and compare the performance of specific sections of the boat. Since we have a working simulator and some foundational code for path verification from previous semesters, existing code will be used and improved upon. Members of this team will gain experience with each section of the codebase, from perception to motion-modelling, by interfacing with and testing them, as well as experiencing simulation/physics engines. Electrical The Electrical Team is responsible for the allocation of power to the boat and management of cables and wires from the battery to the computer, sensors, and motors. Electrical Box Reorganization Our main focus this year was to make the box more organized, neat, and reliable. To achieve these goals, we introduced numerous new parts and custom PCB’s. For example, this year we purchased a breakout board, which splits an ATX cable into its derivative voltage supplies. We also overhauled nearly every single electrical splice connection and adopted a more crimp-oriented approach as opposed to soldering everything. New Electrical Box Over the past couple of years, we have been utilizing custom-cut polycarbonate to construct the main “shell” of the electrical box. This year, we used a pelican box - a rigid, waterproof, and air-tight crate. In order to drill holes in the box for some inputs and outputs, we needed to expose members to different tools needed to penetrate the thick material. Although this process was time consuming, all of the sub-team members were able to contribute, learn a new skill, and the electrical box was completed almost two months ahead of where it was last year. We also built our electrical box based on a CAD model designed and completed last summer. Hulls & Systems H&S Team works on the design and construction of the team’s boat. This includes designing around the boat’s electrical system, accompanying drone, and sensor specifications required by the boat’s autonomous systems. Hull Design Decisions In recent years, the team has used a trimaran hull design which offers incredible stability. However, turning performance is limited due to the resistance offered by the hulls. The team will evaluate whether to keep or change the design in 2023. Vacuum Infusion In previous years, the team utilized pre-resin-impregnated, high-temperature curing carbon fiber cured in an autoclave to construct the hulls. This year, the hulls were constructed using a carbon fiber vacuum resin infusion process. Each demi-hull was fabricated using a machine-milled high-density foam mold produced for the team by the Ford Motor Company. Advanced Capabilities Team The Advanced Capabilities Team creates systems for competition elements that involve more than the base boat. Currently, we're tasked with creating a controllable water cannon and a mechanism that efficiently retrieves balls and places them into a storage bin. This involves using Computer-Aided Design (CAD) to physically build these systems, followed by designing the electrical circuits and sensors these components will use to function optimally. Finally, we'll create a communication platform to control these new features effectively. Duck Wash This challenge will consist of three major steps: target recognition, calculating the water trajectory, and actuation. For target recognition, we will use camera-based computer vision system to detect and pinpoint target locations accurately. When it comes to trajectory calculation, we will calculate based on the position and orientation of both our vessel and the target.The actuation step will involve using the data gathered from the previous steps to properly align our water cannon. Once the cannon has been aligned, the water will be launched.To maintain “station keeping”—keeping our vessel still during the water launch—we will use force estimates to apply an opposite force via thrusters. Collection and Delivery The boat will identify the collection zone, which is an octagon floating on the water’s surface. Once the area is detected, the ASV will then proceed to collect designated items—floating rubber ducks and red racquetballs. The detection will be mainly facilitated by our camera-based computer vision system.After successfully collecting the items, the ASV will navigate towards the Delivery Octagon. Here, the vehicle’s primary task is to safely deliver the collected items. Points are awarded for not only delivering the items inside the octagon but also if items are delivered to the correct ‘nests’.Throughout the process, the ASV needs to maintain efficient object handling and accurate navigational capabilities, which will be key to succeeding in this demanding challenge. The design and functionality of our vehicle will rely heavily on optimal strategies and technological advancements. Business The Business Team secures funding for the team, processes reimbursement requests, maintains sponsor relationships and is responsible for social media engagement. The subteam also creates and maintains the team website. Reimbursement Request Tracking We currently have a Google Form that requires separately uploading receipts for member reimbursement requests. While far better than the previous system involving manually notifying a team officer, we hope to introduce a streamlined system that allows receipt and description uploading quickly, which then immediately notifies the relevant person for purchase approval. Social Engagement We hope to expand our social events even further than the previous year. In 2022-2023, we brought team members to a board game night, go-karting and arcade, and many team dinners after even work sessions. We also started a Minecraft server for members to play over the summer. However, we aim to have more frequent events, such as movie nights every other week. UMA Website With an effort to boost recruitment in 2023, several pages of the website have been redesigned to be more informative and appealing. Redesigns of several more pages are planned, and more content will be produced to further recruitment efforts, increase appeal to sponsors, and score more points in the RoboBoat website judging. Members: Ben Schattinger "
} ,
{
"title" : "RoboBoat 2023",
"category" : "",
"tags" : "",
"url" : "/roboboat/",
"date" : "",
"content" : " RoboBoat 2023: Ocean Exploration Nathan Benderson Park Sarasota, Florida RoboBoat is an international competition where students design, build, and compete with self-driving robotic boats, in a series of tests aimed at challenging teams through a variety autonomous (self-driving) tasks. In 2023, we were joined by 22 other teams from 4 continents. UM::Autonomy placed 6th overall, and 3rd among American Universities. Jump to Competition Results ↓ Competition Strategy For this competition season, we tested with the 2022 hull (itself a refurbished 2017 hull) for most of the year, since it was already built. A new hull made of carbon fiber was being built concurrently by the mechanical team. At the last minute, days before departure for the competition, it was ready. The team spent the weekend preparing the new boat for the competition, and thanks to simulator testing, this process went smoothly and few code changes were needed. Static Judging Criteria Besides a team's performance autonomously, we are judged on aspects of both our team and the boat. Design Documentation The team must prepare a website, a technical design report, and a video for judges to score. These are evaluated based on how well they introduce the team and its structure as well as design considerations of the boat. Presentation The team must present to the judges live their decisions leading to the design of the boat. Other Judging Criteria Before the boat can participate in an autonomous challenge, several prerequisite activites must be completed. Static Safety Inspection As the boats are very high powered, a runaway boat could damage itself and hurt others. Therefore, competition staff ensure that the boat follows several safety rules: The boat stops when a physical red button is pressed on the boat The boat stops when a remote switch is flipped, or the remote switch loses power or connection The boat does not have any sharp edges so that people in the water can touch the boat safely UM::Autonomy is proud to have been one of the first three teams to pass the safety inspection at the 2023 competition. Boat Thrust-to-Weight Ratio The competition rewards fast and light craft. Therefore, a sliding scale is used where points are lost faster the heavier it gets. The boat is weighed and its thrust is measured every day it is entered in the water. In 2023, UM::Autonomy's boat weighed 55 pounds, the lightest weight class. High Priority Challenges Navigate the Panama Canal Description This challenge is mandatory before attempting other tasks. The ASV needs to pass through two sets of gates (a pair of red and green buoys) and starts autonomous navigation at a minimum of 6 ft before the set of gates. Analysis As it is mandatory, this challenge is of high importance. In 2019, the boat could only successfully pass the navigation channel once out of four qualification runs as a result of a major electrical failure onboard. Goal 14 out of 15 successful runs Post-competition Remarks As one of the simplest tasks, this was completed with high success. However, additional tuning was needed upon arrival to the competition site as the boat's computer vision system would occasionally fail to detect a buoy. Magellan's Route / Count the Manatees & Jellyfish Description The ASV passes through between multiple sets of gates (pairs of red and green buoys) The ASV also avoids intermittent yellow buoys (jelly fish) and black buoys (manatees) of various sizes and counts them. Analysis The challenge requires minimal external hardware or software development and mainly just involves careful navigational operability and fine motor control. This challenge could be tested and fine-tuned early in the development process. Goal 9 out of 10 successful runs Post-competition Remarks This challenge revealed some disadvantages of our indoors testing area. Specifically, our obstacle-avoidance system decided that the best way to avoid hitting buoys was to go outside of the red-green channel! While technically following our instructions, it didn't score many points. Although we didn't have time to fix that during the competition, the boat did go through several red-green pairs on some runs scoring us important points. Northern Passage Challenge Description The ASV enters the gate buoys, maneuvers around the mark buoy, and exits thought the same gate buoys, as quickly as possible. The timer starts when the bow (front) crosses the gate buoys and stops when the stern (back) crosses the gate buoys. The team colloquially refers to this as the "Speed Challenge". Analysis Based on the 2019 score-sheet, a time between 25-45s is needed to remain competitive in the Northern Passage challenge, with the fastest 2019 run coming in at 27 seconds. Goal 9 out of 10 successful runs. We hope for a baseline of 35 seconds, and a goal of 26 seconds. Post-competition Remarks Another disadvantage of indoors testing was highlighted here: buoy interference. Specifically, our computer vision system had a hard time distinguising the blue buoy (marking where to turn around) from the black buoys (marking an obstacle to avoid in the previous challenge, Magellan's Route). When we tested indoors, we only tested one or two challenges at a time, and with different lighting. Medium Priority Challenges Beaching & Inspecting Turtle Nests Description Before the time slot starts, teams are assigned a color and must dock at the bay with the matching color. Once the ASV detects and enters the docking bay, it must report the number of "eggs" (number of circles) in the nest. The team colloquially refers to this challenge as "Docking." Analysis This challenge is a bit more involved in terms of computer and color/shape recognition but does not require external hardware development. Goal 9 out of 10 successful runs Post-competition Remarks This task turned out easier than expected. Matching on color rather than number of dots on the board turned out rather easy. Scoring involved simply hitting the docks. Feed the Fish Description The ASV detects the "feeding table" (purple frame), then lines up and shoot three "pellets" (racquetballs) through the frame into any of the three holes. Points are awarded if the ball is fired into any of the holes but fewer points are awarded for just landing the ball on the deck. The team colloquially refers to this challenge as "Skeeball," the classic arcade game. Analysis As both the Ponce de Leon (see next) and Feeding the Fish are new challenges, UM::Autonomy chose to only focus on completing the Ponce de Leon challenge this year, though work was done throughout the year to complete the Skeeball task in the future. Goal N/A Post-competition Remarks See next task Ponce de Leon / Fountain of Youth Description The ASV detects the target face (blue/white striped) and shoots enough water through the target to raise the ball above the green line in the pipe. The ASV may pump the water from the environment or store it on board. The team colloquially refers to this challenge as "Water Blast." Analysis This is the first season with this challenge and hardware and software development of external mechanisms pushed back actual testing. Therefore, we knew that immediate mastery of this task would be difficult and time consuming, and should only be attempted after other challenges. Goal 3 out of 5 successful runs Post-competition Remarks Although we had planned to focus on shooting water rather than balls, it turned out that water leakage was a big worry: if the pump failed and dumped water in the boat's electronics, we wouldn't be able to compete anymore. As such, we re-focued our effort on Feed the Fish. We finally had a working ball-shooting system while at the competition site, but lack of testing time meant that it couldn't be integrated in time. Both tasks only had three teams that could shoot anything. No teams landed balls in the buckets. Low Priority Challenges Ocean Cleanup Description The ASV detects an underwater pinger which designates the area to collect "debris" (raquetballs) from. The ASV may then use the collected balls as extra balls in the Feed the Fish challenge. Analysis As this task is a new challenge, UM::Autonomy chose to focus on completing the Ponce de Leon challenge and Feeding the Fish challenge for this year, though work was done throughout the year to complete the Ocean Cleanup task in the future. Goal N/A Post-competition Remarks This was one of the hardest challenges this year. Only a couple teams even had the hardware to participate, and none scored points. We will need to evaluate again whether this task is worth pursuing next year. UM::Autonomy extends a special thanks to Cole Biesemeyer from the Open Source Robotics Foundation for the 3D model of Nathan Benderson Park and Gdańsk University of Technology's SimLE: SeaSentinel team for creating 3D models of various competition elements. Competition Results UM::Autonomy placed 6th overall, and 3rd among American Universities. Static Judging UM::Autonomy placed 1st in the technical report, 2nd in the video, and 1st in the presentation for an overall 3rd place in design documentation. Autonomous Challenge UM::Autonomy placed 9th. 13 teams scored no points in the autonomous challenge. The Team The team feels very confident for the 2024 season. Many new members attended competition for the first time, creating an exciting environment where many members are familiar with competition practices allowing us to achieve further success in future years. "
} ,
{
} ,
{
} ,
{
} ,
{
} ,
{
"title" : "Sponsors",
"category" : "",
"tags" : "",
"url" : "/sponsors/",
"date" : "",
"content" : " Sponsors Thank you to our wonderful sponsors for your contributions! Learn more ▼ Platinum Gold Lastly, thank you to our alumni and friends for your donations during Giving Blue Day! If you are interested in sponsoring UM::Autonomy, please email our 2023-24 business leads for more information: President: Asheya Naik | user = 'asheya'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); Treasurer: Elaina Mann | user = 'elainamn'; site = 'umich.edu'; document.write(''); document.write(user + '@' + site + ''); "
} ,
{
"title" : "The Team",
"category" : "",
"tags" : "",
"url" : "/team/",
"date" : "",
"content" : " The Team Get to know our talented members from 2022-23! Leadership Saheth Edupuganti President linkedIn Graduating Winter 2023 Asheya Ashok Naik Systems Engineering Lead President in 2023-2024 linkedIn Graduating Winter 2024 Tom Gao Vice President and ACT Lead linkedIn Graduating Fall 2023 Ben Bruick Vice President in 2023-2024 LinkedIn Graduating Winter 2026 Raghav Varshney Electrical Co-Lead linkedIn Graduating Winter 2024 Aayush Shah Electrical Lead in 2023-2024 Graduating Winter 2025 Aayushi Nakum Electrical Co-Lead Email Graduating Winter 2023 Frances Truong Mechanical Co-Lead Email Graduating Winter 2024 Lucas Mitsch Mechanical Co-Lead linkedIn Graduating Winter 2024 Gordon Fream Chief Naval Architect in 2023-2024 LinkedIn Graduating Winter 2025 Chad Rakoczy AI Co-Lead / CV Lead linkedIn Graduating Winter 2023 Ben Schattinger AI Co-Lead AI Lead in 2023-2024 linkedIn Graduating Winter 2026 Murphy Justian Task Planning Co-Lead Task Planning Co-Lead in 2023-2024 linkedIn Graduating Winter 2024 Zain Eazad Task Planning Co-Lead linkedIn Graduating Winter 2023 Christopher Briggs Navigation & Controls Co-Lead in 2023-2024 linkedIn Graduating Fall 2024 Georgia Zender Navigation Co-Lead Navigation & Controls Co-Lead in 2023-2024 Email Graduating Winter 2023 Arya Patil Navigation Co-Lead linkedIn Graduating Winter 2024 Elaina Mann Treasurer in 2023-2024 Graduating Winter 2026 Isabella Minkin Business Lead in 2023-2024 linkedIn Graduating Winter 2023 Vanessa Lulla Controls Lead Email Graduating Winter 2025 Dimitrios Dikos Business Lead linkedIn Graduating Winter 2023 Kyle Gross Task Planning Co-Lead in 2023-2024 Graduating Winter 2025 Hevwar Shahab Computer Vision Lead in 2023-2024 linkedIn Graduating Winter 2024 Artificial Intelligence Chad Rakoczy AI Co-Lead / CV Lead linkedIn Graduating Winter 2023 Ben Schattinger Controls & AI Co-Lead linkedIn Graduating Winter 2026 Murphy Justian Task Planning Co-Lead linkedIn Graduating Winter 2024 Christopher Briggs Navigation Member linkedIn Graduating Fall 2024 Georgia Zender Navigation Co-Lead Email Graduating Winter 2023 Arya Patil Navigation Co-Lead linkedIn Graduating Winter 2024 Vanessa Lulla Controls Lead Email Graduating Winter 2025 Kyle Gross Task Planning Member Graduating Winter 2025 Zain Eazad Task Planning Co-Lead linkedIn Graduating Winter 2024 Hevwar Shahab CV Member linkedIn Graduating Winter 2024 Amirali Danai CV Member linkedIn Graduating Fall 2026 Sonika Potnis Task Planning Member Email Graduating Fall 2025 Sushrita Rakshit Task Planning Member linkedIn Graduating Winter 2025 Lada Protcheva Task Planning Member linkedIn Graduating Winter 2024 Nathan Buckwalter Task Planning Member Email Graduating Winter 2023 Frank Sun Navigation Member Email Graduating Winter 2024 Advanced Capabilities Tom Gao Advanced Capabilities Software Lead linkedIn Graduating Fall 2023 Ben Bruick Advanced Capabilities Hardware Lead LinkedIn Graduating Winter 2026 Broderick Riopelle Member linkedIn Graduating Winter 2024 Ryan Chua Member linkedIn Graduating Winter 2024 Joshua Beatty Member linkedIn Graduating Winter 2023 Business Zain Eazad Web Dev Team Lead linkedIn Graduating Winter 2023 Elaina Mann Member Graduating Winter 2026 Isabella Minkin Member linkedIn Graduating Winter 2023 Dimitrios Dikos Business Lead linkedIn Graduating Winter 2023 Chelsea Sun Member linkedIn Graduating Winter 2025 Electrical Raghav Varshney Electrical Co-Lead linkedIn Graduating Winter 2024 Aayush Shah Member Graduating Winter 2025 Aayushi Nakum Electrical Co-Lead Email Graduating Winter 2023 Zamir North Member Email Graduating Winter 2025 Mechanical Frances Truong Mechanical Co-Lead Email Graduating Winter 2024 Lucas Mitsch Mechanical Co-Lead linkedIn Graduating Winter 2024 Gordon Fream Member LinkedIn Graduating Winter 2025 Chelsea Sun Member linkedIn Graduating Winter 2025 Anthony Tan Member Graduating Winter 2025 Cameron Muzall Member Email Graduating Winter 2024 Jackson Brown Member linkedIn Graduating Winter 2023 Kye Dembinski Member Email Graduating Winter 2023 Systems Engineering Asheya Ashok Naik Systems Engineering lead linkedIn Graduating Winter 2024 Axel Avram Member linkedIn Graduating Winter 2024 "
} ,
{
} ,
{
"title" : "v1.0.3 Short Fuse",
"category" : "",
"tags" : "",
"url" : "/node_modules/fuzzysearch/CHANGELOG/",
"date" : "",
"content" : "v1.0.3 Short Fuse Improved circuit-breaker when needle and haystack length are equalv1.0.2 Vodka Tonic Slightly updated circuit-breaker that tests for equal length first Doubled method performance (see jsperf tests)v1.0.1 Circuit Breaker Introduced a circuit-breaker where queries longer than the searched string will return false Introduced a circuit-breaker where queries identical to the searched string will return true Introduced a circuit-breaker where text containing the entire query will return truev1.0.0 IPO Initial Public Release"
} ,
{
"title" : "fuzzysearch",
"category" : "",
"tags" : "",
"url" : "/node_modules/fuzzysearch/",
"date" : "",
"content" : "fuzzysearch Tiny and blazing-fast fuzzy search in JavaScriptFuzzy searching allows for flexibly matching a string with partial input, useful for filtering data very quickly based on lightweight user input.DemoTo see fuzzysearch in action, head over to bevacqua.github.io/horsey, which is a demo of an autocomplete component that uses fuzzysearch to filter out results based on user input.InstallFrom npmnpm install --save fuzzysearchfuzzysearch(needle, haystack)Returns true if needle matches haystack using a fuzzy-searching algorithm. Note that this program doesn’t implement levenshtein distance, but rather a simplified version where there’s no approximation. The method will return true only if each character in the needle can be found in the haystack and occurs after the preceding character.fuzzysearch('twl', 'cartwheel') // <- truefuzzysearch('cart', 'cartwheel') // <- truefuzzysearch('cw', 'cartwheel') // <- truefuzzysearch('ee', 'cartwheel') // <- truefuzzysearch('art', 'cartwheel') // <- truefuzzysearch('eeel', 'cartwheel') // <- falsefuzzysearch('dog', 'cartwheel') // <- falseAn exciting application for this kind of algorithm is to filter options from an autocomplete menu, check out horsey for an example on how that might look like.But! RegExps…!LicenseMIT"
} ,
{
"title" : "Simple-Jekyll-Search",
"category" : "",
"tags" : "",
"url" : "/node_modules/simple-jekyll-search/",
"date" : "",
"content" : "# [Simple-Jekyll-Search](https://www.npmjs.com/package/simple-jekyll-search)[](https://travis-ci.org/christian-fei/Simple-Jekyll-Search)[](https://david-dm.org/christian-fei/Simple-Jekyll-Search)[](https://david-dm.org/christian-fei/Simple-Jekyll-Search?type=dev)A JavaScript library to add search functionality to any Jekyll blog.## Use caseYou have a blog, built with Jekyll, and want a **lightweight search functionality** on your blog, purely client-side?*No server configurations or databases to maintain*.Just **5 minutes** to have a **fully working searchable blog**.---## Installation### npm```shnpm install simple-jekyll-search```## Getting started### Create `search.json`Place the following code in a file called `search.json` in the **root** of your Jekyll blog. (You can also get a copy [from here](/example/search.json))This file will be used as a small data source to perform the searches on the client side:```yaml---layout: none---[ {% for post in site.posts %} { "title" : "{{ post.title | escape }}", "category" : "{{ post.category }}", "tags" : "{{ post.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ post.url }}", "date" : "{{ post.date }}" } {% unless forloop.last %},{% endunless %} {% endfor %}]```## Preparing the plugin### Add DOM elementsSimpleJekyllSearch needs two `DOM` elements to work:- a search input field- a result container to display the results#### Give me the codeHere is the code you can use with the default configuration:You need to place the following code within the layout where you want the search to appear. (See the configuration section below to customize it)For example in **_layouts/default.html**:```html```## UsageCustomize SimpleJekyllSearch by passing in your configuration options:```jsvar sjs = SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), json: '/search.json'})```### returns { search }A new instance of SimpleJekyllSearch returns an object, with the only property `search`.`search` is a function used to simulate a user input and display the matching results. E.g.:```jsvar sjs = SimpleJekyllSearch({ ...options })sjs.search('Hello')```💡 it can be used to filter posts by tags or categories!## OptionsHere is a list of the available options, usage questions, troubleshooting & guides.### searchInput (Element) [required]The input element on which the plugin should listen for keyboard event and trigger the searching and rendering for articles.### resultsContainer (Element) [required]The container element in which the search results should be rendered in. Typically a ``.### json (String|JSON) [required]You can either pass in an URL to the `search.json` file, or the results in form of JSON directly, to save one round trip to get the data.### searchResultTemplate (String) [optional]The template of a single rendered search result.The templating syntax is very simple: You just enclose the properties you want to replace with curly braces.E.g.The template```jsvar sjs = SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), json: '/search.json', searchResultTemplate: '{title}'})```will render to the following```htmlWelcome to Jekyll!```If the `search.json` contains this data```json[ { "title" : "Welcome to Jekyll!", "category" : "", "tags" : "", "url" : "/jekyll/update/2014/11/01/welcome-to-jekyll.html", "date" : "2014-11-01 21:07:22 +0100" }]```### templateMiddleware (Function) [optional]A function that will be called whenever a match in the template is found.It gets passed the current property name, property value, and the template.If the function returns a non-undefined value, it gets replaced in the template.This can be potentially useful for manipulating URLs etc.Example:```jsSimpleJekyllSearch({ ... templateMiddleware: function(prop, value, template) { if (prop === 'bar') { return value.replace(/^\//, '') } } ...})```See the [tests](https://github.com/christian-fei/Simple-Jekyll-Search/blob/master/tests/Templater.test.js) for an in-depth code example### sortMiddleware (Function) [optional]A function that will be used to sort the filtered results.It can be used for example to group the sections together.Example:```jsSimpleJekyllSearch({ ... sortMiddleware: function(a, b) { var astr = String(a.section) + "-" + String(a.caption); var bstr = String(b.section) + "-" + String(b.caption); return astr.localeCompare(bstr) } ...})```### noResultsText (String) [optional]The HTML that will be shown if the query didn't match anything.### limit (Number) [optional]You can limit the number of posts rendered on the page.### fuzzy (Boolean) [optional]Enable fuzzy search to allow less restrictive matching.### exclude (Array) [optional]Pass in a list of terms you want to exclude (terms will be matched against a regex, so URLs, words are allowed).### success (Function) [optional]A function called once the data has been loaded.### debounceTime (Number) [optional]Limit how many times the search function can be executed over the given time window. This is especially useful to improve the user experience when searching over a large dataset (either with rare terms or because the number of posts to display is large). If no `debounceTime` (milliseconds) is provided a search will be triggered on each keystroke.---## If search isn't working due to invalid JSON- There is a filter plugin in the _plugins folder which should remove most characters that cause invalid JSON. To use it, add the simple_search_filter.rb file to your _plugins folder, and use `remove_chars` as a filter.For example: in search.json, replace```json"content": "{{ page.content | strip_html | strip_newlines }}"```with```json"content": "{{ page.content | strip_html | strip_newlines | remove_chars | escape }}"```If this doesn't work when using Github pages you can try `jsonify` to make sure the content is json compatible:```js"content": {{ page.content | jsonify }}```**Note: you don't need to use quotes `"` in this since `jsonify` automatically inserts them.**## Enabling full-text searchReplace `search.json` with the following code:```yaml---layout: none---[ {% for post in site.posts %} { "title" : "{{ post.title | escape }}", "category" : "{{ post.category }}", "tags" : "{{ post.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ post.url }}", "date" : "{{ post.date }}", "content" : "{{ post.content | strip_html | strip_newlines }}" } {% unless forloop.last %},{% endunless %} {% endfor %} , {% for page in site.pages %} { {% if page.title != nil %} "title" : "{{ page.title | escape }}", "category" : "{{ page.category }}", "tags" : "{{ page.tags | join: ', ' }}", "url" : "{{ site.baseurl }}{{ page.url }}", "date" : "{{ page.date }}", "content" : "{{ page.content | strip_html | strip_newlines }}" {% endif %} } {% unless forloop.last %},{% endunless %} {% endfor %}]```## Development- `npm install`- `npm test`#### Acceptance tests```bashcd example; jekyll serve# in another tabnpm run cypress -- run```## ContributorsThanks to all [contributors](https://github.com/christian-fei/Simple-Jekyll-Search/graphs/contributors) over the years! You are the best :)> [@daviddarnes](https://github.com/daviddarnes)[@XhmikosR](https://github.com/XhmikosR)[@PeterDaveHello](https://github.com/PeterDaveHello)[@mikeybeck](https://github.com/mikeybeck)[@egladman](https://github.com/egladman)[@midzer](https://github.com/midzer)[@eduardoboucas](https://github.com/eduardoboucas)[@kremalicious](https://github.com/kremalicious)[@tibotiber](https://github.com/tibotiber)and many others!## Stargazers over time[](https://starchart.cc/christian-fei/Simple-Jekyll-Search)"
} ,
{
} ,
{
}
]
npm install
npm test
cd example; jekyll serve
# in another tab
npm run cypress -- run
Thanks to all contributors over the years! You are the best :)
@daviddarnes @XhmikosR @PeterDaveHello @mikeybeck @egladman @midzer @eduardoboucas @kremalicious @tibotiber and many others!