(function () { /** * Converts a colon formatted string to a object with properties. * * This is process a provided string and look for any tokens in the format * of `:name[=value]` and then convert it to a object and return. * An example of this is ':include :type=code :fragment=demo' is taken and * then converted to: * * ``` * { * include: '', * type: 'code', * fragment: 'demo' * } * ``` * * @param {string} str The string to parse. * * @return {object} The original string and parsed object, { str, config }. */ function getAndRemoveConfig(str) { if ( str === void 0 ) str = ''; var config = {}; if (str) { str = str .replace(/^('|")/, '') .replace(/('|")$/, '') .replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g, function (m, key, value) { if (key.indexOf(':') === -1) { config[key] = (value && value.replace(/"/g, '')) || true; return ''; } return m; }) .trim(); } return { str: str, config: config }; } function removeDocsifyIgnoreTag(str) { return str .replace(//, '') .replace(/{docsify-ignore}/, '') .replace(//, '') .replace(/{docsify-ignore-all}/, '') .trim(); } /* eslint-disable no-unused-vars */ var INDEXS = {}; var LOCAL_STORAGE = { EXPIRE_KEY: 'docsify.search.expires', INDEX_KEY: 'docsify.search.index', }; function resolveExpireKey(namespace) { return namespace ? ((LOCAL_STORAGE.EXPIRE_KEY) + "/" + namespace) : LOCAL_STORAGE.EXPIRE_KEY; } function resolveIndexKey(namespace) { return namespace ? ((LOCAL_STORAGE.INDEX_KEY) + "/" + namespace) : LOCAL_STORAGE.INDEX_KEY; } function escapeHtml(string) { var entityMap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', }; return String(string).replace(/[&<>"']/g, function (s) { return entityMap[s]; }); } function getAllPaths(router) { var paths = []; Docsify.dom .findAll('.sidebar-nav a:not(.section-link):not([data-nosearch])') .forEach(function (node) { var href = node.href; var originHref = node.getAttribute('href'); var path = router.parse(href).path; if ( path && paths.indexOf(path) === -1 && !Docsify.util.isAbsolutePath(originHref) ) { paths.push(path); } }); return paths; } function getTableData(token) { if (!token.text && token.type === 'table') { token.cells.unshift(token.header); token.text = token.cells .map(function (rows) { return rows.join(' | '); }) .join(' |\n '); } return token.text; } function getListData(token) { if (!token.text && token.type === 'list') { token.text = token.raw; } return token.text; } function saveData(maxAge, expireKey, indexKey) { localStorage.setItem(expireKey, Date.now() + maxAge); localStorage.setItem(indexKey, JSON.stringify(INDEXS)); } function genIndex(path, content, router, depth) { if ( content === void 0 ) content = ''; var tokens = window.marked.lexer(content); var slugify = window.Docsify.slugify; var index = {}; var slug; var title = ''; tokens.forEach(function (token, tokenIndex) { if (token.type === 'heading' && token.depth <= depth) { var ref = getAndRemoveConfig(token.text); var str = ref.str; var config = ref.config; var text = removeDocsifyIgnoreTag(token.text); if (config.id) { slug = router.toURL(path, { id: slugify(config.id) }); } else { slug = router.toURL(path, { id: slugify(escapeHtml(text)) }); } if (str) { title = removeDocsifyIgnoreTag(str); } index[slug] = { slug: slug, title: title, body: '' }; } else { if (tokenIndex === 0) { slug = router.toURL(path); index[slug] = { slug: slug, title: path !== '/' ? path.slice(1) : 'Home Page', body: token.text || '', }; } if (!slug) { return; } if (!index[slug]) { index[slug] = { slug: slug, title: '', body: '' }; } else if (index[slug].body) { token.text = getTableData(token); token.text = getListData(token); index[slug].body += '\n' + (token.text || ''); } else { token.text = getTableData(token); token.text = getListData(token); index[slug].body = token.text || ''; } } }); slugify.clear(); return index; } function ignoreDiacriticalMarks(keyword) { if (keyword && keyword.normalize) { return keyword.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); } return keyword; } /** * @param {String} query Search query * @returns {Array} Array of results */ function search(query) { var matchingResults = []; var data = []; Object.keys(INDEXS).forEach(function (key) { data = data.concat(Object.keys(INDEXS[key]).map(function (page) { return INDEXS[key][page]; })); }); query = query.trim(); var keywords = query.split(/[\s\-,\\/]+/); if (keywords.length !== 1) { keywords = [].concat(query, keywords); } var loop = function ( i ) { var post = data[i]; var matchesScore = 0; var resultStr = ''; var handlePostTitle = ''; var handlePostContent = ''; var postTitle = post.title && post.title.trim(); var postContent = post.body && post.body.trim(); var postUrl = post.slug || ''; if (postTitle) { keywords.forEach(function (keyword) { // From https://github.com/sindresorhus/escape-string-regexp var regEx = new RegExp( escapeHtml(ignoreDiacriticalMarks(keyword)).replace( /[|\\{}()[\]^$+*?.]/g, '\\$&' ), 'gi' ); var indexTitle = -1; var indexContent = -1; handlePostTitle = postTitle ? escapeHtml(ignoreDiacriticalMarks(postTitle)) : postTitle; handlePostContent = postContent ? escapeHtml(ignoreDiacriticalMarks(postContent)) : postContent; indexTitle = postTitle ? handlePostTitle.search(regEx) : -1; indexContent = postContent ? handlePostContent.search(regEx) : -1; if (indexTitle >= 0 || indexContent >= 0) { matchesScore += indexTitle >= 0 ? 3 : indexContent >= 0 ? 2 : 0; if (indexContent < 0) { indexContent = 0; } var start = 0; var end = 0; start = indexContent < 11 ? 0 : indexContent - 10; end = start === 0 ? 70 : indexContent + keyword.length + 60; if (postContent && end > postContent.length) { end = postContent.length; } var matchContent = handlePostContent && '...' + handlePostContent .substring(start, end) .replace( regEx, function (word) { return ("" + word + ""); } ) + '...'; resultStr += matchContent; } }); if (matchesScore > 0) { var matchingPost = { title: handlePostTitle, content: postContent ? resultStr : '', url: postUrl, score: matchesScore, }; matchingResults.push(matchingPost); } } }; for (var i = 0; i < data.length; i++) loop( i ); return matchingResults.sort(function (r1, r2) { return r2.score - r1.score; }); } function init(config, vm) { var isAuto = config.paths === 'auto'; var paths = isAuto ? getAllPaths(vm.router) : config.paths; var namespaceSuffix = ''; // only in auto mode if (paths.length && isAuto && config.pathNamespaces) { var path = paths[0]; if (Array.isArray(config.pathNamespaces)) { namespaceSuffix = config.pathNamespaces.filter( function (prefix) { return path.slice(0, prefix.length) === prefix; } )[0] || namespaceSuffix; } else if (config.pathNamespaces instanceof RegExp) { var matches = path.match(config.pathNamespaces); if (matches) { namespaceSuffix = matches[0]; } } var isExistHome = paths.indexOf(namespaceSuffix + '/') === -1; var isExistReadme = paths.indexOf(namespaceSuffix + '/README') === -1; if (isExistHome && isExistReadme) { paths.unshift(namespaceSuffix + '/'); } } else if (paths.indexOf('/') === -1 && paths.indexOf('/README') === -1) { paths.unshift('/'); } var expireKey = resolveExpireKey(config.namespace) + namespaceSuffix; var indexKey = resolveIndexKey(config.namespace) + namespaceSuffix; var isExpired = localStorage.getItem(expireKey) < Date.now(); INDEXS = JSON.parse(localStorage.getItem(indexKey)); if (isExpired) { INDEXS = {}; } else if (!isAuto) { return; } var len = paths.length; var count = 0; paths.forEach(function (path) { if (INDEXS[path]) { return count++; } Docsify.get(vm.router.getFile(path), false, vm.config.requestHeaders).then( function (result) { INDEXS[path] = genIndex(path, result, vm.router, config.depth); len === ++count && saveData(config.maxAge, expireKey, indexKey); } ); }); } /* eslint-disable no-unused-vars */ var NO_DATA_TEXT = ''; var options; function style() { var code = "\n.sidebar {\n padding-top: 0;\n}\n\n.search {\n margin-bottom: 20px;\n padding: 6px;\n border-bottom: 1px solid #eee;\n}\n\n.search .input-wrap {\n display: flex;\n align-items: center;\n}\n\n.search .results-panel {\n display: none;\n}\n\n.search .results-panel.show {\n display: block;\n}\n\n.search input {\n outline: none;\n border: none;\n width: 100%;\n padding: 0.6em 7px;\n font-size: inherit;\n border: 1px solid transparent;\n}\n\n.search input:focus {\n box-shadow: 0 0 5px var(--theme-color, #42b983);\n border: 1px solid var(--theme-color, #42b983);\n}\n\n.search input::-webkit-search-decoration,\n.search input::-webkit-search-cancel-button,\n.search input {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n\n.search input::-ms-clear {\n display: none;\n height: 0;\n width: 0;\n}\n\n.search .clear-button {\n cursor: pointer;\n width: 36px;\n text-align: right;\n display: none;\n}\n\n.search .clear-button.show {\n display: block;\n}\n\n.search .clear-button svg {\n transform: scale(.5);\n}\n\n.search h2 {\n font-size: 17px;\n margin: 10px 0;\n}\n\n.search a {\n text-decoration: none;\n color: inherit;\n}\n\n.search .matching-post {\n border-bottom: 1px solid #eee;\n}\n\n.search .matching-post:last-child {\n border-bottom: 0;\n}\n\n.search p {\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.search p.empty {\n text-align: center;\n}\n\n.app-name.hide, .sidebar-nav.hide {\n display: none;\n}"; Docsify.dom.style(code); } function tpl(defaultValue) { if ( defaultValue === void 0 ) defaultValue = ''; var html = "
" + NO_DATA_TEXT + "
"); if (options.hideOtherSidebarContent) { $sidebarNav && $sidebarNav.classList.add('hide'); $appName && $appName.classList.add('hide'); } } function bindEvents() { var $search = Docsify.dom.find('div.search'); var $input = Docsify.dom.find($search, 'input'); var $inputWrap = Docsify.dom.find($search, '.input-wrap'); var timeId; /** Prevent to Fold sidebar. When searching on the mobile end, the sidebar is collapsed when you click the INPUT box, making it impossible to search. */ Docsify.dom.on( $search, 'click', function (e) { return ['A', 'H2', 'P', 'EM'].indexOf(e.target.tagName) === -1 && e.stopPropagation(); } ); Docsify.dom.on($input, 'input', function (e) { clearTimeout(timeId); timeId = setTimeout(function (_) { return doSearch(e.target.value.trim()); }, 100); }); Docsify.dom.on($inputWrap, 'click', function (e) { // Click input outside if (e.target.tagName !== 'INPUT') { $input.value = ''; doSearch(); } }); } function updatePlaceholder(text, path) { var $input = Docsify.dom.getNode('.search input[type="search"]'); if (!$input) { return; } if (typeof text === 'string') { $input.placeholder = text; } else { var match = Object.keys(text).filter(function (key) { return path.indexOf(key) > -1; })[0]; $input.placeholder = text[match]; } } function updateNoData(text, path) { if (typeof text === 'string') { NO_DATA_TEXT = text; } else { var match = Object.keys(text).filter(function (key) { return path.indexOf(key) > -1; })[0]; NO_DATA_TEXT = text[match]; } } function updateOptions(opts) { options = opts; } function init$1(opts, vm) { var keywords = vm.router.parse().query.s; updateOptions(opts); style(); tpl(keywords); bindEvents(); keywords && setTimeout(function (_) { return doSearch(keywords); }, 500); } function update(opts, vm) { updateOptions(opts); updatePlaceholder(opts.placeholder, vm.route.path); updateNoData(opts.noData, vm.route.path); } /* eslint-disable no-unused-vars */ var CONFIG = { placeholder: 'Type to search', noData: 'No Results!', paths: 'auto', depth: 2, maxAge: 86400000, // 1 day hideOtherSidebarContent: false, namespace: undefined, pathNamespaces: undefined, }; var install = function (hook, vm) { var util = Docsify.util; var opts = vm.config.search || CONFIG; if (Array.isArray(opts)) { CONFIG.paths = opts; } else if (typeof opts === 'object') { CONFIG.paths = Array.isArray(opts.paths) ? opts.paths : 'auto'; CONFIG.maxAge = util.isPrimitive(opts.maxAge) ? opts.maxAge : CONFIG.maxAge; CONFIG.placeholder = opts.placeholder || CONFIG.placeholder; CONFIG.noData = opts.noData || CONFIG.noData; CONFIG.depth = opts.depth || CONFIG.depth; CONFIG.hideOtherSidebarContent = opts.hideOtherSidebarContent || CONFIG.hideOtherSidebarContent; CONFIG.namespace = opts.namespace || CONFIG.namespace; CONFIG.pathNamespaces = opts.pathNamespaces || CONFIG.pathNamespaces; } var isAuto = CONFIG.paths === 'auto'; hook.mounted(function (_) { init$1(CONFIG, vm); !isAuto && init(CONFIG, vm); }); hook.doneEach(function (_) { update(CONFIG, vm); isAuto && init(CONFIG, vm); }); }; $docsify.plugins = [].concat(install, $docsify.plugins); }());