Merge pull request #10720 from MoonE/apidoc-better-search
Apidoc better search
This commit is contained in:
@@ -106,6 +106,20 @@ function includeTypes(doclet) {
|
||||
}
|
||||
}
|
||||
|
||||
const defaultExports = {};
|
||||
const path = require('path');
|
||||
const moduleRoot = path.join(process.cwd(), 'src');
|
||||
|
||||
// Tag default exported Identifiers because their name should be the same as the module name.
|
||||
exports.astNodeVisitor = {
|
||||
visitNode: function(node, e, parser, currentSourceName) {
|
||||
if (node.type === 'Identifier' && node.parent.type === 'ExportDefaultDeclaration') {
|
||||
const modulePath = path.relative(moduleRoot, currentSourceName).replace(/\.js$/, '');
|
||||
defaultExports['module:' + modulePath + '~' + node.name] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.handlers = {
|
||||
|
||||
newDoclet: function(e) {
|
||||
@@ -169,6 +183,15 @@ exports.handlers = {
|
||||
delete doclet.undocumented;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
processingComplete(e) {
|
||||
const byLongname = e.doclets.index.longname;
|
||||
for (const name in defaultExports) {
|
||||
byLongname[name].forEach(function(doclet) {
|
||||
doclet.isDefaultExport = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -14,7 +14,6 @@ const path = require('jsdoc/lib/jsdoc/path');
|
||||
const taffy = require('taffydb').taffy;
|
||||
const handle = require('jsdoc/lib/jsdoc/util/error').handle;
|
||||
const helper = require('jsdoc/lib/jsdoc/util/templateHelper');
|
||||
const _ = require('underscore');
|
||||
const htmlsafe = helper.htmlsafe;
|
||||
const linkto = helper.linkto;
|
||||
const resolveAuthorLinks = helper.resolveAuthorLinks;
|
||||
@@ -188,10 +187,12 @@ function attachModuleSymbols(doclets, modules) {
|
||||
});
|
||||
}
|
||||
|
||||
function getPrettyName(longname) {
|
||||
return longname
|
||||
.split('~')[0]
|
||||
.replace('module:', '');
|
||||
function getPrettyName(doclet) {
|
||||
const fullname = doclet.longname.replace('module:', '');
|
||||
if (doclet.isDefaultExport) {
|
||||
return fullname.split('~')[0];
|
||||
}
|
||||
return fullname;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,27 +210,13 @@ function getPrettyName(longname) {
|
||||
*/
|
||||
function buildNav(members) {
|
||||
const nav = [];
|
||||
// merge namespaces and classes, then sort
|
||||
const merged = members.modules.concat(members.classes);
|
||||
merged.sort(function(a, b) {
|
||||
const prettyNameA = getPrettyName(a.longname).toLowerCase();
|
||||
const prettyNameB = getPrettyName(b.longname).toLowerCase();
|
||||
if (prettyNameA > prettyNameB) {
|
||||
return 1;
|
||||
}
|
||||
if (prettyNameA < prettyNameB) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
_.each(merged, function(v) {
|
||||
members.classes.forEach(function(v) {
|
||||
// exclude interfaces from sidebar
|
||||
if (v.interface !== true && v.kind === 'class') {
|
||||
if (v.interface !== true) {
|
||||
nav.push({
|
||||
type: 'class',
|
||||
longname: v.longname,
|
||||
prettyname: getPrettyName(v.longname),
|
||||
prettyname: getPrettyName(v),
|
||||
name: v.name,
|
||||
module: find({
|
||||
kind: 'module',
|
||||
@@ -253,44 +240,57 @@ function buildNav(members) {
|
||||
memberof: v.longname
|
||||
})
|
||||
});
|
||||
} else if (v.kind == 'module') {
|
||||
const classes = find({
|
||||
kind: 'class',
|
||||
memberof: v.longname
|
||||
});
|
||||
const members = find({
|
||||
kind: 'member',
|
||||
memberof: v.longname
|
||||
});
|
||||
const methods = find({
|
||||
kind: 'function',
|
||||
memberof: v.longname
|
||||
});
|
||||
const typedefs = find({
|
||||
kind: 'typedef',
|
||||
memberof: v.longname
|
||||
});
|
||||
const events = find({
|
||||
kind: 'event',
|
||||
memberof: v.longname
|
||||
});
|
||||
// Only add modules that contain more than just classes with their
|
||||
// associated Options typedef
|
||||
if (typedefs.length > classes.length || members.length + methods.length > 0) {
|
||||
nav.push({
|
||||
type: 'module',
|
||||
longname: v.longname,
|
||||
prettyname: getPrettyName(v.longname),
|
||||
name: v.name,
|
||||
members: members,
|
||||
methods: methods,
|
||||
typedefs: typedefs,
|
||||
fires: v.fires,
|
||||
events: events
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
members.modules.forEach(function(v) {
|
||||
const classes = find({
|
||||
kind: 'class',
|
||||
memberof: v.longname
|
||||
});
|
||||
const members = find({
|
||||
kind: 'member',
|
||||
memberof: v.longname
|
||||
});
|
||||
const methods = find({
|
||||
kind: 'function',
|
||||
memberof: v.longname
|
||||
});
|
||||
const typedefs = find({
|
||||
kind: 'typedef',
|
||||
memberof: v.longname
|
||||
});
|
||||
const events = find({
|
||||
kind: 'event',
|
||||
memberof: v.longname
|
||||
});
|
||||
// Only add modules that contain more than just classes with their
|
||||
// associated Options typedef
|
||||
if (typedefs.length > classes.length || members.length + methods.length > 0) {
|
||||
nav.push({
|
||||
type: 'module',
|
||||
longname: v.longname,
|
||||
prettyname: getPrettyName(v),
|
||||
name: v.name,
|
||||
members: members,
|
||||
methods: methods,
|
||||
typedefs: typedefs,
|
||||
fires: v.fires,
|
||||
events: events
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
nav.sort(function(a, b) {
|
||||
const prettyNameA = a.prettyname.toLowerCase();
|
||||
const prettyNameB = b.prettyname.toLowerCase();
|
||||
if (prettyNameA > prettyNameB) {
|
||||
return 1;
|
||||
}
|
||||
if (prettyNameA < prettyNameB) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return nav;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,99 +1,258 @@
|
||||
$(function () {
|
||||
// Search Items
|
||||
$('#include_modules').change(function (e) {
|
||||
console.log('change');
|
||||
if ($(this).is(':checked')) {
|
||||
'use strict';
|
||||
|
||||
// Allow user configuration?
|
||||
const allowRegex = true;
|
||||
const minInputForSearch = 1;
|
||||
const minInputForFullText = 2;
|
||||
const expandAllOnInputWithoutSearch = true;
|
||||
|
||||
function constructRegex(searchTerm, makeRe, allowRegex) {
|
||||
try {
|
||||
if (allowRegex) {
|
||||
return makeRe(searchTerm);
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
// In case of invalid regexp fall back to non-regexp, but still allow . to match /
|
||||
return makeRe(searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\\\./g, '[./]'));
|
||||
}
|
||||
|
||||
function getWeightFunction(searchTerm, allowRegex) {
|
||||
function makeRe(searchTerm) {
|
||||
return {
|
||||
begin: new RegExp('\\b' + searchTerm), // Begin matches word boundary
|
||||
baseName: new RegExp('\\b' + searchTerm + '[^/]*$'), // Begin matches word boundary of class / module name
|
||||
fullName: new RegExp('\\b' + searchTerm + '(?:[~.]|$)'), // Complete word(s) of class / module matches
|
||||
completeName: new RegExp('^' + searchTerm + '$') // Match from start to finish
|
||||
}
|
||||
}
|
||||
const re = constructRegex(searchTerm, makeRe, allowRegex);
|
||||
return function (matchedItem, beginOnly) {
|
||||
// We could get smarter on the weight here
|
||||
const name = matchedItem.dataset.name;
|
||||
if (beginOnly) {
|
||||
return re.baseName.test(name) ? 100 : 1;
|
||||
}
|
||||
// If everything else is equal, prefer shorter names, and prefer classes over modules
|
||||
let weight = 10000 + matchedItem.dataset.longname.length - name.length * 100;
|
||||
if (name.match(re.begin)) {
|
||||
weight += 10000;
|
||||
if (re.baseName.test(name)) {
|
||||
weight += 10000;
|
||||
if (re.fullName.test(name)) {
|
||||
weight += 10000;
|
||||
if (re.completeName.test(name)) {
|
||||
weight += 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
}
|
||||
|
||||
const search = (function () {
|
||||
const $navList = $('.navigation-list');
|
||||
const navListNode = $navList.get(0);
|
||||
let $classItems;
|
||||
let $members;
|
||||
let stateClass = (function () {
|
||||
$navList.removeClass('search-started searching');
|
||||
$navList.addClass('search-empty');
|
||||
return 'search-empty';
|
||||
})();
|
||||
let manualToggles = {};
|
||||
|
||||
// Show an item related a current documentation automatically
|
||||
const longname = $('.page-title').data('filename')
|
||||
.replace(/\.[a-z]+$/, '')
|
||||
.replace('module-', 'module:')
|
||||
.replace(/_/g, '/')
|
||||
.replace(/-/g, '~');
|
||||
const currentItem = navListNode.querySelector('.item[data-longname="' + longname + '"]');
|
||||
if (currentItem) {
|
||||
$navList.prepend(currentItem);
|
||||
}
|
||||
return {
|
||||
$navList: $navList,
|
||||
$currentItem: currentItem ? $(currentItem) : undefined,
|
||||
lastSearchTerm: undefined,
|
||||
lastState: {},
|
||||
getClassList: function () {
|
||||
return $classItems || ($classItems = $navList.find('li.item'));
|
||||
},
|
||||
getMembers: function () {
|
||||
return $members || ($members = $navList.find('.item li'));
|
||||
},
|
||||
changeStateClass: function (newClass) {
|
||||
if (newClass !== stateClass) {
|
||||
navListNode.classList.remove(stateClass);
|
||||
navListNode.classList.add(newClass);
|
||||
stateClass = newClass;
|
||||
}
|
||||
},
|
||||
manualToggle: function ($node, show) {
|
||||
$node.addClass('toggle-manual');
|
||||
$node.toggleClass('toggle-manual-hide', !show);
|
||||
$node.toggleClass('toggle-manual-show', show);
|
||||
manualToggles[$node.data('longname')] = $node;
|
||||
},
|
||||
clearManualToggles: function() {
|
||||
for (let clsName in manualToggles) {
|
||||
manualToggles[clsName].removeClass('toggle-manual toggle-manual-show toggle-manual-hide');
|
||||
}
|
||||
manualToggles = {};
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
||||
const dummy = {subItems: {}};
|
||||
function clearOldMatches(lastState, searchState) {
|
||||
for (let itemName in lastState) {
|
||||
const lastItem = lastState[itemName];
|
||||
const item = searchState[itemName];
|
||||
if (!item) {
|
||||
lastItem.item.classList.remove('match');
|
||||
}
|
||||
if (lastItem.subItems) {
|
||||
clearOldMatches(lastItem.subItems, (item || dummy).subItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doSearch(searchTerm) {
|
||||
searchTerm = searchTerm.toLowerCase();
|
||||
const lastSearchTerm = search.lastSearchTerm;
|
||||
if (searchTerm === lastSearchTerm) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid layout reflow by scrolling to top first.
|
||||
search.$navList.scrollTop(0);
|
||||
search.lastSearchTerm = searchTerm;
|
||||
search.clearManualToggles();
|
||||
|
||||
if (searchTerm.length < minInputForSearch) {
|
||||
const state = searchTerm.length && expandAllOnInputWithoutSearch ? 'search-started' : 'search-empty';
|
||||
search.changeStateClass(state);
|
||||
if (lastSearchTerm !== undefined && lastSearchTerm.length >= minInputForSearch) {
|
||||
// Restore the original, sorted order
|
||||
search.$navList.append(search.getClassList());
|
||||
}
|
||||
if (state === 'search-empty' && search.$currentItem) {
|
||||
search.manualToggle(search.$currentItem, true);
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
var getSearchWeight = function (searchTerm, $matchedItem) {
|
||||
let weight = 0;
|
||||
// We could get smarter on the weight here
|
||||
if ($matchedItem.data('shortname')
|
||||
&& $matchedItem.data('shortname').toLowerCase() === searchTerm.toLowerCase()) {
|
||||
weight++;
|
||||
}
|
||||
return weight;
|
||||
};
|
||||
|
||||
// sort function callback
|
||||
var weightSorter = function (a, b) {
|
||||
var aW = $(a).data('weight') || 0;
|
||||
var bW = $(b).data('weight') || 0;
|
||||
return bW - aW;
|
||||
};
|
||||
|
||||
// Search Items
|
||||
$('#search').on('keyup', function (e) {
|
||||
var value = $(this).val();
|
||||
var $el = $('.navigation');
|
||||
|
||||
if (value && value.length > 1) {
|
||||
var regexp = new RegExp(value, 'i');
|
||||
$el.find('li, .member-list').hide();
|
||||
|
||||
$el.find('li').each(function (i, v) {
|
||||
const $item = $(v);
|
||||
const name = $item.data('name');
|
||||
|
||||
if (name && regexp.test(name)) {
|
||||
const $classEntry = $item.closest('.item');
|
||||
const $members = $item.closest('.member-list');
|
||||
|
||||
// Do the weight thing
|
||||
$classEntry.removeData('weight');
|
||||
$classEntry.show();
|
||||
const weight = getSearchWeight(value, $classEntry);
|
||||
$classEntry.data('weight', weight);
|
||||
|
||||
$members.show();
|
||||
$classEntry.show();
|
||||
$item.show();
|
||||
search.changeStateClass('searching');
|
||||
searchTerm = searchTerm.toLowerCase();
|
||||
const beginOnly = searchTerm.length < minInputForFullText;
|
||||
const getSearchWeight = getWeightFunction(searchTerm, allowRegex);
|
||||
const re = constructRegex(searchTerm, function (searchTerm) {
|
||||
return new RegExp((beginOnly ? '\\b' : '') + searchTerm);
|
||||
}, allowRegex);
|
||||
const navList = search.$navList.get(0);
|
||||
const classes = [];
|
||||
const searchState = {};
|
||||
search.getClassList().each(function (i, classEntry) {
|
||||
const className = classEntry.dataset.longname;
|
||||
if (!(className in searchState) && re.test(classEntry.dataset.name)) {
|
||||
const cls = searchState[className] = {
|
||||
item: classEntry,
|
||||
// Do the weight thing
|
||||
weight: getSearchWeight(classEntry, beginOnly) * 100000,
|
||||
subItems: {}
|
||||
};
|
||||
classes.push(cls);
|
||||
classEntry.classList.add('match');
|
||||
}
|
||||
});
|
||||
search.getMembers().each(function (i, li) {
|
||||
const name = li.dataset.name;
|
||||
if (re.test(name)) {
|
||||
const itemMember = li.parentElement.parentElement;
|
||||
const classEntry = itemMember.parentElement;
|
||||
const className = classEntry.dataset.longname;
|
||||
let cls = searchState[className];
|
||||
if (!cls) {
|
||||
cls = searchState[className] = {
|
||||
item: classEntry,
|
||||
weight: 0,
|
||||
subItems: {}
|
||||
};
|
||||
classes.push(cls);
|
||||
classEntry.classList.add('match');
|
||||
}
|
||||
cls.weight += getSearchWeight(li, true);
|
||||
const memberType = itemMember.dataset.type;
|
||||
let members = cls.subItems[memberType];
|
||||
if (!members) {
|
||||
members = cls.subItems[memberType] = {
|
||||
item: itemMember,
|
||||
subItems: {}
|
||||
};
|
||||
itemMember.classList.add('match');
|
||||
}
|
||||
members.subItems[name] = { item: li };
|
||||
li.classList.add('match');
|
||||
}
|
||||
});
|
||||
clearOldMatches(search.lastState, searchState);
|
||||
search.lastState = searchState;
|
||||
|
||||
$(".navigation ul.list li.item:visible")
|
||||
.sort(weightSorter) // sort elements
|
||||
.appendTo(".navigation ul.list"); // append again to the list
|
||||
|
||||
} else {
|
||||
$el.find('.item, .member-list').show();
|
||||
classes.sort(function (a, b) {
|
||||
return a.weight - b.weight;
|
||||
});
|
||||
for (let i = classes.length - 1; i >= 0; --i) {
|
||||
navList.appendChild(classes[i].item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$el.find('.list').scrollTop(0);
|
||||
});
|
||||
const searchInput = $('#search').get(0);
|
||||
// Skip searches when typing fast.
|
||||
let key;
|
||||
function queueSearch() {
|
||||
if (!key) {
|
||||
key = setTimeout(function () {
|
||||
key = undefined;
|
||||
|
||||
const searchTerm = searchInput.value;
|
||||
doSearch(searchTerm);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Search Items
|
||||
searchInput.addEventListener('input', queueSearch);
|
||||
doSearch(searchInput.value);
|
||||
|
||||
// Toggle when click an item element
|
||||
$('.navigation').on('click', '.toggle', function (e) {
|
||||
$(this).parent().parent().find('.member-list').toggle();
|
||||
search.$navList.on('click', '.toggle', function (e) {
|
||||
if (event.target.tagName.toLowerCase() === 'a') {
|
||||
return;
|
||||
}
|
||||
const clsItem = $(this).closest('.item');
|
||||
let show;
|
||||
if (clsItem.hasClass('toggle-manual-show')) {
|
||||
show = false;
|
||||
} else if (clsItem.hasClass('toggle-manual-hide')) {
|
||||
show = true;
|
||||
} else {
|
||||
clsItem.find('.member-list li').each(function (i, v) {
|
||||
show = $(v).is(':hidden');
|
||||
return !show;
|
||||
});
|
||||
}
|
||||
search.manualToggle(clsItem, !!show);
|
||||
});
|
||||
|
||||
// Show an item related a current documentation automatically
|
||||
var filename = $('.page-title').data('filename')
|
||||
.replace(/\.[a-z]+$/, '')
|
||||
.replace('module-', 'module:')
|
||||
.replace(/_/g, '/')
|
||||
.replace(/-/g, '~');
|
||||
var $currentItem = $('.navigation .item[data-name*="' + filename + '"]:eq(0)');
|
||||
|
||||
if ($currentItem.length) {
|
||||
$currentItem
|
||||
.remove()
|
||||
.prependTo('.navigation .list')
|
||||
.show()
|
||||
.find('.member-list')
|
||||
.show();
|
||||
}
|
||||
|
||||
// Auto resizing on navigation
|
||||
var _onResize = function () {
|
||||
var height = $(window).height();
|
||||
var $el = $('.navigation');
|
||||
|
||||
$el.height(height).find('.list').height(height - 133);
|
||||
$el.height(height).find('.navigation-list').height(height - 133);
|
||||
};
|
||||
|
||||
$(window).on('resize', _onResize);
|
||||
@@ -137,22 +296,4 @@ $(function () {
|
||||
'<a href="' + link + textParts[1].replace('line ', '#L') + '">' +
|
||||
textParts[1] + '</a>';
|
||||
});
|
||||
|
||||
// Highlighting current anchor
|
||||
|
||||
var anchors = $('.anchor');
|
||||
var _onHashChange = function () {
|
||||
var activeHash = window.document.location.hash
|
||||
.replace(/\./g, '\\.') // Escape dot in element id
|
||||
.replace(/\~/g, '\\~'); // Escape tilde in element id
|
||||
|
||||
anchors.removeClass('highlighted');
|
||||
|
||||
if (activeHash.length > 0) {
|
||||
anchors.filter(activeHash).addClass('highlighted');
|
||||
}
|
||||
};
|
||||
|
||||
$(window).on('hashchange', _onHashChange);
|
||||
_onHashChange();
|
||||
});
|
||||
|
||||
@@ -51,7 +51,8 @@ body {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
.nameContainer .anchor.highlighted + h4 {
|
||||
/* Highlighting current anchor */
|
||||
.nameContainer .anchor:target + h4 {
|
||||
background-color: #faebcc;
|
||||
}
|
||||
a {
|
||||
@@ -123,7 +124,7 @@ li {
|
||||
color: #fff;
|
||||
border-color: #555;
|
||||
}
|
||||
.navigation .list {
|
||||
.navigation .navigation-list {
|
||||
padding: 10px 15px 0 15px;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
@@ -135,6 +136,24 @@ li {
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
.navigation .glyphicon {
|
||||
margin-right: 3px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.navigation .item .glyphicon:before {
|
||||
display: inline-block;
|
||||
}
|
||||
.navigation .item.toggle-manual .glyphicon:before {
|
||||
transition: transform .1s;
|
||||
}
|
||||
.navigation .item-class.toggle-manual-show .glyphicon:before {
|
||||
/* With 90deg the icon slightly slides left at transition end */
|
||||
transform: rotate(89.9deg);
|
||||
}
|
||||
.navigation .item-module.toggle-manual-show .glyphicon:before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.navigation li.perfect-match {
|
||||
border: 5px solid orange;
|
||||
}
|
||||
@@ -147,8 +166,8 @@ li {
|
||||
}
|
||||
.navigation li.item .title {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: block;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
.navigation li.item .title a {
|
||||
@@ -184,9 +203,41 @@ li {
|
||||
margin-top: 2px;
|
||||
}
|
||||
.navigation li.item .member-list {
|
||||
display: none;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
/* search state */
|
||||
/* show all classes when search is empty */
|
||||
.navigation-list.search-empty .item {
|
||||
display: block;
|
||||
}
|
||||
/* hide all members by default when search is empty */
|
||||
.navigation-list.search-empty .item .member-list {
|
||||
display: none;
|
||||
}
|
||||
/* expand all members when input in search field available but too short to search */
|
||||
.navigation-list.search-started li,
|
||||
.navigation-list.search-started .member-list {
|
||||
display: block;
|
||||
}
|
||||
/* when searching hide everything that is not a match */
|
||||
.navigation-list.searching li,
|
||||
.navigation-list.searching .member-list {
|
||||
display: none;
|
||||
}
|
||||
.navigation-list.searching .match {
|
||||
display: block;
|
||||
}
|
||||
/* allow user to hide / show members */
|
||||
.navigation-list .item.toggle-manual-show li,
|
||||
.navigation-list .item.toggle-manual-show .member-list {
|
||||
display: block!important;
|
||||
}
|
||||
.navigation-list:not(.searching) .item.toggle-manual-hide li,
|
||||
.navigation-list:not(.searching) .item.toggle-manual-hide .member-list {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 20px 20px;
|
||||
margin-left: 250px;
|
||||
|
||||
@@ -15,17 +15,17 @@ function getItemCssClass(type) {
|
||||
}
|
||||
|
||||
const printList = v => { ?>
|
||||
<li data-name="<?js= v.longname ?>"><?js
|
||||
<li data-name="<?js= toShortName(v.name).toLowerCase() ?>"><?js
|
||||
}
|
||||
const printListWithStability = v => {
|
||||
const cls = v.stability && v.stability !== 'stable' ? ' class="unstable"' : ''; ?>
|
||||
<li data-name="<?js= v.longname ?>"<?js= cls ?>><?js
|
||||
<li data-name="<?js= toShortName(v.name).toLowerCase() ?>"<?js= cls ?>><?js
|
||||
}
|
||||
|
||||
function listContent(item, title, listItemPrinter) {
|
||||
const type = title.toLowerCase();
|
||||
if (item[type] && item[type].length) { ?>
|
||||
<div class="member-list">
|
||||
<div class="member-list" data-type="<?js= type ?>">
|
||||
<span class="subtitle"><?js= title ?></span>
|
||||
<ul><?js
|
||||
item[type].forEach(function (v) {
|
||||
@@ -40,12 +40,12 @@ function listContent(item, title, listItemPrinter) {
|
||||
<div class="search">
|
||||
<input id="search" type="text" class="form-control input-sm" placeholder="Search Documentation">
|
||||
</div>
|
||||
<ul class="list"><?js
|
||||
<ul class="navigation-list search-empty"><?js
|
||||
this.nav.forEach(function (item) { ?>
|
||||
<li class="item" data-name="<?js= item.longname ?>" data-shortname="<?js= item.name.toLowerCase() ?>">
|
||||
<span class="title">
|
||||
<span class="glyphicon <?js= getItemCssClass(item.type) ?> toggle"></span>
|
||||
<?js= self.linkto(item.longname, item.prettyname) ?>
|
||||
<li class="item item-<?js= item.type ?>" data-longname="<?js= item.longname ?>" data-name="<?js= item.prettyname.toLowerCase() ?>">
|
||||
<span class="title toggle">
|
||||
<span class="glyphicon <?js= getItemCssClass(item.type) ?>"></span>
|
||||
<span><?js= self.linkto(item.longname, item.prettyname.replace(/[.~]/g, '\u200b$&')) ?></span>
|
||||
</span><?js
|
||||
listContent(item, 'Members', printList);
|
||||
listContent(item, 'Typedefs', printListWithStability);
|
||||
|
||||
Reference in New Issue
Block a user