|
4 | 4 | removeAtag, |
5 | 5 | escapeHtml, |
6 | 6 | } from '../../core/render/utils.js'; |
| 7 | +import { getPath, getParentPath, isAbsolutePath } from '../../core/router/util.js'; |
7 | 8 | import { markdownToTxt } from './markdown-to-txt.js'; |
8 | 9 | import Dexie from 'dexie'; |
9 | 10 |
|
@@ -115,6 +116,104 @@ function getListData(token) { |
115 | 116 | return token.text; |
116 | 117 | } |
117 | 118 |
|
| 119 | +function extractFragmentContent(text, fragment, fullLine) { |
| 120 | + if (!fragment) { |
| 121 | + return text; |
| 122 | + } |
| 123 | + |
| 124 | + let fragmentRegex = `(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`; |
| 125 | + if (fullLine) { |
| 126 | + fragmentRegex = `.*${fragmentRegex}.*\n`; |
| 127 | + } |
| 128 | + |
| 129 | + const pattern = new RegExp(`(?:${fragmentRegex})([\\s\\S]*?)(?:${fragmentRegex})`); |
| 130 | + const match = text.match(pattern); |
| 131 | + return ((match || [])[1] || '').trim(); |
| 132 | +} |
| 133 | + |
| 134 | +function collectEmbedRequests(raw = '', path, vm) { |
| 135 | + const tokens = window.marked.lexer(raw); |
| 136 | + const requests = []; |
| 137 | + |
| 138 | + const maybePushEmbed = inlineToken => { |
| 139 | + if (!inlineToken || (inlineToken.type !== 'link' && inlineToken.type !== 'image')) { |
| 140 | + return; |
| 141 | + } |
| 142 | + |
| 143 | + const { config } = getAndRemoveConfig(inlineToken.title || ''); |
| 144 | + if (!config.include || !inlineToken.href) { |
| 145 | + return; |
| 146 | + } |
| 147 | + |
| 148 | + const href = isAbsolutePath(inlineToken.href) |
| 149 | + ? inlineToken.href |
| 150 | + : getPath(vm.router.getBasePath(), getParentPath(path), inlineToken.href); |
| 151 | + |
| 152 | + let type = 'code'; |
| 153 | + if (/\.(md|markdown)/.test(href)) { |
| 154 | + type = 'markdown'; |
| 155 | + } else if (/\.mmd/.test(href)) { |
| 156 | + type = 'mermaid'; |
| 157 | + } |
| 158 | + |
| 159 | + requests.push({ |
| 160 | + url: href, |
| 161 | + type, |
| 162 | + fragment: config.fragment, |
| 163 | + omitFragmentLine: config.omitFragmentLine, |
| 164 | + }); |
| 165 | + }; |
| 166 | + |
| 167 | + tokens.forEach(token => { |
| 168 | + if (token.type === 'paragraph') { |
| 169 | + (token.tokens || []).forEach(maybePushEmbed); |
| 170 | + } else if (token.type === 'table') { |
| 171 | + (token.header || []).forEach(cell => { |
| 172 | + (cell.tokens || []).forEach(maybePushEmbed); |
| 173 | + }); |
| 174 | + (token.rows || []).forEach(row => { |
| 175 | + row.forEach(cell => { |
| 176 | + (cell.tokens || []).forEach(maybePushEmbed); |
| 177 | + }); |
| 178 | + }); |
| 179 | + } |
| 180 | + }); |
| 181 | + |
| 182 | + return requests; |
| 183 | +} |
| 184 | + |
| 185 | +async function getEmbeddedContent(raw = '', path, vm) { |
| 186 | + const requests = collectEmbedRequests(raw, path, vm); |
| 187 | + if (!requests.length) { |
| 188 | + return ''; |
| 189 | + } |
| 190 | + |
| 191 | + const results = await Promise.all( |
| 192 | + requests.map( |
| 193 | + request => |
| 194 | + new Promise(resolve => { |
| 195 | + Docsify.get(request.url, false, vm.config.requestHeaders).then( |
| 196 | + text => { |
| 197 | + let content = text || ''; |
| 198 | + if (request.fragment) { |
| 199 | + content = extractFragmentContent( |
| 200 | + content, |
| 201 | + request.fragment, |
| 202 | + request.omitFragmentLine, |
| 203 | + ); |
| 204 | + } |
| 205 | + |
| 206 | + resolve(request.type === 'markdown' ? content : markdownToTxt(content)); |
| 207 | + }, |
| 208 | + () => resolve(''), |
| 209 | + ); |
| 210 | + }), |
| 211 | + ), |
| 212 | + ); |
| 213 | + |
| 214 | + return results.filter(Boolean).join('\n'); |
| 215 | +} |
| 216 | + |
118 | 217 | export function genIndex(path, content = '', router, depth, indexKey) { |
119 | 218 | const tokens = window.marked.lexer(content); |
120 | 219 | const slugify = window.Docsify.slugify; |
@@ -224,29 +323,24 @@ export function search(query) { |
224 | 323 | ), |
225 | 324 | 'gi', |
226 | 325 | ); |
227 | | - let indexTitle = -1; |
228 | | - let indexContent = -1; |
229 | 326 | handlePostTitle = postTitle |
230 | 327 | ? escapeHtml(ignoreDiacriticalMarks(postTitle)) |
231 | 328 | : postTitle; |
232 | 329 | handlePostContent = postContent |
233 | 330 | ? escapeHtml(ignoreDiacriticalMarks(postContent)) |
234 | 331 | : postContent; |
235 | 332 |
|
236 | | - indexTitle = postTitle ? handlePostTitle.search(regEx) : -1; |
237 | | - indexContent = postContent ? handlePostContent.search(regEx) : -1; |
| 333 | + const indexTitle = postTitle ? handlePostTitle.search(regEx) : -1; |
| 334 | + let indexContent = postContent ? handlePostContent.search(regEx) : -1; |
238 | 335 |
|
239 | 336 | if (indexTitle >= 0 || indexContent >= 0) { |
240 | 337 | matchesScore += indexTitle >= 0 ? 3 : indexContent >= 0 ? 2 : 0; |
241 | 338 | if (indexContent < 0) { |
242 | 339 | indexContent = 0; |
243 | 340 | } |
244 | 341 |
|
245 | | - let start = 0; |
246 | | - let end = 0; |
247 | | - |
248 | | - start = indexContent < 11 ? 0 : indexContent - 10; |
249 | | - end = start === 0 ? 100 : indexContent + keyword.length + 90; |
| 342 | + const start = indexContent < 11 ? 0 : indexContent - 10; |
| 343 | + let end = start === 0 ? 100 : indexContent + keyword.length + 90; |
250 | 344 |
|
251 | 345 | if (handlePostContent && end > handlePostContent.length) { |
252 | 346 | end = handlePostContent.length; |
@@ -341,10 +435,14 @@ export async function init(config, vm) { |
341 | 435 | } |
342 | 436 |
|
343 | 437 | Docsify.get(vm.router.getFile(path), false, vm.config.requestHeaders).then( |
344 | | - result => { |
| 438 | + async result => { |
| 439 | + const embeddedContent = await getEmbeddedContent(result, path, vm); |
| 440 | + const contentToIndex = embeddedContent |
| 441 | + ? `${result}\n${embeddedContent}` |
| 442 | + : result; |
345 | 443 | INDEXES[path] = genIndex( |
346 | 444 | path, |
347 | | - result, |
| 445 | + contentToIndex, |
348 | 446 | vm.router, |
349 | 447 | config.depth, |
350 | 448 | indexKey, |
|
0 commit comments