-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy path_codeBlock.ts
More file actions
69 lines (66 loc) · 2.34 KB
/
_codeBlock.ts
File metadata and controls
69 lines (66 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import type { TinyCodeBlock } from "../rest/getCodeBlocks.ts";
/** Interface for storing code block title line information
*
* In Scrapbox, code blocks start with a title line that defines:
* - The code's filename or language identifier
* - Optional language specification in parentheses
* - Indentation level for nested blocks
*/
export interface CodeTitle {
filename: string;
lang: string;
indent: number;
}
/** Extract properties from a code block title line
*
* This function parses a line of text to determine if it's a valid code block title.
* Valid formats include:
* - `code:filename.ext` - Language determined by extension
* - `code:filename(lang)` - Explicit language specification
* - `code:lang` - Direct language specification without filename
*
* @param lineText - The line text to parse
* @returns A {@linkcode CodeTitle} | {@linkcode null}:
* - Success: A {@linkcode CodeTitle} object containing filename and language info
* - Error: {@linkcode null} if the line is not a valid code block title
* and indentation level.
*/
export const extractFromCodeTitle = (lineText: string): CodeTitle | null => {
const matched = lineText.match(/^(\s*)code:(.+?)(\(.+\)){0,1}\s*$/);
if (matched === null) return null;
const filename = matched[2].trim();
let lang = "";
if (matched[3] === undefined) {
const ext = filename.match(/.+\.(.*)$/);
if (ext === null) {
// `code:ext`
lang = filename;
} else if (ext[1] === "") {
// Reject "code:foo." format as it's invalid (trailing dot without extension)
// This ensures code blocks have either a valid extension or no extension at all
return null;
} else {
// `code:foo.ext`
lang = ext[1].trim();
}
} else {
lang = matched[3].slice(1, -1);
}
return {
filename: filename,
lang: lang,
indent: matched[1].length,
};
};
/** Calculate the indentation level for code block content
*
* The content of a code block is indented one level deeper than its title line.
* This function determines the correct indentation by analyzing the title line's
* whitespace and adding one additional level.
*/
export function countBodyIndent(
codeBlock: Pick<TinyCodeBlock, "titleLine">,
): number {
return codeBlock.titleLine.text.length -
codeBlock.titleLine.text.trimStart().length + 1;
}