(pad:PadType, atext: AText, authorColors?: string[])
| 44 | }; |
| 45 | |
| 46 | const getHTMLFromAtext = async (pad:PadType, atext: AText, authorColors?: string[]) => { |
| 47 | const apool = pad.apool(); |
| 48 | const textLines = atext.text.slice(0, -1).split('\n'); |
| 49 | const attribLines = splitAttributionLines(atext.attribs, atext.text); |
| 50 | |
| 51 | const tags = ['h1', 'h2', 'strong', 'em', 'u', 's']; |
| 52 | const props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough']; |
| 53 | |
| 54 | await Promise.all([ |
| 55 | // prepare tags stored as ['tag', true] to be exported |
| 56 | hooks.aCallAll('exportHtmlAdditionalTags', pad).then((newProps: string[]) => { |
| 57 | newProps.forEach((prop) => { |
| 58 | tags.push(prop); |
| 59 | props.push(prop); |
| 60 | }); |
| 61 | }), |
| 62 | // prepare tags stored as ['tag', 'value'] to be exported. This will generate HTML with tags |
| 63 | // like <span data-tag="value"> |
| 64 | hooks.aCallAll('exportHtmlAdditionalTagsWithData', pad).then((newProps: string[]) => { |
| 65 | newProps.forEach((prop) => { |
| 66 | // Attribute names/values here originate from the pad's attribute pool |
| 67 | // (user content), so escape the value and constrain the data-* name |
| 68 | // before interpolating, consistent with the escaping already applied to |
| 69 | // exported URLs and text below. |
| 70 | const dataName = String(prop[0]).replace(/[^a-zA-Z0-9_-]/g, ''); |
| 71 | tags.push(`span data-${dataName}="${Security.escapeHTMLAttribute(String(prop[1]))}"`); |
| 72 | props.push(prop); |
| 73 | }); |
| 74 | }), |
| 75 | ]); |
| 76 | |
| 77 | // holds a map of used styling attributes (*1, *2, etc) in the apool |
| 78 | // and maps them to an index in props |
| 79 | // *3:2 -> the attribute *3 means strong |
| 80 | // *2:5 -> the attribute *2 means s(trikethrough) |
| 81 | const anumMap:MapArrayType<number> = {}; |
| 82 | let css = ''; |
| 83 | |
| 84 | const stripDotFromAuthorID = (id: string) => id.replace(/\./g, '_'); |
| 85 | |
| 86 | if (authorColors) { |
| 87 | css += '<style>\n'; |
| 88 | |
| 89 | for (const a of Object.keys(apool.numToAttrib)) { |
| 90 | // @ts-ignore |
| 91 | const attr = apool.numToAttrib[a]; |
| 92 | |
| 93 | // skip non author attributes |
| 94 | if (attr[0] === 'author' && attr[1] !== '') { |
| 95 | // add to props array |
| 96 | const propName = `author${stripDotFromAuthorID(attr[1])}`; |
| 97 | const newLength = props.push(propName); |
| 98 | anumMap[a] = newLength - 1; |
| 99 | |
| 100 | css += `.${propName} {background-color: ${authorColors[attr[1]]}}\n`; |
| 101 | } else if (attr[0] === 'removed') { |
| 102 | const propName = 'removed'; |
| 103 | const newLength = props.push(propName); |
no test coverage detected