Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: don't depend on underscore.js #116

Merged
merged 1 commit into from
Aug 9, 2022
Merged
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
9 changes: 7 additions & 2 deletions docs/customization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,14 @@ is given below for reference:
<a href="/api-v2?highlight=api#section-1-sphinx-domain">
<div class="outer_div_page_results" id="hit__3">

<!-- Domain role_name -->
<!-- Domain name -->
<span class="search__result__subheading">
http:get
/api/v2/section/

<!-- Domain role name -->
<div class="search__domain_role_name">
[http:get]
</div>
</span>

<!-- Domain Content -->
Expand Down
191 changes: 98 additions & 93 deletions sphinx_search/static/js/rtd_sphinx_search.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,46 @@ const debounce = (func, wait) => {


/**
* Wrapper around underscorejs's template function.
*
* This is to make it work with new and old versions.
*/
const render_template = (template, data) => {
// pre-1.7 syntax from underscorejs.
let result = $u.template(template, data);
if (typeof result === 'function') {
// New syntax.
result = $u.template(template)(data);
* Build a section with its matching results.
*
* A section has the form:
*
* <a href="{link}">
* <div class="outer_div_page_results" id="{id}">
* <span class="search__result__subheading">
* {title}
* </span>
* <p class="search__result__content">
* {contents[0]}
* </p>
* <p class="search__result__content">
* {contents[1]}
* </p>
* ...
* </div>
* </a>
*
* @param {String} id.
* @param {String} title.
* @param {String} link.
* @param {Array} contents.
*/
const buildSection = function (id, title, link, contents) {
let span_element = createDomNode("span", {class: "search__result__subheading"});
span_element.innerHTML = title;

let div_element = createDomNode("div", {class: "outer_div_page_results", id: id});
div_element.appendChild(span_element);

for (var i = 0; i < contents.length; i += 1) {
let p_element = createDomNode("p", {class: "search__result__content"});
p_element.innerHTML = contents[i];
div_element.appendChild(p_element);
}
return result;

let section = createDomNode("a", {href: link});
section.appendChild(div_element);
return section;
};


Expand Down Expand Up @@ -105,8 +133,10 @@ const isModalVisible = () => {
*/
const createDomNode = (nodeName, attributes) => {
let node = document.createElement(nodeName);
for (let attr in attributes) {
node.setAttribute(attr, attributes[attr]);
if (attributes !== null) {
for (let attr in attributes) {
node.setAttribute(attr, attributes[attr]);
}
}
return node;
};
Expand Down Expand Up @@ -135,21 +165,6 @@ const _is_string = str => {
* @param {Number} id to be used in for this section
*/
const get_section_html = (sectionData, page_link, id) => {
let section_template =
'<a href="<%= section_link %>"> \
<div class="outer_div_page_results" id="<%= section_id %>"> \
<span class="search__result__subheading"> \
<%= section_subheading %> \
</span> \
<% for (var i = 0; i < section_content.length; ++i) { %> \
<p class="search__result__content"> \
<%= section_content[i] %> \
</p> \
<% } %>\
</div> \
</a> \
<br class="br-for-hits">';

let section_subheading = sectionData.title;
let highlights = sectionData.highlights;
if (highlights.title.length) {
Expand All @@ -173,17 +188,8 @@ const get_section_html = (sectionData, page_link, id) => {
}

let section_link = `${page_link}#${sectionData.id}`;

let section_id = "hit__" + id;

let section_html = render_template(section_template, {
section_link: section_link,
section_id: section_id,
section_subheading: section_subheading,
section_content: section_content
});

return section_html;
return buildSection(section_id, section_subheading, section_link, section_content);
};

/**
Expand All @@ -195,20 +201,6 @@ const get_section_html = (sectionData, page_link, id) => {
* @param {Number} id to be used in for this section
*/
const get_domain_html = (domainData, page_link, id) => {
let domain_template =
'<a href="<%= domain_link %>"> \
<div class="outer_div_page_results" id="<%= domain_id %>"> \
<span class="search__result__subheading"> \
<%= domain_subheading %> \
<div class="search__domain_role_name"> \
<%= domain_role_name %> \
</div> \
</span> \
<p class="search__result__content"><%= domain_content %></p> \
</div> \
</a> \
<br class="br-for-hits">';

let domain_link = `${page_link}#${domainData.id}`;
let domain_role_name = domainData.role;
let domain_name = domainData.name;
Expand All @@ -224,37 +216,50 @@ const get_domain_html = (domainData, page_link, id) => {
}

let domain_id = "hit__" + id;
domain_role_name = "[" + domain_role_name + "]";

let domain_html = render_template(domain_template, {
domain_link: domain_link,
domain_id: domain_id,
domain_content: domain_content,
domain_subheading: domain_name,
domain_role_name: domain_role_name
});

return domain_html;
let div_role_name = createDomNode("div", {class: "search__domain_role_name"});
div_role_name.innerText = `[${domain_role_name}]`;
domain_name += div_role_name.outerHTML;

return buildSection(
domain_id,
domain_name,
domain_link,
[domain_content]
);
};


/**
* Generate search results for a single page.
*
* This has the form:
* <div>
* <a href="{link}">
* <h2 class="search__result__title">
* {title}
* <small class="rtd_ui_search_subtitle">{subtitle}</small>
* <br/>
* </h2>
* </a>
*
* <a href="{link}">
* {section}
* </a>
* <br class="br-for-hits" />
*
* <a href="{link}">
* {section}
* </a>
* <br class="br-for-hits" />
* </div>
*
* @param {Object} resultData search results of a page
* @param {String} projectName
* @param {Number} id from the last section
* @return {Object} a <div> node with the results of a single page
*/
const generateSingleResult = (resultData, projectName, id) => {
let content = createDomNode("div");

let page_link_template =
'<a href="<%= page_link %>"> \
<h2 class="search__result__title"> \
<%= page_title %> \
</h2> \
</a>';

let page_link = resultData.path;
let page_title = resultData.title;
let highlights = resultData.highlights;
Expand All @@ -263,47 +268,47 @@ const generateSingleResult = (resultData, projectName, id) => {
page_title = highlights.title[0];
}

// if result is not from the same project,
// then it must be from subproject.
let h2_element = createDomNode("h2", {class: "search__result__title"});
h2_element.innerHTML = page_title;

// If the result is not from the same project,
// then it's from a subproject.
if (projectName !== resultData.project) {
page_title +=
" " +
render_template(
'<small class="rtd_ui_search_subtitle"> \
(from project <%= project %>) \
</small>',
{
project: resultData.project
}
);
let subtitle = createDomNode("small", {class: "rtd_ui_search_subtitle"});
subtitle.innerText = `(from project ${resultData.project})`;
h2_element.appendChild(subtitle);
}
h2_element.appendChild(createDomNode("br"))

page_title += "<br>";
let a_element = createDomNode("a", {href: page_link});
a_element.appendChild(h2_element);

content.innerHTML += render_template(page_link_template, {
page_link: page_link,
page_title: page_title
});
let content = createDomNode("div");
content.appendChild(a_element);

let separator = createDomNode("br", {class: "br-for-hits"});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If more space is needed, wrapping in a <p> is preferable to styling spacing using <br>, which should almost always be avoided. The issue with <br> is that it is difficult to style around. Wrapping each block in <p> should get you similar vertical spacing however.

for (let i = 0; i < resultData.blocks.length; ++i) {
let block = resultData.blocks[i];
let html_structure = "";

let section = null;
id += 1;
if (block.type === "section") {
html_structure = get_section_html(
section = get_section_html(
block,
page_link,
id,
);
} else if (block.type === "domain") {
html_structure = get_domain_html(
section = get_domain_html(
block,
page_link,
id,
);
}
content.innerHTML += html_structure;

if (section !== null) {
content.appendChild(section);
content.appendChild(separator);
}
}
return content;
};
Expand Down
Loading