go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/tools/markdown/plugins/bug_line.ts (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import MarkdownIt from 'markdown-it'; 16 import Token from 'markdown-it/lib/token'; 17 18 import { specialLine } from './special_line'; 19 20 /** 21 * Replace text tokens with bug links. 22 */ 23 function processToken(srcToken: Token): Token[] { 24 const reBug = /\b([-_a-zA-Z0-9]+:)?#?\d+\b/g; 25 let pos = 0; 26 let match = reBug.exec(srcToken.content); 27 const newTokens: Token[] = []; 28 let token: Token; 29 while (match) { 30 const bugStr = match[0]; 31 32 // Insert the text between the last processed character and the first 33 // character of the new match as a text node. 34 if (match.index !== pos) { 35 token = new Token('text', '', 0); 36 token.content = srcToken.content.slice(pos, match.index); 37 newTokens.push(token); 38 pos = match.index; 39 } 40 41 // Insert the bug link nodes. 42 token = new Token('link_open', 'a', 1); 43 token.attrs = [ 44 [ 45 'href', 46 `https://crbug.com/${bugStr.replace('#', '').replace(':', '/')}`, 47 ], 48 ]; 49 token.level = srcToken.level; 50 newTokens.push(token); 51 52 token = new Token('text', '', 0); 53 token.content = bugStr; 54 token.level = srcToken.level + 1; 55 pos += bugStr.length; 56 newTokens.push(token); 57 58 token = new Token('link_close', 'a', -1); 59 token.level = srcToken.level; 60 newTokens.push(token); 61 62 match = reBug.exec(srcToken.content); 63 } 64 65 // If there are remaining unprocessed characters, add them as a text node. 66 if (pos !== srcToken.content.length) { 67 token = new Token('text', '', 0); 68 token.content = srcToken.content.slice(pos); 69 newTokens.push(token); 70 } 71 72 return newTokens; 73 } 74 75 /** 76 * Support converting bug identifiers (e.g. 'proj/123', '234') in bug lines 77 * (e.g. 'Bugs: proj/123, 234', 'BUG=345') to crbug links. 78 * 79 * For instance 80 * ``` 81 * Bug: 123, proj/234 82 * ``` 83 * will be converted to 84 * ```html 85 * <p>Bug: 86 * <a href="https://crbug.com/123">123</a> 87 * <a href="https://crbug.com/proj/234">proj/234</a> 88 * </p> 89 * ``` 90 */ 91 export function bugLine(md: MarkdownIt) { 92 md.use(specialLine, /^(>| )*(bugs?)[:=]/i, processToken); 93 }