GitHub Repository: sagemathinc/cocalc
Views: 178
(IconFonts not available)
Path: blob/master/src/packages/frontend/markdown/checkbox-plugin.tsViews: 178
/*1* LICENSE: MIT (same as upstream)2*/34// This code is inspired by https://github.com/mcecot/markdown-it-checkbox56// However it is meant to behave much like Github, in terms of parsing.78function checkboxReplace(_md, _options) {9let index = 0;10const pattern = /\[(X|\s)\](.*)/i;11function createTokens(12checked: boolean,13before: string,14after: string,15Token16) {17// before <input type="checkbox" data-index="{n}" checked="true"> after18const checkbox_token = new Token("checkbox_input", "input", 0);19checkbox_token.attrs = [20[21"style",22"margin: 0 0.2em 0.2em 0.2em; transform: scale(1.5); vertical-align: middle;",23],24["type", "checkbox"],25["data-index", `${index}`],26[27"disabled",28"true",29] /* disabled: anything in cocalc that is just directly30rendering this doesn't know how to change it.*/,31];32if (checked) {33checkbox_token.attrs.push(["checked", "true"]);34checkbox_token.checked = checked;35}3637const before_token = new Token("text", "", 0);38before_token.content = before;3940const after_token = new Token("text", "", 0);41after_token.content = after;42index += 1;43return [before_token, checkbox_token, after_token];44}4546function splitTextToken(original, Token) {47if (original.markup != "") return null; // don't make checkboxes, e.g., inside of `code` like `R[x]`.48const text = original.content;49const match = text.match(pattern);50if (match === null) {51return null;52}53const before = text.slice(0, match.index);54const value = match[1];55const checked = value === "X" || value === "x";56const after = match[2];57return createTokens(checked, before, after, Token);58}5960return (state) => {61for (const token of state.tokens) {62if (token.type !== "inline") {63// fenced blocks, etc., should be ignored of course.64continue;65}66// Process all the children, setting has_checkboxes67// to true if any are found.68let has_checkboxes: boolean = false;69const v: any[] = [];70for (const child of token.children) {71const x = splitTextToken(child, state.Token);72if (x != null) {73has_checkboxes = true;74v.push(x);75} else {76v.push([child]);77}78}7980if (has_checkboxes) {81// Found at least one checkbox, so replace children. See82// https://stackoverflow.com/questions/5080028/what-is-the-most-efficient-way-to-concatenate-n-arrays83// for why we concat arrays this way.84token.children = [].concat.apply([], v);85}86}87};88}8990export function checkboxPlugin(md, options) {91md.core.ruler.push("checkbox", checkboxReplace(md, options));92}939495