Skip to content
This repository has been archived by the owner on Sep 7, 2020. It is now read-only.

[WIP] Add search function with Algolia #768

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/webpack.config.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const makeConfig = (config = {}) => {
},

postcss: () => [
require("stylelint")(),
// require("stylelint")(),
require("postcss-cssnext")({ browsers: "last 2 versions" }),
require("postcss-reporter")(),
...!config.production ? [
Expand Down
3 changes: 3 additions & 0 deletions flow/interfaces/node-modules/cheerio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module "cheerio" {
declare var exports: any
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"babel-preset-latest": "^6.14.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-1": "^6.13.0",
"cheerio": "^0.22.0",
"cmd-shim": "^2.0.2",
"coveralls": "^2.11.8",
"cross-env": "^2.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"content": "paragraph 1.1 - 1<span>foo</span>",
"closestHeading": {
"heading": 2,
"content": "1.1"
}
},
{
"content": "paragraph 1.1 - 2<span>foo</span>",
"closestHeading": {
"heading": 2,
"content": "1.1"
}
},
{
"content": "paragraph 1.1.2.1.1.1 - 1<span>bar</span>",
"closestHeading": {
"heading": 6,
"content": "1.1.2.1.1.1"
}
}
]
146 changes: 146 additions & 0 deletions src/_utils/search/create-index/__tests__/headings-list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
[
{
"heading": 1,
"content": "1",
"parents": []
},
{
"heading": 2,
"content": "1.1",
"parents": [
{
"heading": 1,
"content": "1"
}
]
},
{
"heading": 3,
"content": "1.1.1",
"parents": [
{
"heading": 2,
"content": "1.1"
},
{
"heading": 1,
"content": "1"
}
]
},
{
"heading": 3,
"content": "1.1.2",
"parents": [
{
"heading": 2,
"content": "1.1"
},
{
"heading": 1,
"content": "1"
}
]
},
{
"heading": 4,
"content": "1.1.2.1",
"parents": [
{
"heading": 3,
"content": "1.1.2"
},
{
"heading": 2,
"content": "1.1"
},
{
"heading": 1,
"content": "1"
}
]
},
{
"heading": 5,
"content": "1.1.2.1.1",
"parents": [
{
"heading": 4,
"content": "1.1.2.1"
},
{
"heading": 3,
"content": "1.1.2"
},
{
"heading": 2,
"content": "1.1"
},
{
"heading": 1,
"content": "1"
}
]
},
{
"heading": 6,
"content": "1.1.2.1.1.1",
"parents": [
{
"heading": 5,
"content": "1.1.2.1.1"
},
{
"heading": 4,
"content": "1.1.2.1"
},
{
"heading": 3,
"content": "1.1.2"
},
{
"heading": 2,
"content": "1.1"
},
{
"heading": 1,
"content": "1"
}
]
},
{
"heading": 2,
"content": "1.2",
"parents": [
{
"heading": 1,
"content": "1"
}
]
},
{
"heading": 1,
"content": "2",
"parents": []
},
{
"heading": 1,
"content": "3",
"parents": []
},
{
"heading": 2,
"content": "3.1",
"parents": [
{
"heading": 1,
"content": "3"
}
]
},
{
"heading": 1,
"content": "4",
"parents": []
}
]
65 changes: 65 additions & 0 deletions src/_utils/search/create-index/__tests__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import test from "ava"
import cheerio from "cheerio"

import headingsList from "../headings-list"
import headingsListResult from "./headings-list.json"

import findClosestHeading from "../find-closest-heading"
import findClosestHeadingResult from "./find-closest-heading-result"

import makeHierarchy from "../make-hierarchy"
import makeHierarchyResult from "./make-hierarchy-result.json"

import createIndex from ".."
// NOTE: The below markup is a flat tree
// indentations were added to make it readable
const document = `
<h1>1</h1>
<h2>1.1</h2>
<p>paragraph 1.1 - 1<span>foo</span></p>
<p>paragraph 1.1 - 2<span>foo</span></p>
<h3>1.1.1</h3>
<h3>1.1.2</h3>
<h4>1.1.2.1</h4>
<h5>1.1.2.1.1</h5>
<h6>1.1.2.1.1.1</h6>
<p>paragraph 1.1.2.1.1.1 - 1<span>bar</span></p>
<h2>1.2</h2>
<h1>2</h1>
<h1>3</h1>
<h2>3.1</h2>
<h1>4</h1>
`

test("create a hierarchy index", (t) => {
const $ = cheerio.load(document)
t.deepEqual(
headingsList($),
headingsListResult,
"it should parse html to headings list"
)

t.deepEqual(
findClosestHeading($),
findClosestHeadingResult,
"it should find all paragraphs along with its closest heading"
)

t.deepEqual(
makeHierarchy(headingsListResult, findClosestHeadingResult),
makeHierarchyResult,
"it should make a hierarchy based on headings list and paragraphs"
)
})

test("main function", (t) => {
t.deepEqual(createIndex(document), makeHierarchyResult)
})

test("it works with documnent with a single paragraph", (t) => {
const html = `<p>
Content here not used, see <code>src/layouts/PageError</code>
</p>`

t.truthy(createIndex(html))
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[
{
"h2": "1.1",
"h1": "1",
"content": "paragraph 1.1 - 1<span>foo</span>"
},
{
"h2": "1.1",
"h1": "1",
"content": "paragraph 1.1 - 2<span>foo</span>"
},
{
"h6": "1.1.2.1.1.1",
"h5": "1.1.2.1.1",
"h4": "1.1.2.1",
"h3": "1.1.2",
"h2": "1.1",
"h1": "1",
"content": "paragraph 1.1.2.1.1.1 - 1<span>bar</span>"
}
]
48 changes: 48 additions & 0 deletions src/_utils/search/create-index/find-closest-heading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// @flow
export type paragraphWithClosestHeading = {
content: string,
closestHeading?: {
heading: number,
content: string,
},
}
export type paragraphsWithClosestHeading = Array<paragraphWithClosestHeading>

/*
* Find closest heading to all paragraph
*/
export default function($: any): paragraphsWithClosestHeading {
const result = []

$("p").each(function() {
let next = true
let currentTag = $(this)

while (next) {
currentTag = currentTag.prev()

if (typeof currentTag.get(0) === "undefined") {
result.push({
content: $(this).html(),
})
next = false
}
else {
const currentTagName = currentTag.get(0).tagName

if (/^h\d$/.test(currentTagName)) {
result.push({
content: $(this).html(),
closestHeading: {
heading: parseInt(currentTagName.slice(1)),
content: currentTag.text(),
},
})
next = false
}
}
}
})

return result
}
42 changes: 42 additions & 0 deletions src/_utils/search/create-index/headings-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// @flow
export type heading = {
heading: number,
content: string,
parents: Array<heading>,
}

export type headingsList = Array<heading>
/*
* Generate a heading list
*/
export default function($: any) {
const filter = "h1, h2, h3, h4, h5, h6"

const flatTree = []
$(filter).each(function() {
flatTree.push({
heading: parseInt($(this).get(0).tagName.slice(1)),
content: $(this).text(),
})
})

return flatTree.map((node, i) => {
let currentHeadingLvl = node.heading - 1

const result = {
...node,
parents: [],
}

while (currentHeadingLvl > 0 && i >= 0) {
const currentNode = flatTree[i]
if (currentNode.heading === currentHeadingLvl) {
result.parents.push(currentNode)
currentHeadingLvl--
}
i--
}

return result
})
}
19 changes: 19 additions & 0 deletions src/_utils/search/create-index/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// @flow
import cheerio from "cheerio"
import headingsList from "./headings-list"
import findClosestHeading from "./find-closest-heading"
import makeHierarchy from "./make-hierarchy"
import type { hierarchy } from "./make-hierarchy"

const createIndexFromHTML = (html: string): hierarchy => {
const $ = cheerio.load(html)
const headingsListResult = headingsList($)
const paragraphsWithClosestHeading = findClosestHeading($)

return makeHierarchy(
headingsListResult,
paragraphsWithClosestHeading
)
}

export default createIndexFromHTML
Loading