Merge pull request #22 from koirand/test

Test and refactoring search.js
Close #19
This commit is contained in:
Kazuki Koide 2019-03-27 02:08:00 +09:00 committed by GitHub
commit b19c01c3a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 1240 additions and 46 deletions

13
.editorconfig Normal file
View file

@ -0,0 +1,13 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
indent_size = 4

3
.eslintrc.json Normal file
View file

@ -0,0 +1,3 @@
{
"extends": ["standard"]
}

91
.gitignore vendored
View file

@ -1,2 +1,93 @@
.DS_Store .DS_Store
resources resources
# Created by https://www.gitignore.io/api/node
# Edit at https://www.gitignore.io/?templates=node
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# End of https://www.gitignore.io/api/node

View file

@ -1,14 +1,23 @@
var lunrIndex /* global lunr $ */
var lunrResult let lunrIndex
var pagesIndex let lunrResult
let pagesIndex
var bigramTokeniser = function (obj, metadata) { /**
if (obj == null || obj == undefined) { * A function for splitting a string into bigram.
*
* @static
* @param {?(string|object|object[])} obj - The object to convert into tokens
* @param {?object} metadata - Optional metadata to associate with every token
* @returns {lunr.Token[]}
*/
const bigramTokeniser = (obj, metadata) => {
if (obj == null || obj === undefined) {
return [] return []
} }
if (Array.isArray(obj)) { if (Array.isArray(obj)) {
return obj.map(function (t) { return obj.map((t) => {
return new lunr.Token( return new lunr.Token(
lunr.utils.asString(t).toLowerCase(), lunr.utils.asString(t).toLowerCase(),
lunr.utils.clone(metadata) lunr.utils.clone(metadata)
@ -16,67 +25,72 @@ var bigramTokeniser = function (obj, metadata) {
}) })
} }
var str = obj.toString().trim().toLowerCase(), let str = obj.toString().trim().toLowerCase()
tokens = [] let tokens = []
for(var i = 0; i <= str.length - 2; i++) { for (let i = 0; i <= str.length - 2; i++) {
var tokenMetadata = lunr.utils.clone(metadata) || {} const tokenMetadata = lunr.utils.clone(metadata) || {}
tokenMetadata["position"] = [i, i + 2] tokenMetadata['position'] = [i, i + 2]
tokenMetadata["index"] = tokens.length tokenMetadata['index'] = tokens.length
tokens.push( tokens.push(
new lunr.Token ( new lunr.Token(
str.slice(i, i + 2), str.slice(i, i + 2),
tokenMetadata tokenMetadata
) )
) )
} }
return tokens return tokens
} }
var queryNgramSeparator = function (query) { /**
var str = query.toString().trim().toLowerCase(), * A function for separating a string into bigram and join it with space.
tokens = [] *
* @static
* @param {?string} query - The string to convert into tokens
* @returns {string}
*/
const queryNgramSeparator = (query) => {
const str = query.toString().trim().toLowerCase()
const tokens = []
for(var i = 0; i <= str.length - 2; i++) { for (let i = 0; i <= str.length - 2; i++) {
tokens.push(str.slice(i, i + 2)) tokens.push(str.slice(i, i + 2))
} }
return tokens.join(' ') return tokens.join(' ')
} }
/** /**
* Preparation for using lunr.js * Preparation for using lunr.js
*/ */
function initLunr () { const initLunr = () => {
$.getJSON('index.json').done(function (index) { $.getJSON('index.json').done((index) => {
pagesIndex = index pagesIndex = index
lunrIndex = lunr(function () { lunrIndex = lunr(() => {
this.tokenizer = bigramTokeniser this.tokenizer = bigramTokeniser
this.pipeline.reset() this.pipeline.reset()
this.ref('ref') this.ref('ref')
this.field('title', { boost: 10 }) this.field('title', { boost: 10 })
this.field('body') this.field('body')
this.metadataWhitelist = ['position'] this.metadataWhitelist = ['position']
for (var page of pagesIndex) { for (let page of pagesIndex) {
this.add(page) this.add(page)
} }
}) })
}).fail(function (jqxhr, textStatus, error) { }).fail((jqxhr, textStatus, error) => {
var err = textStatus + ', ' + error const err = textStatus + ', ' + error
console.error('Error getting Hugo index flie:', err) console.error('Error getting Hugo index flie:', err)
}) })
} }
/** /**
* Searching pages using lunr * Searching pages using lunr
* @param {String} query Query string for searching * @param {String} query - Query string for searching
* @return {Object[]} Array of search results * @return {Object[]} - Array of search results
*/ */
function search (query) { const search = (query) => {
lunrResult = lunrIndex.search(queryNgramSeparator(query)) lunrResult = lunrIndex.search(queryNgramSeparator(query))
return lunrResult.map(function (result) { return lunrResult.map((result) => {
return pagesIndex.filter(function (page) { return pagesIndex.filter((page) => {
return page.ref === result.ref return page.ref === result.ref
})[0] })[0]
}) })
@ -85,17 +99,17 @@ function search (query) {
/** /**
* Setup UI for Search * Setup UI for Search
*/ */
function initUI () { const initUI = () => {
// Clear query when clear icon is clicked // Clear query when clear icon is clicked
$('#searchBoxIcon').click(function () { $('#searchBoxIcon').click(() => {
$('#searchBoxInput').val('') $('#searchBoxInput').val('')
$('#searchBoxInput').trigger('keyup') $('#searchBoxInput').trigger('keyup')
}) })
// Event when chenging query // Event when chenging query
$('#searchBoxInput').keyup(function () { $('#searchBoxInput').keyup(() => {
var $searchResults = $('#searchResults') const $searchResults = $('#searchResults')
var query = $(this).val() const query = $(this).val()
// Icon switching // Icon switching
if (query.length) { if (query.length) {
@ -125,11 +139,11 @@ function initUI () {
* Rendering search results * Rendering search results
* @param {Object[]} results Array of search results * @param {Object[]} results Array of search results
*/ */
function renderResults (results) { const renderResults = (results) => {
var $searchResults = $('#searchResults') const $searchResults = $('#searchResults')
var query = $('#searchBoxInput').val() const query = $('#searchBoxInput').val()
var BODY_LENGTH = 100 const BODY_LENGTH = 100
var MAX_PAGES = 10 const MAX_PAGES = 10
// Clear search result // Clear search result
$searchResults.empty() $searchResults.empty()
@ -141,11 +155,11 @@ function renderResults (results) {
} }
// Only show the ten first results // Only show the ten first results
results.slice(0, MAX_PAGES).forEach(function (result, idx) { results.slice(0, MAX_PAGES).forEach((result, idx) => {
var $searchResultPage = $('<div class="searchResultPage">') const $searchResultPage = $('<div class="searchResultPage">')
var metadata = lunrResult[idx].matchData.metadata const metadata = lunrResult[idx].matchData.metadata
var matchPosition = metadata[Object.keys(metadata)[0]].body ? metadata[Object.keys(metadata)[0]].body.position[0][0] : 0 const matchPosition = metadata[Object.keys(metadata)[0]].body ? metadata[Object.keys(metadata)[0]].body.position[0][0] : 0
var bodyStartPosition = (matchPosition - (BODY_LENGTH / 2) > 0) ? matchPosition - (BODY_LENGTH / 2) : 0 const bodyStartPosition = (matchPosition - (BODY_LENGTH / 2) > 0) ? matchPosition - (BODY_LENGTH / 2) : 0
$searchResultPage.append('<a class="searchResultTitle" href="' + result.ref + '">' + result.title + '</a>') $searchResultPage.append('<a class="searchResultTitle" href="' + result.ref + '">' + result.title + '</a>')
@ -159,6 +173,6 @@ function renderResults (results) {
initLunr() initLunr()
$(function () { $(() => {
initUI() initUI()
}) })

15
package.json Normal file
View file

@ -0,0 +1,15 @@
{
"name": "pulp",
"version": "1.0.0",
"repository": "git@github.com:koirand/pulp.git",
"author": "koirand <koirand.jp@gmail.com>",
"license": "MIT",
"devDependencies": {
"eslint": "^5.15.3",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0"
}
}

1058
yarn.lock Normal file

File diff suppressed because it is too large Load diff