All files / src utils.ts

100% Statements 16/16
100% Branches 8/8
100% Functions 3/3
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 506x 6x     121x 121x 3872x   121x                     31x 31x                                               11x 10x 5x 3x    
const NONCE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const NONCE_LENGTH = 32;
 
export function getNonce(): string {
  let text = '';
  for (let i = 0; i < NONCE_LENGTH; i++) {
    text += NONCE_CHARS.charAt(Math.floor(Math.random() * NONCE_CHARS.length));
  }
  return text;
}
 
export interface HtmlTemplateParams {
  cspSource: string;
  nonce: string;
  scriptUri: string;
  cssUri: string;
}
 
export function buildPreviewHtml(params: HtmlTemplateParams): string {
  const { cspSource, nonce, scriptUri, cssUri } = params;
  return `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="Content-Security-Policy" content="
    default-src 'none';
    img-src ${cspSource} https: data: blob:;
    media-src ${cspSource} https: blob:;
    script-src ${cspSource} 'nonce-${nonce}' 'unsafe-eval';
    style-src ${cspSource} 'unsafe-inline';
    font-src ${cspSource} https: data:;
  ">
  <link rel="stylesheet" href="${cssUri}">
  <title>Markdown Preview</title>
</head>
<body>
  <div id="root"></div>
  <script nonce="${nonce}" type="module" src="${scriptUri}"></script>
</body>
</html>`;
}
 
export function resolveImageSrc(src: string, baseUri: string): string {
  if (!src) return src;
  if (src.startsWith('http') || src.startsWith('data:')) return src;
  if (!baseUri) return src;
  return `${baseUri}/${src}`;
}