diff --git a/README.md b/README.md index 9941d52..844603a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In release, you can find a .deb or a ubuntu gzipped file. ## Usage -Export a json of your proposal: +Export a json of your proposal: ![export json on conference-hall.io](assets/export-json.png) @@ -44,6 +44,7 @@ Options: -t, --titlelength the title length (default: 100) -w, --links view links -x, --export export into tsv file + -r, --render render on a webpage (default: false) -h, --help display help for command ``` diff --git a/bun.lockb b/bun.lockb index 98fa341..7c7d431 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 2335b62..dd9a77d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "choc", - "version": "0.1.6", + "version": "0.1.7", "module": "src/index.ts", "type": "module", "devDependencies": { diff --git a/src/choc.ts b/src/choc.ts index b6f3a22..6fb7cae 100644 --- a/src/choc.ts +++ b/src/choc.ts @@ -1,4 +1,5 @@ import { DTO, DTOExport } from "./DTO"; +import render from "./render"; import type { Format, Options, @@ -10,44 +11,51 @@ import type { import { removeEmojis } from "./utils"; const choc = async (file: string, options: Options) => { - const { talks, speakers, formats, categories } = await Bun.file(file).json(); - const formatsHash = new Map(); - (formats as Format[]).forEach(({ id, name }) => { - formatsHash.set(id, removeEmojis(name)); - }); - const speakerHash = new Map(); - (speakers as Speaker[]).forEach(({ uid, displayName, company, address }) => { - speakerHash.set(uid, { - name: removeEmojis(displayName), - company: removeEmojis(company ?? ""), - address: removeEmojis(address?.formattedAddress ?? ""), + const json = await Bun.file(file).json(); + if (options.render) { + render(json, options); + } else { + const { talks, speakers, formats, categories } = json; + const formatsHash = new Map(); + (formats as Format[]).forEach(({ id, name }) => { + formatsHash.set(id, removeEmojis(name)); }); - }); - const categoriesHash = new Map(); - (categories as Format[]).forEach(({ id, name }) => { - categoriesHash.set(id, removeEmojis(name)); - }); - const talksLines = (talks as Talk[]).sort((a, b) => - a.rating <= b.rating ? 1 : -1 - ); - if (options.export) { - const exportLines = DTOExport( - talksLines, - options, - speakerHash, - formatsHash, - categoriesHash + const speakerHash = new Map(); + (speakers as Speaker[]).forEach( + ({ uid, displayName, company, address }) => { + speakerHash.set(uid, { + name: removeEmojis(displayName), + company: removeEmojis(company ?? ""), + address: removeEmojis(address?.formattedAddress ?? ""), + }); + } ); - Bun.write( - options.export, - `${Object.keys(exportLines[0]).join("\t")}\n${exportLines - .map((t: TalkRow) => Object.values(t).join("\t")) - .join("\n")}` - ); - } else - console.table( - DTO(talksLines, options, speakerHash, formatsHash, categoriesHash) + const categoriesHash = new Map(); + (categories as Format[]).forEach(({ id, name }) => { + categoriesHash.set(id, removeEmojis(name)); + }); + const talksLines = (talks as Talk[]).sort((a, b) => + a.rating <= b.rating ? 1 : -1 ); + if (options.export) { + const exportLines = DTOExport( + talksLines, + options, + speakerHash, + formatsHash, + categoriesHash + ); + Bun.write( + options.export, + `${Object.keys(exportLines[0]).join("\t")}\n${exportLines + .map((t: TalkRow) => Object.values(t).join("\t")) + .join("\n")}` + ); + } else + console.table( + DTO(talksLines, options, speakerHash, formatsHash, categoriesHash) + ); + } }; export default choc; diff --git a/src/index.ts b/src/index.ts index 3b72aec..20859ad 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,7 @@ program .option("-t, --titlelength ", "the title length", myParseInt, 100) .option("-w, --links ", "view links") .option("-x, --export ", "export into tsv file") + .option("-r, --render", "render on a webpage", false) .action(choc); program.parse(); diff --git a/src/render.ts b/src/render.ts new file mode 100644 index 0000000..67097d9 --- /dev/null +++ b/src/render.ts @@ -0,0 +1,41 @@ +import html from "./render/index.html.txt"; +import js from "./render/main.js.txt"; +import css from "./render/main.css.txt"; +import type { Options } from "./types"; + +export const render = (json: JSON, options?: Options) => { + const server = Bun.serve({ + port: 1337, + async fetch(req) { + const path = new URL(req.url).pathname; + if (path === "/main.css") + return new Response(css, { + headers: { "content-type": "text/css" }, + }); + if (path === "/main.js") + return new Response( + ` + const exportJSON = ${JSON.stringify(json).replaceAll("\n", "
")} + const options = ${JSON.stringify(options)}; + ${js} + `.trim(), + { + headers: { + "Content-Type": "application/javascript", + }, + status: 200, + } + ); + return new Response(html, { + headers: { + "Content-Type": "text/html", + }, + status: 200, + }); + }, + }); + + console.log("๐Ÿซ is listening on \x1b[1m\x1b[35;49m%s\x1b[0m", server.url); +}; + +export default render; diff --git a/src/render/index.html.txt b/src/render/index.html.txt new file mode 100644 index 0000000..186b90d --- /dev/null +++ b/src/render/index.html.txt @@ -0,0 +1,41 @@ + + + + + + + + + CHoC + + + +
+

+ +

Talks

+
+
+ + + diff --git a/src/render/libs/picocss.min.css.txt b/src/render/libs/picocss.min.css.txt new file mode 100644 index 0000000..dc2f980 --- /dev/null +++ b/src/render/libs/picocss.min.css.txt @@ -0,0 +1,3026 @@ +@charset "UTF-8"; /*! + * Pico CSS โœจ v2.0.6 (https://picocss.com) + * Copyright 2019-2024 - Licensed under MIT + */ +:root { + --pico-font-family-emoji: "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji"; + --pico-font-family-sans-serif: system-ui, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, Helvetica, Arial, "Helvetica Neue", sans-serif, + var(--pico-font-family-emoji); + --pico-font-family-monospace: ui-monospace, SFMono-Regular, "SF Mono", Menlo, + Consolas, "Liberation Mono", monospace, var(--pico-font-family-emoji); + --pico-font-family: var(--pico-font-family-sans-serif); + --pico-line-height: 1.5; + --pico-font-weight: 400; + --pico-font-size: 100%; + --pico-text-underline-offset: 0.1rem; + --pico-border-radius: 0.25rem; + --pico-border-width: 0.0625rem; + --pico-outline-width: 0.125rem; + --pico-transition: 0.2s ease-in-out; + --pico-spacing: 1rem; + --pico-typography-spacing-vertical: 1rem; + --pico-block-spacing-vertical: var(--pico-spacing); + --pico-block-spacing-horizontal: var(--pico-spacing); + --pico-grid-column-gap: var(--pico-spacing); + --pico-grid-row-gap: var(--pico-spacing); + --pico-form-element-spacing-vertical: 0.75rem; + --pico-form-element-spacing-horizontal: 1rem; + --pico-group-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) + var(--pico-primary-focus); + --pico-group-box-shadow-focus-with-input: 0 0 0 0.0625rem + var(--pico-form-element-border-color); + --pico-modal-overlay-backdrop-filter: blur(0.375rem); + --pico-nav-element-spacing-vertical: 1rem; + --pico-nav-element-spacing-horizontal: 0.5rem; + --pico-nav-link-spacing-vertical: 0.5rem; + --pico-nav-link-spacing-horizontal: 0.5rem; + --pico-nav-breadcrumb-divider: ">"; + --pico-icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --pico-icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E"); + --pico-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + --pico-icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); + --pico-icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E"); + --pico-icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); + --pico-icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E"); + --pico-icon-loading: url("data:image/svg+xml,%3Csvg fill='none' height='24' width='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' %3E%3Cstyle%3E g %7B animation: rotate 2s linear infinite; transform-origin: center center; %7D circle %7B stroke-dasharray: 75,100; stroke-dashoffset: -5; animation: dash 1.5s ease-in-out infinite; stroke-linecap: round; %7D @keyframes rotate %7B 0%25 %7B transform: rotate(0deg); %7D 100%25 %7B transform: rotate(360deg); %7D %7D @keyframes dash %7B 0%25 %7B stroke-dasharray: 1,100; stroke-dashoffset: 0; %7D 50%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -17.5; %7D 100%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -62; %7D %7D %3C/style%3E%3Cg%3E%3Ccircle cx='12' cy='12' r='10' fill='none' stroke='rgb(136, 145, 164)' stroke-width='4' /%3E%3C/g%3E%3C/svg%3E"); +} +@media (min-width: 576px) { + :root { + --pico-font-size: 106.25%; + } +} +@media (min-width: 768px) { + :root { + --pico-font-size: 112.5%; + } +} +@media (min-width: 1024px) { + :root { + --pico-font-size: 118.75%; + } +} +@media (min-width: 1280px) { + :root { + --pico-font-size: 125%; + } +} +@media (min-width: 1536px) { + :root { + --pico-font-size: 131.25%; + } +} +a { + --pico-text-decoration: underline; +} +a.contrast, +a.secondary { + --pico-text-decoration: underline; +} +small { + --pico-font-size: 0.875em; +} +h1, +h2, +h3, +h4, +h5, +h6 { + --pico-font-weight: 700; +} +h1 { + --pico-font-size: 2rem; + --pico-line-height: 1.125; + --pico-typography-spacing-top: 3rem; +} +h2 { + --pico-font-size: 1.75rem; + --pico-line-height: 1.15; + --pico-typography-spacing-top: 2.625rem; +} +h3 { + --pico-font-size: 1.5rem; + --pico-line-height: 1.175; + --pico-typography-spacing-top: 2.25rem; +} +h4 { + --pico-font-size: 1.25rem; + --pico-line-height: 1.2; + --pico-typography-spacing-top: 1.874rem; +} +h5 { + --pico-font-size: 1.125rem; + --pico-line-height: 1.225; + --pico-typography-spacing-top: 1.6875rem; +} +h6 { + --pico-font-size: 1rem; + --pico-line-height: 1.25; + --pico-typography-spacing-top: 1.5rem; +} +tfoot td, +tfoot th, +thead td, +thead th { + --pico-font-weight: 600; + --pico-border-width: 0.1875rem; +} +code, +kbd, +pre, +samp { + --pico-font-family: var(--pico-font-family-monospace); +} +kbd { + --pico-font-weight: bolder; +} +:where(select, textarea), +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ) { + --pico-outline-width: 0.0625rem; +} +[type="search"] { + --pico-border-radius: 5rem; +} +[type="checkbox"], +[type="radio"] { + --pico-border-width: 0.125rem; +} +[type="checkbox"][role="switch"] { + --pico-border-width: 0.1875rem; +} +details.dropdown summary:not([role="button"]) { + --pico-outline-width: 0.0625rem; +} +nav details.dropdown summary:focus-visible { + --pico-outline-width: 0.125rem; +} +[role="search"] { + --pico-border-radius: 5rem; +} +[role="group"]:has( + button.secondary:focus, + [type="submit"].secondary:focus, + [type="button"].secondary:focus, + [role="button"].secondary:focus + ), +[role="search"]:has( + button.secondary:focus, + [type="submit"].secondary:focus, + [type="button"].secondary:focus, + [role="button"].secondary:focus + ) { + --pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) + var(--pico-secondary-focus); +} +[role="group"]:has( + button.contrast:focus, + [type="submit"].contrast:focus, + [type="button"].contrast:focus, + [role="button"].contrast:focus + ), +[role="search"]:has( + button.contrast:focus, + [type="submit"].contrast:focus, + [type="button"].contrast:focus, + [role="button"].contrast:focus + ) { + --pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) + var(--pico-contrast-focus); +} +[role="group"] [role="button"], +[role="group"] [type="button"], +[role="group"] [type="submit"], +[role="group"] button, +[role="search"] [role="button"], +[role="search"] [type="button"], +[role="search"] [type="submit"], +[role="search"] button { + --pico-form-element-spacing-horizontal: 2rem; +} +details summary[role="button"]:not(.outline)::after { + filter: brightness(0) invert(1); +} +[aria-busy="true"]:not(input, select, textarea):is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ):not(.outline)::before { + filter: brightness(0) invert(1); +} +:root:not([data-theme="dark"]), +[data-theme="light"] { + --pico-background-color: #fff; + --pico-color: #373c44; + --pico-text-selection-color: rgba(2, 154, 232, 0.25); + --pico-muted-color: #646b79; + --pico-muted-border-color: #e7eaf0; + --pico-primary: #0172ad; + --pico-primary-background: #0172ad; + --pico-primary-border: var(--pico-primary-background); + --pico-primary-underline: rgba(1, 114, 173, 0.5); + --pico-primary-hover: #015887; + --pico-primary-hover-background: #02659a; + --pico-primary-hover-border: var(--pico-primary-hover-background); + --pico-primary-hover-underline: var(--pico-primary-hover); + --pico-primary-focus: rgba(2, 154, 232, 0.5); + --pico-primary-inverse: #fff; + --pico-secondary: #5d6b89; + --pico-secondary-background: #525f7a; + --pico-secondary-border: var(--pico-secondary-background); + --pico-secondary-underline: rgba(93, 107, 137, 0.5); + --pico-secondary-hover: #48536b; + --pico-secondary-hover-background: #48536b; + --pico-secondary-hover-border: var(--pico-secondary-hover-background); + --pico-secondary-hover-underline: var(--pico-secondary-hover); + --pico-secondary-focus: rgba(93, 107, 137, 0.25); + --pico-secondary-inverse: #fff; + --pico-contrast: #181c25; + --pico-contrast-background: #181c25; + --pico-contrast-border: var(--pico-contrast-background); + --pico-contrast-underline: rgba(24, 28, 37, 0.5); + --pico-contrast-hover: #000; + --pico-contrast-hover-background: #000; + --pico-contrast-hover-border: var(--pico-contrast-hover-background); + --pico-contrast-hover-underline: var(--pico-secondary-hover); + --pico-contrast-focus: rgba(93, 107, 137, 0.25); + --pico-contrast-inverse: #fff; + --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(129, 145, 181, 0.01698), + 0.0335rem 0.067rem 0.402rem rgba(129, 145, 181, 0.024), + 0.0625rem 0.125rem 0.75rem rgba(129, 145, 181, 0.03), + 0.1125rem 0.225rem 1.35rem rgba(129, 145, 181, 0.036), + 0.2085rem 0.417rem 2.502rem rgba(129, 145, 181, 0.04302), + 0.5rem 1rem 6rem rgba(129, 145, 181, 0.06), + 0 0 0 0.0625rem rgba(129, 145, 181, 0.015); + --pico-h1-color: #2d3138; + --pico-h2-color: #373c44; + --pico-h3-color: #424751; + --pico-h4-color: #4d535e; + --pico-h5-color: #5c6370; + --pico-h6-color: #646b79; + --pico-mark-background-color: #fde7c0; + --pico-mark-color: #0f1114; + --pico-ins-color: #1d6a54; + --pico-del-color: #883935; + --pico-blockquote-border-color: var(--pico-muted-border-color); + --pico-blockquote-footer-color: var(--pico-muted-color); + --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-table-border-color: var(--pico-muted-border-color); + --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375); + --pico-code-background-color: #f3f5f7; + --pico-code-color: #646b79; + --pico-code-kbd-background-color: var(--pico-color); + --pico-code-kbd-color: var(--pico-background-color); + --pico-form-element-background-color: #fbfcfc; + --pico-form-element-selected-background-color: #dfe3eb; + --pico-form-element-border-color: #cfd5e2; + --pico-form-element-color: #23262c; + --pico-form-element-placeholder-color: var(--pico-muted-color); + --pico-form-element-active-background-color: #fff; + --pico-form-element-active-border-color: var(--pico-primary-border); + --pico-form-element-focus-color: var(--pico-primary-border); + --pico-form-element-disabled-opacity: 0.5; + --pico-form-element-invalid-border-color: #b86a6b; + --pico-form-element-invalid-active-border-color: #c84f48; + --pico-form-element-invalid-focus-color: var( + --pico-form-element-invalid-active-border-color + ); + --pico-form-element-valid-border-color: #4c9b8a; + --pico-form-element-valid-active-border-color: #279977; + --pico-form-element-valid-focus-color: var( + --pico-form-element-valid-active-border-color + ); + --pico-switch-background-color: #bfc7d9; + --pico-switch-checked-background-color: var(--pico-primary-background); + --pico-switch-color: #fff; + --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-range-border-color: #dfe3eb; + --pico-range-active-border-color: #bfc7d9; + --pico-range-thumb-border-color: var(--pico-background-color); + --pico-range-thumb-color: var(--pico-secondary-background); + --pico-range-thumb-active-color: var(--pico-primary-background); + --pico-accordion-border-color: var(--pico-muted-border-color); + --pico-accordion-active-summary-color: var(--pico-primary-hover); + --pico-accordion-close-summary-color: var(--pico-color); + --pico-accordion-open-summary-color: var(--pico-muted-color); + --pico-card-background-color: var(--pico-background-color); + --pico-card-border-color: var(--pico-muted-border-color); + --pico-card-box-shadow: var(--pico-box-shadow); + --pico-card-sectioning-background-color: #fbfcfc; + --pico-dropdown-background-color: #fff; + --pico-dropdown-border-color: #eff1f4; + --pico-dropdown-box-shadow: var(--pico-box-shadow); + --pico-dropdown-color: var(--pico-color); + --pico-dropdown-hover-background-color: #eff1f4; + --pico-loading-spinner-opacity: 0.5; + --pico-modal-overlay-background-color: rgba(232, 234, 237, 0.75); + --pico-progress-background-color: #dfe3eb; + --pico-progress-color: var(--pico-primary-background); + --pico-tooltip-background-color: var(--pico-contrast-background); + --pico-tooltip-color: var(--pico-contrast-inverse); + --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(76, 155, 138)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(200, 79, 72)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); + color-scheme: light; +} +:root:not([data-theme="dark"]) + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ), +[data-theme="light"] + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ) { + --pico-form-element-focus-color: var(--pico-primary-focus); +} +@media only screen and (prefers-color-scheme: dark) { + :root:not([data-theme]) { + --pico-background-color: #13171f; + --pico-color: #c2c7d0; + --pico-text-selection-color: rgba(1, 170, 255, 0.1875); + --pico-muted-color: #7b8495; + --pico-muted-border-color: #202632; + --pico-primary: #01aaff; + --pico-primary-background: #0172ad; + --pico-primary-border: var(--pico-primary-background); + --pico-primary-underline: rgba(1, 170, 255, 0.5); + --pico-primary-hover: #79c0ff; + --pico-primary-hover-background: #017fc0; + --pico-primary-hover-border: var(--pico-primary-hover-background); + --pico-primary-hover-underline: var(--pico-primary-hover); + --pico-primary-focus: rgba(1, 170, 255, 0.375); + --pico-primary-inverse: #fff; + --pico-secondary: #969eaf; + --pico-secondary-background: #525f7a; + --pico-secondary-border: var(--pico-secondary-background); + --pico-secondary-underline: rgba(150, 158, 175, 0.5); + --pico-secondary-hover: #b3b9c5; + --pico-secondary-hover-background: #5d6b89; + --pico-secondary-hover-border: var(--pico-secondary-hover-background); + --pico-secondary-hover-underline: var(--pico-secondary-hover); + --pico-secondary-focus: rgba(144, 158, 190, 0.25); + --pico-secondary-inverse: #fff; + --pico-contrast: #dfe3eb; + --pico-contrast-background: #eff1f4; + --pico-contrast-border: var(--pico-contrast-background); + --pico-contrast-underline: rgba(223, 227, 235, 0.5); + --pico-contrast-hover: #fff; + --pico-contrast-hover-background: #fff; + --pico-contrast-hover-border: var(--pico-contrast-hover-background); + --pico-contrast-hover-underline: var(--pico-contrast-hover); + --pico-contrast-focus: rgba(207, 213, 226, 0.25); + --pico-contrast-inverse: #000; + --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(7, 9, 12, 0.01698), + 0.0335rem 0.067rem 0.402rem rgba(7, 9, 12, 0.024), + 0.0625rem 0.125rem 0.75rem rgba(7, 9, 12, 0.03), + 0.1125rem 0.225rem 1.35rem rgba(7, 9, 12, 0.036), + 0.2085rem 0.417rem 2.502rem rgba(7, 9, 12, 0.04302), + 0.5rem 1rem 6rem rgba(7, 9, 12, 0.06), + 0 0 0 0.0625rem rgba(7, 9, 12, 0.015); + --pico-h1-color: #f0f1f3; + --pico-h2-color: #e0e3e7; + --pico-h3-color: #c2c7d0; + --pico-h4-color: #b3b9c5; + --pico-h5-color: #a4acba; + --pico-h6-color: #8891a4; + --pico-mark-background-color: #014063; + --pico-mark-color: #fff; + --pico-ins-color: #62af9a; + --pico-del-color: #ce7e7b; + --pico-blockquote-border-color: var(--pico-muted-border-color); + --pico-blockquote-footer-color: var(--pico-muted-color); + --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-table-border-color: var(--pico-muted-border-color); + --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375); + --pico-code-background-color: #1a1f28; + --pico-code-color: #8891a4; + --pico-code-kbd-background-color: var(--pico-color); + --pico-code-kbd-color: var(--pico-background-color); + --pico-form-element-background-color: #1c212c; + --pico-form-element-selected-background-color: #2a3140; + --pico-form-element-border-color: #2a3140; + --pico-form-element-color: #e0e3e7; + --pico-form-element-placeholder-color: #8891a4; + --pico-form-element-active-background-color: #1a1f28; + --pico-form-element-active-border-color: var(--pico-primary-border); + --pico-form-element-focus-color: var(--pico-primary-border); + --pico-form-element-disabled-opacity: 0.5; + --pico-form-element-invalid-border-color: #964a50; + --pico-form-element-invalid-active-border-color: #b7403b; + --pico-form-element-invalid-focus-color: var( + --pico-form-element-invalid-active-border-color + ); + --pico-form-element-valid-border-color: #2a7b6f; + --pico-form-element-valid-active-border-color: #16896a; + --pico-form-element-valid-focus-color: var( + --pico-form-element-valid-active-border-color + ); + --pico-switch-background-color: #333c4e; + --pico-switch-checked-background-color: var(--pico-primary-background); + --pico-switch-color: #fff; + --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-range-border-color: #202632; + --pico-range-active-border-color: #2a3140; + --pico-range-thumb-border-color: var(--pico-background-color); + --pico-range-thumb-color: var(--pico-secondary-background); + --pico-range-thumb-active-color: var(--pico-primary-background); + --pico-accordion-border-color: var(--pico-muted-border-color); + --pico-accordion-active-summary-color: var(--pico-primary-hover); + --pico-accordion-close-summary-color: var(--pico-color); + --pico-accordion-open-summary-color: var(--pico-muted-color); + --pico-card-background-color: #181c25; + --pico-card-border-color: var(--pico-card-background-color); + --pico-card-box-shadow: var(--pico-box-shadow); + --pico-card-sectioning-background-color: #1a1f28; + --pico-dropdown-background-color: #181c25; + --pico-dropdown-border-color: #202632; + --pico-dropdown-box-shadow: var(--pico-box-shadow); + --pico-dropdown-color: var(--pico-color); + --pico-dropdown-hover-background-color: #202632; + --pico-loading-spinner-opacity: 0.5; + --pico-modal-overlay-background-color: rgba(8, 9, 10, 0.75); + --pico-progress-background-color: #202632; + --pico-progress-color: var(--pico-primary-background); + --pico-tooltip-background-color: var(--pico-contrast-background); + --pico-tooltip-color: var(--pico-contrast-inverse); + --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(150, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); + color-scheme: dark; + } + :root:not([data-theme]) + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ) { + --pico-form-element-focus-color: var(--pico-primary-focus); + } + :root:not([data-theme]) + details + summary[role="button"].contrast:not(.outline)::after { + filter: brightness(0); + } + :root:not([data-theme]) + [aria-busy="true"]:not(input, select, textarea).contrast:is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ):not(.outline)::before { + filter: brightness(0); + } +} +[data-theme="dark"] { + --pico-background-color: #13171f; + --pico-color: #c2c7d0; + --pico-text-selection-color: rgba(1, 170, 255, 0.1875); + --pico-muted-color: #7b8495; + --pico-muted-border-color: #202632; + --pico-primary: #01aaff; + --pico-primary-background: #0172ad; + --pico-primary-border: var(--pico-primary-background); + --pico-primary-underline: rgba(1, 170, 255, 0.5); + --pico-primary-hover: #79c0ff; + --pico-primary-hover-background: #017fc0; + --pico-primary-hover-border: var(--pico-primary-hover-background); + --pico-primary-hover-underline: var(--pico-primary-hover); + --pico-primary-focus: rgba(1, 170, 255, 0.375); + --pico-primary-inverse: #fff; + --pico-secondary: #969eaf; + --pico-secondary-background: #525f7a; + --pico-secondary-border: var(--pico-secondary-background); + --pico-secondary-underline: rgba(150, 158, 175, 0.5); + --pico-secondary-hover: #b3b9c5; + --pico-secondary-hover-background: #5d6b89; + --pico-secondary-hover-border: var(--pico-secondary-hover-background); + --pico-secondary-hover-underline: var(--pico-secondary-hover); + --pico-secondary-focus: rgba(144, 158, 190, 0.25); + --pico-secondary-inverse: #fff; + --pico-contrast: #dfe3eb; + --pico-contrast-background: #eff1f4; + --pico-contrast-border: var(--pico-contrast-background); + --pico-contrast-underline: rgba(223, 227, 235, 0.5); + --pico-contrast-hover: #fff; + --pico-contrast-hover-background: #fff; + --pico-contrast-hover-border: var(--pico-contrast-hover-background); + --pico-contrast-hover-underline: var(--pico-contrast-hover); + --pico-contrast-focus: rgba(207, 213, 226, 0.25); + --pico-contrast-inverse: #000; + --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(7, 9, 12, 0.01698), + 0.0335rem 0.067rem 0.402rem rgba(7, 9, 12, 0.024), + 0.0625rem 0.125rem 0.75rem rgba(7, 9, 12, 0.03), + 0.1125rem 0.225rem 1.35rem rgba(7, 9, 12, 0.036), + 0.2085rem 0.417rem 2.502rem rgba(7, 9, 12, 0.04302), + 0.5rem 1rem 6rem rgba(7, 9, 12, 0.06), 0 0 0 0.0625rem rgba(7, 9, 12, 0.015); + --pico-h1-color: #f0f1f3; + --pico-h2-color: #e0e3e7; + --pico-h3-color: #c2c7d0; + --pico-h4-color: #b3b9c5; + --pico-h5-color: #a4acba; + --pico-h6-color: #8891a4; + --pico-mark-background-color: #014063; + --pico-mark-color: #fff; + --pico-ins-color: #62af9a; + --pico-del-color: #ce7e7b; + --pico-blockquote-border-color: var(--pico-muted-border-color); + --pico-blockquote-footer-color: var(--pico-muted-color); + --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-table-border-color: var(--pico-muted-border-color); + --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375); + --pico-code-background-color: #1a1f28; + --pico-code-color: #8891a4; + --pico-code-kbd-background-color: var(--pico-color); + --pico-code-kbd-color: var(--pico-background-color); + --pico-form-element-background-color: #1c212c; + --pico-form-element-selected-background-color: #2a3140; + --pico-form-element-border-color: #2a3140; + --pico-form-element-color: #e0e3e7; + --pico-form-element-placeholder-color: #8891a4; + --pico-form-element-active-background-color: #1a1f28; + --pico-form-element-active-border-color: var(--pico-primary-border); + --pico-form-element-focus-color: var(--pico-primary-border); + --pico-form-element-disabled-opacity: 0.5; + --pico-form-element-invalid-border-color: #964a50; + --pico-form-element-invalid-active-border-color: #b7403b; + --pico-form-element-invalid-focus-color: var( + --pico-form-element-invalid-active-border-color + ); + --pico-form-element-valid-border-color: #2a7b6f; + --pico-form-element-valid-active-border-color: #16896a; + --pico-form-element-valid-focus-color: var( + --pico-form-element-valid-active-border-color + ); + --pico-switch-background-color: #333c4e; + --pico-switch-checked-background-color: var(--pico-primary-background); + --pico-switch-color: #fff; + --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --pico-range-border-color: #202632; + --pico-range-active-border-color: #2a3140; + --pico-range-thumb-border-color: var(--pico-background-color); + --pico-range-thumb-color: var(--pico-secondary-background); + --pico-range-thumb-active-color: var(--pico-primary-background); + --pico-accordion-border-color: var(--pico-muted-border-color); + --pico-accordion-active-summary-color: var(--pico-primary-hover); + --pico-accordion-close-summary-color: var(--pico-color); + --pico-accordion-open-summary-color: var(--pico-muted-color); + --pico-card-background-color: #181c25; + --pico-card-border-color: var(--pico-card-background-color); + --pico-card-box-shadow: var(--pico-box-shadow); + --pico-card-sectioning-background-color: #1a1f28; + --pico-dropdown-background-color: #181c25; + --pico-dropdown-border-color: #202632; + --pico-dropdown-box-shadow: var(--pico-box-shadow); + --pico-dropdown-color: var(--pico-color); + --pico-dropdown-hover-background-color: #202632; + --pico-loading-spinner-opacity: 0.5; + --pico-modal-overlay-background-color: rgba(8, 9, 10, 0.75); + --pico-progress-background-color: #202632; + --pico-progress-color: var(--pico-primary-background); + --pico-tooltip-background-color: var(--pico-contrast-background); + --pico-tooltip-color: var(--pico-contrast-inverse); + --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(150, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); + color-scheme: dark; +} +[data-theme="dark"] + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ) { + --pico-form-element-focus-color: var(--pico-primary-focus); +} +[data-theme="dark"] + details + summary[role="button"].contrast:not(.outline)::after { + filter: brightness(0); +} +[data-theme="dark"] + [aria-busy="true"]:not(input, select, textarea).contrast:is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ):not(.outline)::before { + filter: brightness(0); +} +[type="checkbox"], +[type="radio"], +[type="range"], +progress { + accent-color: var(--pico-primary); +} +*, +::after, +::before { + box-sizing: border-box; + background-repeat: no-repeat; +} +::after, +::before { + text-decoration: inherit; + vertical-align: inherit; +} +:where(:root) { + -webkit-tap-highlight-color: transparent; + -webkit-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + text-size-adjust: 100%; + background-color: var(--pico-background-color); + color: var(--pico-color); + font-weight: var(--pico-font-weight); + font-size: var(--pico-font-size); + line-height: var(--pico-line-height); + font-family: var(--pico-font-family); + text-underline-offset: var(--pico-text-underline-offset); + text-rendering: optimizeLegibility; + overflow-wrap: break-word; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; +} +body { + width: 100%; + margin: 0; +} +main { + display: block; +} +body > footer, +body > header, +body > main { + padding-block: var(--pico-block-spacing-vertical); +} +section { + margin-bottom: var(--pico-block-spacing-vertical); +} +.container, +.container-fluid { + width: 100%; + margin-right: auto; + margin-left: auto; + padding-right: var(--pico-spacing); + padding-left: var(--pico-spacing); +} +@media (min-width: 576px) { + .container { + max-width: 510px; + padding-right: 0; + padding-left: 0; + } +} +@media (min-width: 768px) { + .container { + max-width: 700px; + } +} +@media (min-width: 1024px) { + .container { + max-width: 950px; + } +} +@media (min-width: 1280px) { + .container { + max-width: 1200px; + } +} +@media (min-width: 1536px) { + .container { + max-width: 1450px; + } +} +.grid { + grid-column-gap: var(--pico-grid-column-gap); + grid-row-gap: var(--pico-grid-row-gap); + display: grid; + grid-template-columns: 1fr; +} +@media (min-width: 768px) { + .grid { + grid-template-columns: repeat(auto-fit, minmax(0%, 1fr)); + } +} +.grid > * { + min-width: 0; +} +.overflow-auto { + overflow: auto; +} +b, +strong { + font-weight: bolder; +} +sub, +sup { + position: relative; + font-size: 0.75em; + line-height: 0; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +address, +blockquote, +dl, +ol, +p, +pre, +table, +ul { + margin-top: 0; + margin-bottom: var(--pico-typography-spacing-vertical); + color: var(--pico-color); + font-style: normal; + font-weight: var(--pico-font-weight); +} +h1, +h2, +h3, +h4, +h5, +h6 { + margin-top: 0; + margin-bottom: var(--pico-typography-spacing-vertical); + color: var(--pico-color); + font-weight: var(--pico-font-weight); + font-size: var(--pico-font-size); + line-height: var(--pico-line-height); + font-family: var(--pico-font-family); +} +h1 { + --pico-color: var(--pico-h1-color); +} +h2 { + --pico-color: var(--pico-h2-color); +} +h3 { + --pico-color: var(--pico-h3-color); +} +h4 { + --pico-color: var(--pico-h4-color); +} +h5 { + --pico-color: var(--pico-h5-color); +} +h6 { + --pico-color: var(--pico-h6-color); +} +:where(article, address, blockquote, dl, figure, form, ol, p, pre, table, ul) + ~ :is(h1, h2, h3, h4, h5, h6) { + margin-top: var(--pico-typography-spacing-top); +} +p { + margin-bottom: var(--pico-typography-spacing-vertical); +} +hgroup { + margin-bottom: var(--pico-typography-spacing-vertical); +} +hgroup > * { + margin-top: 0; + margin-bottom: 0; +} +hgroup > :not(:first-child):last-child { + --pico-color: var(--pico-muted-color); + --pico-font-weight: unset; + font-size: 1rem; +} +:where(ol, ul) li { + margin-bottom: calc(var(--pico-typography-spacing-vertical) * 0.25); +} +:where(dl, ol, ul) :where(dl, ol, ul) { + margin: 0; + margin-top: calc(var(--pico-typography-spacing-vertical) * 0.25); +} +ul li { + list-style: square; +} +mark { + padding: 0.125rem 0.25rem; + background-color: var(--pico-mark-background-color); + color: var(--pico-mark-color); + vertical-align: baseline; +} +blockquote { + display: block; + margin: var(--pico-typography-spacing-vertical) 0; + padding: var(--pico-spacing); + border-right: none; + border-left: 0.25rem solid var(--pico-blockquote-border-color); + border-inline-start: 0.25rem solid var(--pico-blockquote-border-color); + border-inline-end: none; +} +blockquote footer { + margin-top: calc(var(--pico-typography-spacing-vertical) * 0.5); + color: var(--pico-blockquote-footer-color); +} +abbr[title] { + border-bottom: 1px dotted; + text-decoration: none; + cursor: help; +} +ins { + color: var(--pico-ins-color); + text-decoration: none; +} +del { + color: var(--pico-del-color); +} +::-moz-selection { + background-color: var(--pico-text-selection-color); +} +::selection { + background-color: var(--pico-text-selection-color); +} +:where(a:not([role="button"])), +[role="link"] { + --pico-color: var(--pico-primary); + --pico-background-color: transparent; + --pico-underline: var(--pico-primary-underline); + outline: 0; + background-color: var(--pico-background-color); + color: var(--pico-color); + -webkit-text-decoration: var(--pico-text-decoration); + text-decoration: var(--pico-text-decoration); + text-decoration-color: var(--pico-underline); + text-underline-offset: 0.125em; + transition: background-color var(--pico-transition), + color var(--pico-transition), box-shadow var(--pico-transition), + -webkit-text-decoration var(--pico-transition); + transition: background-color var(--pico-transition), + color var(--pico-transition), text-decoration var(--pico-transition), + box-shadow var(--pico-transition); + transition: background-color var(--pico-transition), + color var(--pico-transition), text-decoration var(--pico-transition), + box-shadow var(--pico-transition), + -webkit-text-decoration var(--pico-transition); +} +:where(a:not([role="button"])):is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[role="link"]:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-color: var(--pico-primary-hover); + --pico-underline: var(--pico-primary-hover-underline); + --pico-text-decoration: underline; +} +:where(a:not([role="button"])):focus-visible, +[role="link"]:focus-visible { + box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus); +} +:where(a:not([role="button"])).secondary, +[role="link"].secondary { + --pico-color: var(--pico-secondary); + --pico-underline: var(--pico-secondary-underline); +} +:where(a:not([role="button"])).secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[role="link"].secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-color: var(--pico-secondary-hover); + --pico-underline: var(--pico-secondary-hover-underline); +} +:where(a:not([role="button"])).contrast, +[role="link"].contrast { + --pico-color: var(--pico-contrast); + --pico-underline: var(--pico-contrast-underline); +} +:where(a:not([role="button"])).contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[role="link"].contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-color: var(--pico-contrast-hover); + --pico-underline: var(--pico-contrast-hover-underline); +} +a[role="button"] { + display: inline-block; +} +button { + margin: 0; + overflow: visible; + font-family: inherit; + text-transform: none; +} +[type="button"], +[type="reset"], +[type="submit"], +button { + -webkit-appearance: button; +} +[role="button"], +[type="button"], +[type="file"]::file-selector-button, +[type="reset"], +[type="submit"], +button { + --pico-background-color: var(--pico-primary-background); + --pico-border-color: var(--pico-primary-border); + --pico-color: var(--pico-primary-inverse); + --pico-box-shadow: var(--pico-button-box-shadow, 0 0 0 rgba(0, 0, 0, 0)); + padding: var(--pico-form-element-spacing-vertical) + var(--pico-form-element-spacing-horizontal); + border: var(--pico-border-width) solid var(--pico-border-color); + border-radius: var(--pico-border-radius); + outline: 0; + background-color: var(--pico-background-color); + box-shadow: var(--pico-box-shadow); + color: var(--pico-color); + font-weight: var(--pico-font-weight); + font-size: 1rem; + line-height: var(--pico-line-height); + text-align: center; + text-decoration: none; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + transition: background-color var(--pico-transition), + border-color var(--pico-transition), color var(--pico-transition), + box-shadow var(--pico-transition); +} +[role="button"]:is(:hover, :active, :focus), +[role="button"]:is([aria-current]:not([aria-current="false"])), +[type="button"]:is(:hover, :active, :focus), +[type="button"]:is([aria-current]:not([aria-current="false"])), +[type="file"]::file-selector-button:is(:hover, :active, :focus), +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]) + ), +[type="reset"]:is(:hover, :active, :focus), +[type="reset"]:is([aria-current]:not([aria-current="false"])), +[type="submit"]:is(:hover, :active, :focus), +[type="submit"]:is([aria-current]:not([aria-current="false"])), +button:is(:hover, :active, :focus), +button:is([aria-current]:not([aria-current="false"])) { + --pico-background-color: var(--pico-primary-hover-background); + --pico-border-color: var(--pico-primary-hover-border); + --pico-box-shadow: var( + --pico-button-hover-box-shadow, + 0 0 0 rgba(0, 0, 0, 0) + ); + --pico-color: var(--pico-primary-inverse); +} +[role="button"]:focus, +[role="button"]:is([aria-current]:not([aria-current="false"])):focus, +[type="button"]:focus, +[type="button"]:is([aria-current]:not([aria-current="false"])):focus, +[type="file"]::file-selector-button:focus, +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]) + ):focus, +[type="reset"]:focus, +[type="reset"]:is([aria-current]:not([aria-current="false"])):focus, +[type="submit"]:focus, +[type="submit"]:is([aria-current]:not([aria-current="false"])):focus, +button:focus, +button:is([aria-current]:not([aria-current="false"])):focus { + --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--pico-outline-width) var(--pico-primary-focus); +} +[type="button"], +[type="reset"], +[type="submit"] { + margin-bottom: var(--pico-spacing); +} +:is(button, [type="submit"], [type="button"], [role="button"]).secondary, +[type="file"]::file-selector-button, +[type="reset"] { + --pico-background-color: var(--pico-secondary-background); + --pico-border-color: var(--pico-secondary-border); + --pico-color: var(--pico-secondary-inverse); + cursor: pointer; +} +:is(button, [type="submit"], [type="button"], [role="button"]).secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="reset"]:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-background-color: var(--pico-secondary-hover-background); + --pico-border-color: var(--pico-secondary-hover-border); + --pico-color: var(--pico-secondary-inverse); +} +:is(button, [type="submit"], [type="button"], [role="button"]).secondary:focus, +:is(button, [type="submit"], [type="button"], [role="button"]).secondary:is( + [aria-current]:not([aria-current="false"]) + ):focus, +[type="file"]::file-selector-button:focus, +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]) + ):focus, +[type="reset"]:focus, +[type="reset"]:is([aria-current]:not([aria-current="false"])):focus { + --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus); +} +:is(button, [type="submit"], [type="button"], [role="button"]).contrast { + --pico-background-color: var(--pico-contrast-background); + --pico-border-color: var(--pico-contrast-border); + --pico-color: var(--pico-contrast-inverse); +} +:is(button, [type="submit"], [type="button"], [role="button"]).contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-background-color: var(--pico-contrast-hover-background); + --pico-border-color: var(--pico-contrast-hover-border); + --pico-color: var(--pico-contrast-inverse); +} +:is(button, [type="submit"], [type="button"], [role="button"]).contrast:focus, +:is(button, [type="submit"], [type="button"], [role="button"]).contrast:is( + [aria-current]:not([aria-current="false"]) + ):focus { + --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--pico-outline-width) var(--pico-contrast-focus); +} +:is(button, [type="submit"], [type="button"], [role="button"]).outline, +[type="reset"].outline { + --pico-background-color: transparent; + --pico-color: var(--pico-primary); + --pico-border-color: var(--pico-primary); +} +:is(button, [type="submit"], [type="button"], [role="button"]).outline:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="reset"].outline:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-background-color: transparent; + --pico-color: var(--pico-primary-hover); + --pico-border-color: var(--pico-primary-hover); +} +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.secondary, +[type="reset"].outline { + --pico-color: var(--pico-secondary); + --pico-border-color: var(--pico-secondary); +} +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="reset"].outline:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-color: var(--pico-secondary-hover); + --pico-border-color: var(--pico-secondary-hover); +} +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.contrast { + --pico-color: var(--pico-contrast); + --pico-border-color: var(--pico-contrast); +} +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --pico-color: var(--pico-contrast-hover); + --pico-border-color: var(--pico-contrast-hover); +} +:where( + button, + [type="submit"], + [type="reset"], + [type="button"], + [role="button"] + )[disabled], +:where(fieldset[disabled]) + :is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ) { + opacity: 0.5; + pointer-events: none; +} +:where(table) { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + text-indent: 0; +} +td, +th { + padding: calc(var(--pico-spacing) / 2) var(--pico-spacing); + border-bottom: var(--pico-border-width) solid var(--pico-table-border-color); + background-color: var(--pico-background-color); + color: var(--pico-color); + font-weight: var(--pico-font-weight); + text-align: left; + text-align: start; +} +tfoot td, +tfoot th { + border-top: var(--pico-border-width) solid var(--pico-table-border-color); + border-bottom: 0; +} +table.striped tbody tr:nth-child(odd) td, +table.striped tbody tr:nth-child(odd) th { + background-color: var(--pico-table-row-stripped-background-color); +} +:where(audio, canvas, iframe, img, svg, video) { + vertical-align: middle; +} +audio, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; + height: 0; +} +:where(iframe) { + border-style: none; +} +img { + max-width: 100%; + height: auto; + border-style: none; +} +:where(svg:not([fill])) { + fill: currentColor; +} +svg:not(:root) { + overflow: hidden; +} +code, +kbd, +pre, +samp { + font-size: 0.875em; + font-family: var(--pico-font-family); +} +pre code { + font-size: inherit; + font-family: inherit; +} +pre { + -ms-overflow-style: scrollbar; + overflow: auto; +} +code, +kbd, +pre { + border-radius: var(--pico-border-radius); + background: var(--pico-code-background-color); + color: var(--pico-code-color); + font-weight: var(--pico-font-weight); + line-height: initial; +} +code, +kbd { + display: inline-block; + padding: 0.375rem; +} +pre { + display: block; + margin-bottom: var(--pico-spacing); + overflow-x: auto; +} +pre > code { + display: block; + padding: var(--pico-spacing); + background: 0 0; + line-height: var(--pico-line-height); +} +kbd { + background-color: var(--pico-code-kbd-background-color); + color: var(--pico-code-kbd-color); + vertical-align: baseline; +} +figure { + display: block; + margin: 0; + padding: 0; +} +figure figcaption { + padding: calc(var(--pico-spacing) * 0.5) 0; + color: var(--pico-muted-color); +} +hr { + height: 0; + margin: var(--pico-typography-spacing-vertical) 0; + border: 0; + border-top: 1px solid var(--pico-muted-border-color); + color: inherit; +} +[hidden], +template { + display: none !important; +} +canvas { + display: inline-block; +} +input, +optgroup, +select, +textarea { + margin: 0; + font-size: 1rem; + line-height: var(--pico-line-height); + font-family: inherit; + letter-spacing: inherit; +} +input { + overflow: visible; +} +select { + text-transform: none; +} +legend { + max-width: 100%; + padding: 0; + color: inherit; + white-space: normal; +} +textarea { + overflow: auto; +} +[type="checkbox"], +[type="radio"] { + padding: 0; +} +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; +} +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} +::-moz-focus-inner { + padding: 0; + border-style: none; +} +:-moz-focusring { + outline: 0; +} +:-moz-ui-invalid { + box-shadow: none; +} +::-ms-expand { + display: none; +} +[type="file"], +[type="range"] { + padding: 0; + border-width: 0; +} +input:not([type="checkbox"], [type="radio"], [type="range"]) { + height: calc( + 1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * + 2 + var(--pico-border-width) * 2 + ); +} +fieldset { + width: 100%; + margin: 0; + margin-bottom: var(--pico-spacing); + padding: 0; + border: 0; +} +fieldset legend, +label { + display: block; + margin-bottom: calc(var(--pico-spacing) * 0.375); + color: var(--pico-color); + font-weight: var(--pico-form-label-font-weight, var(--pico-font-weight)); +} +fieldset legend { + margin-bottom: calc(var(--pico-spacing) * 0.5); +} +button[type="submit"], +input:not([type="checkbox"], [type="radio"]), +select, +textarea { + width: 100%; +} +input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), +select, +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: var(--pico-form-element-spacing-vertical) + var(--pico-form-element-spacing-horizontal); +} +input, +select, +textarea { + --pico-background-color: var(--pico-form-element-background-color); + --pico-border-color: var(--pico-form-element-border-color); + --pico-color: var(--pico-form-element-color); + --pico-box-shadow: none; + border: var(--pico-border-width) solid var(--pico-border-color); + border-radius: var(--pico-border-radius); + outline: 0; + background-color: var(--pico-background-color); + box-shadow: var(--pico-box-shadow); + color: var(--pico-color); + font-weight: var(--pico-font-weight); + transition: background-color var(--pico-transition), + border-color var(--pico-transition), color var(--pico-transition), + box-shadow var(--pico-transition); +} +:where(select, textarea):not([readonly]):is(:active, :focus), +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [readonly] + ):is(:active, :focus) { + --pico-background-color: var(--pico-form-element-active-background-color); +} +:where(select, textarea):not([readonly]):is(:active, :focus), +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [role="switch"], + [readonly] + ):is(:active, :focus) { + --pico-border-color: var(--pico-form-element-active-border-color); +} +:where(select, textarea):not([readonly]):focus, +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [type="range"], + [type="file"], + [readonly] + ):focus { + --pico-box-shadow: 0 0 0 var(--pico-outline-width) + var(--pico-form-element-focus-color); +} +:where(fieldset[disabled]) + :is( + input:not([type="submit"], [type="button"], [type="reset"]), + select, + textarea + ), +input:not([type="submit"], [type="button"], [type="reset"])[disabled], +label[aria-disabled="true"], +select[disabled], +textarea[disabled] { + opacity: var(--pico-form-element-disabled-opacity); + pointer-events: none; +} +label[aria-disabled="true"] input[disabled] { + opacity: 1; +} +:where(input, select, textarea):not( + [type="checkbox"], + [type="radio"], + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"], + [type="range"] + )[aria-invalid] { + padding-right: calc( + var(--pico-form-element-spacing-horizontal) + 1.5rem + ) !important; + padding-left: var(--pico-form-element-spacing-horizontal); + padding-inline-start: var(--pico-form-element-spacing-horizontal) !important; + padding-inline-end: calc( + var(--pico-form-element-spacing-horizontal) + 1.5rem + ) !important; + background-position: center right 0.75rem; + background-size: 1rem auto; + background-repeat: no-repeat; +} +:where(input, select, textarea):not( + [type="checkbox"], + [type="radio"], + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"], + [type="range"] + )[aria-invalid="false"]:not(select) { + background-image: var(--pico-icon-valid); +} +:where(input, select, textarea):not( + [type="checkbox"], + [type="radio"], + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"], + [type="range"] + )[aria-invalid="true"]:not(select) { + background-image: var(--pico-icon-invalid); +} +:where(input, select, textarea)[aria-invalid="false"] { + --pico-border-color: var(--pico-form-element-valid-border-color); +} +:where(input, select, textarea)[aria-invalid="false"]:is(:active, :focus) { + --pico-border-color: var( + --pico-form-element-valid-active-border-color + ) !important; +} +:where(input, select, textarea)[aria-invalid="false"]:is(:active, :focus):not( + [type="checkbox"], + [type="radio"] + ) { + --pico-box-shadow: 0 0 0 var(--pico-outline-width) + var(--pico-form-element-valid-focus-color) !important; +} +:where(input, select, textarea)[aria-invalid="true"] { + --pico-border-color: var(--pico-form-element-invalid-border-color); +} +:where(input, select, textarea)[aria-invalid="true"]:is(:active, :focus) { + --pico-border-color: var( + --pico-form-element-invalid-active-border-color + ) !important; +} +:where(input, select, textarea)[aria-invalid="true"]:is(:active, :focus):not( + [type="checkbox"], + [type="radio"] + ) { + --pico-box-shadow: 0 0 0 var(--pico-outline-width) + var(--pico-form-element-invalid-focus-color) !important; +} +[dir="rtl"] + :where(input, select, textarea):not([type="checkbox"], [type="radio"]):is( + [aria-invalid], + [aria-invalid="true"], + [aria-invalid="false"] + ) { + background-position: center left 0.75rem; +} +input::-webkit-input-placeholder, +input::placeholder, +select:invalid, +textarea::-webkit-input-placeholder, +textarea::placeholder { + color: var(--pico-form-element-placeholder-color); + opacity: 1; +} +input:not([type="checkbox"], [type="radio"]), +select, +textarea { + margin-bottom: var(--pico-spacing); +} +select::-ms-expand { + border: 0; + background-color: transparent; +} +select:not([multiple], [size]) { + padding-right: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem); + padding-left: var(--pico-form-element-spacing-horizontal); + padding-inline-start: var(--pico-form-element-spacing-horizontal); + padding-inline-end: calc( + var(--pico-form-element-spacing-horizontal) + 1.5rem + ); + background-image: var(--pico-icon-chevron); + background-position: center right 0.75rem; + background-size: 1rem auto; + background-repeat: no-repeat; +} +select[multiple] option:checked { + background: var(--pico-form-element-selected-background-color); + color: var(--pico-form-element-color); +} +[dir="rtl"] select:not([multiple], [size]) { + background-position: center left 0.75rem; +} +textarea { + display: block; + resize: vertical; +} +textarea[aria-invalid] { + --pico-icon-height: calc( + 1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * + 2 + var(--pico-border-width) * 2 + ); + background-position: top right 0.75rem !important; + background-size: 1rem var(--pico-icon-height) !important; +} +:where(input, select, textarea, fieldset, .grid) + small { + display: block; + width: 100%; + margin-top: calc(var(--pico-spacing) * -0.75); + margin-bottom: var(--pico-spacing); + color: var(--pico-muted-color); +} +:where(input, select, textarea, fieldset, .grid)[aria-invalid="false"] + small { + color: var(--pico-ins-color); +} +:where(input, select, textarea, fieldset, .grid)[aria-invalid="true"] + small { + color: var(--pico-del-color); +} +label > :where(input, select, textarea) { + margin-top: calc(var(--pico-spacing) * 0.25); +} +label:has([type="checkbox"], [type="radio"]) { + width: -moz-fit-content; + width: fit-content; + cursor: pointer; +} +[type="checkbox"], +[type="radio"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 1.25em; + height: 1.25em; + margin-top: -0.125em; + margin-inline-end: 0.5em; + border-width: var(--pico-border-width); + vertical-align: middle; + cursor: pointer; +} +[type="checkbox"]::-ms-check, +[type="radio"]::-ms-check { + display: none; +} +[type="checkbox"]:checked, +[type="checkbox"]:checked:active, +[type="checkbox"]:checked:focus, +[type="radio"]:checked, +[type="radio"]:checked:active, +[type="radio"]:checked:focus { + --pico-background-color: var(--pico-primary-background); + --pico-border-color: var(--pico-primary-border); + background-image: var(--pico-icon-checkbox); + background-position: center; + background-size: 0.75em auto; + background-repeat: no-repeat; +} +[type="checkbox"] ~ label, +[type="radio"] ~ label { + display: inline-block; + margin-bottom: 0; + cursor: pointer; +} +[type="checkbox"] ~ label:not(:last-of-type), +[type="radio"] ~ label:not(:last-of-type) { + margin-inline-end: 1em; +} +[type="checkbox"]:indeterminate { + --pico-background-color: var(--pico-primary-background); + --pico-border-color: var(--pico-primary-border); + background-image: var(--pico-icon-minus); + background-position: center; + background-size: 0.75em auto; + background-repeat: no-repeat; +} +[type="radio"] { + border-radius: 50%; +} +[type="radio"]:checked, +[type="radio"]:checked:active, +[type="radio"]:checked:focus { + --pico-background-color: var(--pico-primary-inverse); + border-width: 0.35em; + background-image: none; +} +[type="checkbox"][role="switch"] { + --pico-background-color: var(--pico-switch-background-color); + --pico-color: var(--pico-switch-color); + width: 2.25em; + height: 1.25em; + border: var(--pico-border-width) solid var(--pico-border-color); + border-radius: 1.25em; + background-color: var(--pico-background-color); + line-height: 1.25em; +} +[type="checkbox"][role="switch"]:not([aria-invalid]) { + --pico-border-color: var(--pico-switch-background-color); +} +[type="checkbox"][role="switch"]:before { + display: block; + aspect-ratio: 1; + height: 100%; + border-radius: 50%; + background-color: var(--pico-color); + box-shadow: var(--pico-switch-thumb-box-shadow); + content: ""; + transition: margin 0.1s ease-in-out; +} +[type="checkbox"][role="switch"]:focus { + --pico-background-color: var(--pico-switch-background-color); + --pico-border-color: var(--pico-switch-background-color); +} +[type="checkbox"][role="switch"]:checked { + --pico-background-color: var(--pico-switch-checked-background-color); + --pico-border-color: var(--pico-switch-checked-background-color); + background-image: none; +} +[type="checkbox"][role="switch"]:checked::before { + margin-inline-start: calc(2.25em - 1.25em); +} +[type="checkbox"][role="switch"][disabled] { + --pico-background-color: var(--pico-border-color); +} +[type="checkbox"][aria-invalid="false"]:checked, +[type="checkbox"][aria-invalid="false"]:checked:active, +[type="checkbox"][aria-invalid="false"]:checked:focus, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:active, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:focus { + --pico-background-color: var(--pico-form-element-valid-border-color); +} +[type="checkbox"]:checked:active[aria-invalid="true"], +[type="checkbox"]:checked:focus[aria-invalid="true"], +[type="checkbox"]:checked[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:active[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:focus[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked[aria-invalid="true"] { + --pico-background-color: var(--pico-form-element-invalid-border-color); +} +[type="checkbox"][aria-invalid="false"]:checked, +[type="checkbox"][aria-invalid="false"]:checked:active, +[type="checkbox"][aria-invalid="false"]:checked:focus, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:active, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:focus, +[type="radio"][aria-invalid="false"]:checked, +[type="radio"][aria-invalid="false"]:checked:active, +[type="radio"][aria-invalid="false"]:checked:focus { + --pico-border-color: var(--pico-form-element-valid-border-color); +} +[type="checkbox"]:checked:active[aria-invalid="true"], +[type="checkbox"]:checked:focus[aria-invalid="true"], +[type="checkbox"]:checked[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:active[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:focus[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked[aria-invalid="true"], +[type="radio"]:checked:active[aria-invalid="true"], +[type="radio"]:checked:focus[aria-invalid="true"], +[type="radio"]:checked[aria-invalid="true"] { + --pico-border-color: var(--pico-form-element-invalid-border-color); +} +[type="color"]::-webkit-color-swatch-wrapper { + padding: 0; +} +[type="color"]::-moz-focus-inner { + padding: 0; +} +[type="color"]::-webkit-color-swatch { + border: 0; + border-radius: calc(var(--pico-border-radius) * 0.5); +} +[type="color"]::-moz-color-swatch { + border: 0; + border-radius: calc(var(--pico-border-radius) * 0.5); +} +input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]):is( + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"] + ) { + --pico-icon-position: 0.75rem; + --pico-icon-width: 1rem; + padding-right: calc(var(--pico-icon-width) + var(--pico-icon-position)); + background-image: var(--pico-icon-date); + background-position: center right var(--pico-icon-position); + background-size: var(--pico-icon-width) auto; + background-repeat: no-repeat; +} +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="time"] { + background-image: var(--pico-icon-time); +} +[type="date"]::-webkit-calendar-picker-indicator, +[type="datetime-local"]::-webkit-calendar-picker-indicator, +[type="month"]::-webkit-calendar-picker-indicator, +[type="time"]::-webkit-calendar-picker-indicator, +[type="week"]::-webkit-calendar-picker-indicator { + width: var(--pico-icon-width); + margin-right: calc(var(--pico-icon-width) * -1); + margin-left: var(--pico-icon-position); + opacity: 0; +} +@-moz-document url-prefix() { + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"] { + padding-right: var(--pico-form-element-spacing-horizontal) !important; + background-image: none !important; + } +} +[dir="rtl"] + :is( + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"] + ) { + text-align: right; +} +[type="file"] { + --pico-color: var(--pico-muted-color); + margin-left: calc(var(--pico-outline-width) * -1); + padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) 0; + padding-left: var(--pico-outline-width); + border: 0; + border-radius: 0; + background: 0 0; +} +[type="file"]::file-selector-button { + margin-right: calc(var(--pico-spacing) / 2); + padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) + var(--pico-form-element-spacing-horizontal); +} +[type="file"]:is(:hover, :active, :focus)::file-selector-button { + --pico-background-color: var(--pico-secondary-hover-background); + --pico-border-color: var(--pico-secondary-hover-border); +} +[type="file"]:focus::file-selector-button { + --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus); +} +[type="range"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 100%; + height: 1.25rem; + background: 0 0; +} +[type="range"]::-webkit-slider-runnable-track { + width: 100%; + height: 0.375rem; + border-radius: var(--pico-border-radius); + background-color: var(--pico-range-border-color); + -webkit-transition: background-color var(--pico-transition), + box-shadow var(--pico-transition); + transition: background-color var(--pico-transition), + box-shadow var(--pico-transition); +} +[type="range"]::-moz-range-track { + width: 100%; + height: 0.375rem; + border-radius: var(--pico-border-radius); + background-color: var(--pico-range-border-color); + -moz-transition: background-color var(--pico-transition), + box-shadow var(--pico-transition); + transition: background-color var(--pico-transition), + box-shadow var(--pico-transition); +} +[type="range"]::-ms-track { + width: 100%; + height: 0.375rem; + border-radius: var(--pico-border-radius); + background-color: var(--pico-range-border-color); + -ms-transition: background-color var(--pico-transition), + box-shadow var(--pico-transition); + transition: background-color var(--pico-transition), + box-shadow var(--pico-transition); +} +[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + width: 1.25rem; + height: 1.25rem; + margin-top: -0.4375rem; + border: 2px solid var(--pico-range-thumb-border-color); + border-radius: 50%; + background-color: var(--pico-range-thumb-color); + cursor: pointer; + -webkit-transition: background-color var(--pico-transition), + transform var(--pico-transition); + transition: background-color var(--pico-transition), + transform var(--pico-transition); +} +[type="range"]::-moz-range-thumb { + -webkit-appearance: none; + width: 1.25rem; + height: 1.25rem; + margin-top: -0.4375rem; + border: 2px solid var(--pico-range-thumb-border-color); + border-radius: 50%; + background-color: var(--pico-range-thumb-color); + cursor: pointer; + -moz-transition: background-color var(--pico-transition), + transform var(--pico-transition); + transition: background-color var(--pico-transition), + transform var(--pico-transition); +} +[type="range"]::-ms-thumb { + -webkit-appearance: none; + width: 1.25rem; + height: 1.25rem; + margin-top: -0.4375rem; + border: 2px solid var(--pico-range-thumb-border-color); + border-radius: 50%; + background-color: var(--pico-range-thumb-color); + cursor: pointer; + -ms-transition: background-color var(--pico-transition), + transform var(--pico-transition); + transition: background-color var(--pico-transition), + transform var(--pico-transition); +} +[type="range"]:active, +[type="range"]:focus-within { + --pico-range-border-color: var(--pico-range-active-border-color); + --pico-range-thumb-color: var(--pico-range-thumb-active-color); +} +[type="range"]:active::-webkit-slider-thumb { + transform: scale(1.25); +} +[type="range"]:active::-moz-range-thumb { + transform: scale(1.25); +} +[type="range"]:active::-ms-thumb { + transform: scale(1.25); +} +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"] { + padding-inline-start: calc( + var(--pico-form-element-spacing-horizontal) + 1.75rem + ); + background-image: var(--pico-icon-search); + background-position: center left + calc(var(--pico-form-element-spacing-horizontal) + 0.125rem); + background-size: 1rem auto; + background-repeat: no-repeat; +} +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid] { + padding-inline-start: calc( + var(--pico-form-element-spacing-horizontal) + 1.75rem + ) !important; + background-position: center left 1.125rem, center right 0.75rem; +} +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid="false"] { + background-image: var(--pico-icon-search), var(--pico-icon-valid); +} +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid="true"] { + background-image: var(--pico-icon-search), var(--pico-icon-invalid); +} +[dir="rtl"] + :where(input):not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"] { + background-position: center right 1.125rem; +} +[dir="rtl"] + :where(input):not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid] { + background-position: center right 1.125rem, center left 0.75rem; +} +details { + display: block; + margin-bottom: var(--pico-spacing); +} +details summary { + line-height: 1rem; + list-style-type: none; + cursor: pointer; + transition: color var(--pico-transition); +} +details summary:not([role]) { + color: var(--pico-accordion-close-summary-color); +} +details summary::-webkit-details-marker { + display: none; +} +details summary::marker { + display: none; +} +details summary::-moz-list-bullet { + list-style-type: none; +} +details summary::after { + display: block; + width: 1rem; + height: 1rem; + margin-inline-start: calc(var(--pico-spacing, 1rem) * 0.5); + float: right; + transform: rotate(-90deg); + background-image: var(--pico-icon-chevron); + background-position: right center; + background-size: 1rem auto; + background-repeat: no-repeat; + content: ""; + transition: transform var(--pico-transition); +} +details summary:focus { + outline: 0; +} +details summary:focus:not([role]) { + color: var(--pico-accordion-active-summary-color); +} +details summary:focus-visible:not([role]) { + outline: var(--pico-outline-width) solid var(--pico-primary-focus); + outline-offset: calc(var(--pico-spacing, 1rem) * 0.5); + color: var(--pico-primary); +} +details summary[role="button"] { + width: 100%; + text-align: left; +} +details summary[role="button"]::after { + height: calc(1rem * var(--pico-line-height, 1.5)); +} +details[open] > summary { + margin-bottom: var(--pico-spacing); +} +details[open] > summary:not([role]):not(:focus) { + color: var(--pico-accordion-open-summary-color); +} +details[open] > summary::after { + transform: rotate(0); +} +[dir="rtl"] details summary { + text-align: right; +} +[dir="rtl"] details summary::after { + float: left; + background-position: left center; +} +article { + margin-bottom: var(--pico-block-spacing-vertical); + padding: var(--pico-block-spacing-vertical) + var(--pico-block-spacing-horizontal); + border-radius: var(--pico-border-radius); + background: var(--pico-card-background-color); + box-shadow: var(--pico-card-box-shadow); +} +article > footer, +article > header { + margin-right: calc(var(--pico-block-spacing-horizontal) * -1); + margin-left: calc(var(--pico-block-spacing-horizontal) * -1); + padding: calc(var(--pico-block-spacing-vertical) * 0.66) + var(--pico-block-spacing-horizontal); + background-color: var(--pico-card-sectioning-background-color); +} +article > header { + margin-top: calc(var(--pico-block-spacing-vertical) * -1); + margin-bottom: var(--pico-block-spacing-vertical); + border-bottom: var(--pico-border-width) solid var(--pico-card-border-color); + border-top-right-radius: var(--pico-border-radius); + border-top-left-radius: var(--pico-border-radius); +} +article > footer { + margin-top: var(--pico-block-spacing-vertical); + margin-bottom: calc(var(--pico-block-spacing-vertical) * -1); + border-top: var(--pico-border-width) solid var(--pico-card-border-color); + border-bottom-right-radius: var(--pico-border-radius); + border-bottom-left-radius: var(--pico-border-radius); +} +details.dropdown { + position: relative; + border-bottom: none; +} +details.dropdown summary::after, +details.dropdown > a::after, +details.dropdown > button::after { + display: block; + width: 1rem; + height: calc(1rem * var(--pico-line-height, 1.5)); + margin-inline-start: 0.25rem; + float: right; + transform: rotate(0) translateX(0.2rem); + background-image: var(--pico-icon-chevron); + background-position: right center; + background-size: 1rem auto; + background-repeat: no-repeat; + content: ""; +} +nav details.dropdown { + margin-bottom: 0; +} +details.dropdown summary:not([role]) { + height: calc( + 1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * + 2 + var(--pico-border-width) * 2 + ); + padding: var(--pico-form-element-spacing-vertical) + var(--pico-form-element-spacing-horizontal); + border: var(--pico-border-width) solid var(--pico-form-element-border-color); + border-radius: var(--pico-border-radius); + background-color: var(--pico-form-element-background-color); + color: var(--pico-form-element-placeholder-color); + line-height: inherit; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + transition: background-color var(--pico-transition), + border-color var(--pico-transition), color var(--pico-transition), + box-shadow var(--pico-transition); +} +details.dropdown summary:not([role]):active, +details.dropdown summary:not([role]):focus { + border-color: var(--pico-form-element-active-border-color); + background-color: var(--pico-form-element-active-background-color); +} +details.dropdown summary:not([role]):focus { + box-shadow: 0 0 0 var(--pico-outline-width) + var(--pico-form-element-focus-color); +} +details.dropdown summary:not([role]):focus-visible { + outline: 0; +} +details.dropdown summary:not([role])[aria-invalid="false"] { + --pico-form-element-border-color: var(--pico-form-element-valid-border-color); + --pico-form-element-active-border-color: var( + --pico-form-element-valid-focus-color + ); + --pico-form-element-focus-color: var(--pico-form-element-valid-focus-color); +} +details.dropdown summary:not([role])[aria-invalid="true"] { + --pico-form-element-border-color: var( + --pico-form-element-invalid-border-color + ); + --pico-form-element-active-border-color: var( + --pico-form-element-invalid-focus-color + ); + --pico-form-element-focus-color: var(--pico-form-element-invalid-focus-color); +} +nav details.dropdown { + display: inline; + margin: calc(var(--pico-nav-element-spacing-vertical) * -1) 0; +} +nav details.dropdown summary::after { + transform: rotate(0) translateX(0); +} +nav details.dropdown summary:not([role]) { + height: calc( + 1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 2 + ); + padding: calc( + var(--pico-nav-link-spacing-vertical) - var(--pico-border-width) * 2 + ) + var(--pico-nav-link-spacing-horizontal); +} +nav details.dropdown summary:not([role]):focus-visible { + box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus); +} +details.dropdown summary + ul { + display: flex; + z-index: 99; + position: absolute; + left: 0; + flex-direction: column; + width: 100%; + min-width: -moz-fit-content; + min-width: fit-content; + margin: 0; + margin-top: var(--pico-outline-width); + padding: 0; + border: var(--pico-border-width) solid var(--pico-dropdown-border-color); + border-radius: var(--pico-border-radius); + background-color: var(--pico-dropdown-background-color); + box-shadow: var(--pico-dropdown-box-shadow); + color: var(--pico-dropdown-color); + white-space: nowrap; + opacity: 0; + transition: opacity var(--pico-transition), transform 0s ease-in-out 1s; +} +details.dropdown summary + ul[dir="rtl"] { + right: 0; + left: auto; +} +details.dropdown summary + ul li { + width: 100%; + margin-bottom: 0; + padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) + var(--pico-form-element-spacing-horizontal); + list-style: none; +} +details.dropdown summary + ul li:first-of-type { + margin-top: calc(var(--pico-form-element-spacing-vertical) * 0.5); +} +details.dropdown summary + ul li:last-of-type { + margin-bottom: calc(var(--pico-form-element-spacing-vertical) * 0.5); +} +details.dropdown summary + ul li a { + display: block; + margin: calc(var(--pico-form-element-spacing-vertical) * -0.5) + calc(var(--pico-form-element-spacing-horizontal) * -1); + padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) + var(--pico-form-element-spacing-horizontal); + overflow: hidden; + border-radius: 0; + color: var(--pico-dropdown-color); + text-decoration: none; + text-overflow: ellipsis; +} +details.dropdown summary + ul li a:active, +details.dropdown summary + ul li a:focus, +details.dropdown summary + ul li a:focus-visible, +details.dropdown summary + ul li a:hover, +details.dropdown summary + ul li a[aria-current]:not([aria-current="false"]) { + background-color: var(--pico-dropdown-hover-background-color); +} +details.dropdown summary + ul li label { + width: 100%; +} +details.dropdown summary + ul li:has(label):hover { + background-color: var(--pico-dropdown-hover-background-color); +} +details.dropdown[open] summary { + margin-bottom: 0; +} +details.dropdown[open] summary + ul { + transform: scaleY(1); + opacity: 1; + transition: opacity var(--pico-transition), transform 0s ease-in-out 0s; +} +details.dropdown[open] summary::before { + display: block; + z-index: 1; + position: fixed; + width: 100vw; + height: 100vh; + inset: 0; + background: 0 0; + content: ""; + cursor: default; +} +label > details.dropdown { + margin-top: calc(var(--pico-spacing) * 0.25); +} +[role="group"], +[role="search"] { + display: inline-flex; + position: relative; + width: 100%; + margin-bottom: var(--pico-spacing); + border-radius: var(--pico-border-radius); + box-shadow: var(--pico-group-box-shadow, 0 0 0 transparent); + vertical-align: middle; + transition: box-shadow var(--pico-transition); +} +[role="group"] input:not([type="checkbox"], [type="radio"]), +[role="group"] select, +[role="group"] > *, +[role="search"] input:not([type="checkbox"], [type="radio"]), +[role="search"] select, +[role="search"] > * { + position: relative; + flex: 1 1 auto; + margin-bottom: 0; +} +[role="group"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="group"] select:not(:first-child), +[role="group"] > :not(:first-child), +[role="search"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="search"] select:not(:first-child), +[role="search"] > :not(:first-child) { + margin-left: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +[role="group"] input:not([type="checkbox"], [type="radio"]):not(:last-child), +[role="group"] select:not(:last-child), +[role="group"] > :not(:last-child), +[role="search"] input:not([type="checkbox"], [type="radio"]):not(:last-child), +[role="search"] select:not(:last-child), +[role="search"] > :not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +[role="group"] input:not([type="checkbox"], [type="radio"]):focus, +[role="group"] select:focus, +[role="group"] > :focus, +[role="search"] input:not([type="checkbox"], [type="radio"]):focus, +[role="search"] select:focus, +[role="search"] > :focus { + z-index: 2; +} +[role="group"] [role="button"]:not(:first-child), +[role="group"] [type="button"]:not(:first-child), +[role="group"] [type="reset"]:not(:first-child), +[role="group"] [type="submit"]:not(:first-child), +[role="group"] button:not(:first-child), +[role="group"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="group"] select:not(:first-child), +[role="search"] [role="button"]:not(:first-child), +[role="search"] [type="button"]:not(:first-child), +[role="search"] [type="reset"]:not(:first-child), +[role="search"] [type="submit"]:not(:first-child), +[role="search"] button:not(:first-child), +[role="search"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="search"] select:not(:first-child) { + margin-left: calc(var(--pico-border-width) * -1); +} +[role="group"] [role="button"], +[role="group"] [type="button"], +[role="group"] [type="reset"], +[role="group"] [type="submit"], +[role="group"] button, +[role="search"] [role="button"], +[role="search"] [type="button"], +[role="search"] [type="reset"], +[role="search"] [type="submit"], +[role="search"] button { + width: auto; +} +@supports selector(:has(*)) { + [role="group"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ), + [role="search"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) { + --pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-button); + } + [role="group"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + input:not([type="checkbox"], [type="radio"]), + [role="group"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + select, + [role="search"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + input:not([type="checkbox"], [type="radio"]), + [role="search"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + select { + border-color: transparent; + } + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ), + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) { + --pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-input); + } + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [role="button"], + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="button"], + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="submit"], + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + button, + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [role="button"], + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="button"], + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="submit"], + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + button { + --pico-button-box-shadow: 0 0 0 var(--pico-border-width) + var(--pico-primary-border); + --pico-button-hover-box-shadow: 0 0 0 var(--pico-border-width) + var(--pico-primary-hover-border); + } + [role="group"] [role="button"]:focus, + [role="group"] [type="button"]:focus, + [role="group"] [type="reset"]:focus, + [role="group"] [type="submit"]:focus, + [role="group"] button:focus, + [role="search"] [role="button"]:focus, + [role="search"] [type="button"]:focus, + [role="search"] [type="reset"]:focus, + [role="search"] [type="submit"]:focus, + [role="search"] button:focus { + box-shadow: none; + } +} +[role="search"] > :first-child { + border-top-left-radius: 5rem; + border-bottom-left-radius: 5rem; +} +[role="search"] > :last-child { + border-top-right-radius: 5rem; + border-bottom-right-radius: 5rem; +} +[aria-busy="true"]:not(input, select, textarea, html) { + white-space: nowrap; +} +[aria-busy="true"]:not(input, select, textarea, html)::before { + display: inline-block; + width: 1em; + height: 1em; + background-image: var(--pico-icon-loading); + background-size: 1em auto; + background-repeat: no-repeat; + content: ""; + vertical-align: -0.125em; +} +[aria-busy="true"]:not(input, select, textarea, html):not(:empty)::before { + margin-inline-end: calc(var(--pico-spacing) * 0.5); +} +[aria-busy="true"]:not(input, select, textarea, html):empty { + text-align: center; +} +[role="button"][aria-busy="true"], +[type="button"][aria-busy="true"], +[type="reset"][aria-busy="true"], +[type="submit"][aria-busy="true"], +a[aria-busy="true"], +button[aria-busy="true"] { + pointer-events: none; +} +:root { + --pico-scrollbar-width: 0px; +} +dialog { + display: flex; + z-index: 999; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + align-items: center; + justify-content: center; + width: inherit; + min-width: 100%; + height: inherit; + min-height: 100%; + padding: 0; + border: 0; + -webkit-backdrop-filter: var(--pico-modal-overlay-backdrop-filter); + backdrop-filter: var(--pico-modal-overlay-backdrop-filter); + background-color: var(--pico-modal-overlay-background-color); + color: var(--pico-color); +} +dialog article { + width: 100%; + max-height: calc(100vh - var(--pico-spacing) * 2); + margin: var(--pico-spacing); + overflow: auto; +} +@media (min-width: 576px) { + dialog article { + max-width: 510px; + } +} +@media (min-width: 768px) { + dialog article { + max-width: 700px; + } +} +dialog article > header > * { + margin-bottom: 0; +} +dialog article > header .close, +dialog article > header :is(a, button)[rel="prev"] { + margin: 0; + margin-left: var(--pico-spacing); + padding: 0; + float: right; +} +dialog article > footer { + text-align: right; +} +dialog article > footer [role="button"], +dialog article > footer button { + margin-bottom: 0; +} +dialog article > footer [role="button"]:not(:first-of-type), +dialog article > footer button:not(:first-of-type) { + margin-left: calc(var(--pico-spacing) * 0.5); +} +dialog article .close, +dialog article :is(a, button)[rel="prev"] { + display: block; + width: 1rem; + height: 1rem; + margin-top: calc(var(--pico-spacing) * -1); + margin-bottom: var(--pico-spacing); + margin-left: auto; + border: none; + background-image: var(--pico-icon-close); + background-position: center; + background-size: auto 1rem; + background-repeat: no-repeat; + background-color: transparent; + opacity: 0.5; + transition: opacity var(--pico-transition); +} +dialog + article + .close:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +dialog + article + :is(a, button)[rel="prev"]:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + opacity: 1; +} +dialog:not([open]), +dialog[open="false"] { + display: none; +} +.modal-is-open { + padding-right: var(--pico-scrollbar-width, 0); + overflow: hidden; + pointer-events: none; + touch-action: none; +} +.modal-is-open dialog { + pointer-events: auto; + touch-action: auto; +} +:where(.modal-is-opening, .modal-is-closing) dialog, +:where(.modal-is-opening, .modal-is-closing) dialog > article { + animation-duration: 0.2s; + animation-timing-function: ease-in-out; + animation-fill-mode: both; +} +:where(.modal-is-opening, .modal-is-closing) dialog { + animation-duration: 0.8s; + animation-name: modal-overlay; +} +:where(.modal-is-opening, .modal-is-closing) dialog > article { + animation-delay: 0.2s; + animation-name: modal; +} +.modal-is-closing dialog, +.modal-is-closing dialog > article { + animation-delay: 0s; + animation-direction: reverse; +} +@keyframes modal-overlay { + from { + -webkit-backdrop-filter: none; + backdrop-filter: none; + background-color: transparent; + } +} +@keyframes modal { + from { + transform: translateY(-100%); + opacity: 0; + } +} +:where(nav li)::before { + float: left; + content: "โ€‹"; +} +nav, +nav ul { + display: flex; +} +nav { + justify-content: space-between; + overflow: visible; +} +nav ol, +nav ul { + align-items: center; + margin-bottom: 0; + padding: 0; + list-style: none; +} +nav ol:first-of-type, +nav ul:first-of-type { + margin-left: calc(var(--pico-nav-element-spacing-horizontal) * -1); +} +nav ol:last-of-type, +nav ul:last-of-type { + margin-right: calc(var(--pico-nav-element-spacing-horizontal) * -1); +} +nav li { + display: inline-block; + margin: 0; + padding: var(--pico-nav-element-spacing-vertical) + var(--pico-nav-element-spacing-horizontal); +} +nav li :where(a, [role="link"]) { + display: inline-block; + margin: calc(var(--pico-nav-link-spacing-vertical) * -1) + calc(var(--pico-nav-link-spacing-horizontal) * -1); + padding: var(--pico-nav-link-spacing-vertical) + var(--pico-nav-link-spacing-horizontal); + border-radius: var(--pico-border-radius); +} +nav li :where(a, [role="link"]):not(:hover) { + text-decoration: none; +} +nav li [role="button"], +nav li [type="button"], +nav li button, +nav + li + input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), +nav li select { + height: auto; + margin-right: inherit; + margin-bottom: 0; + margin-left: inherit; + padding: calc( + var(--pico-nav-link-spacing-vertical) - var(--pico-border-width) * 2 + ) + var(--pico-nav-link-spacing-horizontal); +} +nav[aria-label="breadcrumb"] { + align-items: center; + justify-content: start; +} +nav[aria-label="breadcrumb"] ul li:not(:first-child) { + margin-inline-start: var(--pico-nav-link-spacing-horizontal); +} +nav[aria-label="breadcrumb"] ul li a { + margin: calc(var(--pico-nav-link-spacing-vertical) * -1) 0; + margin-inline-start: calc(var(--pico-nav-link-spacing-horizontal) * -1); +} +nav[aria-label="breadcrumb"] ul li:not(:last-child)::after { + display: inline-block; + position: absolute; + width: calc(var(--pico-nav-link-spacing-horizontal) * 4); + margin: 0 calc(var(--pico-nav-link-spacing-horizontal) * -1); + content: var(--pico-nav-breadcrumb-divider); + color: var(--pico-muted-color); + text-align: center; + text-decoration: none; + white-space: nowrap; +} +nav[aria-label="breadcrumb"] a[aria-current]:not([aria-current="false"]) { + background-color: transparent; + color: inherit; + text-decoration: none; + pointer-events: none; +} +aside li, +aside nav, +aside ol, +aside ul { + display: block; +} +aside li { + padding: calc(var(--pico-nav-element-spacing-vertical) * 0.5) + var(--pico-nav-element-spacing-horizontal); +} +aside li a { + display: block; +} +aside li [role="button"] { + margin: inherit; +} +[dir="rtl"] nav[aria-label="breadcrumb"] ul li:not(:last-child) ::after { + content: "\\"; +} +progress { + display: inline-block; + vertical-align: baseline; +} +progress { + -webkit-appearance: none; + -moz-appearance: none; + display: inline-block; + appearance: none; + width: 100%; + height: 0.5rem; + margin-bottom: calc(var(--pico-spacing) * 0.5); + overflow: hidden; + border: 0; + border-radius: var(--pico-border-radius); + background-color: var(--pico-progress-background-color); + color: var(--pico-progress-color); +} +progress::-webkit-progress-bar { + border-radius: var(--pico-border-radius); + background: 0 0; +} +progress[value]::-webkit-progress-value { + background-color: var(--pico-progress-color); + -webkit-transition: inline-size var(--pico-transition); + transition: inline-size var(--pico-transition); +} +progress::-moz-progress-bar { + background-color: var(--pico-progress-color); +} +@media (prefers-reduced-motion: no-preference) { + progress:indeterminate { + background: var(--pico-progress-background-color) + linear-gradient( + to right, + var(--pico-progress-color) 30%, + var(--pico-progress-background-color) 30% + ) + top left/150% 150% no-repeat; + animation: progress-indeterminate 1s linear infinite; + } + progress:indeterminate[value]::-webkit-progress-value { + background-color: transparent; + } + progress:indeterminate::-moz-progress-bar { + background-color: transparent; + } +} +@media (prefers-reduced-motion: no-preference) { + [dir="rtl"] progress:indeterminate { + animation-direction: reverse; + } +} +@keyframes progress-indeterminate { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} +[data-tooltip] { + position: relative; +} +[data-tooltip]:not(a, button, input) { + border-bottom: 1px dotted; + text-decoration: none; + cursor: help; +} +[data-tooltip]::after, +[data-tooltip]::before, +[data-tooltip][data-placement="top"]::after, +[data-tooltip][data-placement="top"]::before { + display: block; + z-index: 99; + position: absolute; + bottom: 100%; + left: 50%; + padding: 0.25rem 0.5rem; + overflow: hidden; + transform: translate(-50%, -0.25rem); + border-radius: var(--pico-border-radius); + background: var(--pico-tooltip-background-color); + content: attr(data-tooltip); + color: var(--pico-tooltip-color); + font-style: normal; + font-weight: var(--pico-font-weight); + font-size: 0.875rem; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + opacity: 0; + pointer-events: none; +} +[data-tooltip]::after, +[data-tooltip][data-placement="top"]::after { + padding: 0; + transform: translate(-50%, 0); + border-top: 0.3rem solid; + border-right: 0.3rem solid transparent; + border-left: 0.3rem solid transparent; + border-radius: 0; + background-color: transparent; + content: ""; + color: var(--pico-tooltip-background-color); +} +[data-tooltip][data-placement="bottom"]::after, +[data-tooltip][data-placement="bottom"]::before { + top: 100%; + bottom: auto; + transform: translate(-50%, 0.25rem); +} +[data-tooltip][data-placement="bottom"]:after { + transform: translate(-50%, -0.3rem); + border: 0.3rem solid transparent; + border-bottom: 0.3rem solid; +} +[data-tooltip][data-placement="left"]::after, +[data-tooltip][data-placement="left"]::before { + top: 50%; + right: 100%; + bottom: auto; + left: auto; + transform: translate(-0.25rem, -50%); +} +[data-tooltip][data-placement="left"]:after { + transform: translate(0.3rem, -50%); + border: 0.3rem solid transparent; + border-left: 0.3rem solid; +} +[data-tooltip][data-placement="right"]::after, +[data-tooltip][data-placement="right"]::before { + top: 50%; + right: auto; + bottom: auto; + left: 100%; + transform: translate(0.25rem, -50%); +} +[data-tooltip][data-placement="right"]:after { + transform: translate(-0.3rem, -50%); + border: 0.3rem solid transparent; + border-right: 0.3rem solid; +} +[data-tooltip]:focus::after, +[data-tooltip]:focus::before, +[data-tooltip]:hover::after, +[data-tooltip]:hover::before { + opacity: 1; +} +@media (hover: hover) and (pointer: fine) { + [data-tooltip]:focus::after, + [data-tooltip]:focus::before, + [data-tooltip]:hover::after, + [data-tooltip]:hover::before { + --pico-tooltip-slide-to: translate(-50%, -0.25rem); + transform: translate(-50%, 0.75rem); + animation-duration: 0.2s; + animation-fill-mode: forwards; + animation-name: tooltip-slide; + opacity: 0; + } + [data-tooltip]:focus::after, + [data-tooltip]:hover::after { + --pico-tooltip-caret-slide-to: translate(-50%, 0rem); + transform: translate(-50%, -0.25rem); + animation-name: tooltip-caret-slide; + } + [data-tooltip][data-placement="bottom"]:focus::after, + [data-tooltip][data-placement="bottom"]:focus::before, + [data-tooltip][data-placement="bottom"]:hover::after, + [data-tooltip][data-placement="bottom"]:hover::before { + --pico-tooltip-slide-to: translate(-50%, 0.25rem); + transform: translate(-50%, -0.75rem); + animation-name: tooltip-slide; + } + [data-tooltip][data-placement="bottom"]:focus::after, + [data-tooltip][data-placement="bottom"]:hover::after { + --pico-tooltip-caret-slide-to: translate(-50%, -0.3rem); + transform: translate(-50%, -0.5rem); + animation-name: tooltip-caret-slide; + } + [data-tooltip][data-placement="left"]:focus::after, + [data-tooltip][data-placement="left"]:focus::before, + [data-tooltip][data-placement="left"]:hover::after, + [data-tooltip][data-placement="left"]:hover::before { + --pico-tooltip-slide-to: translate(-0.25rem, -50%); + transform: translate(0.75rem, -50%); + animation-name: tooltip-slide; + } + [data-tooltip][data-placement="left"]:focus::after, + [data-tooltip][data-placement="left"]:hover::after { + --pico-tooltip-caret-slide-to: translate(0.3rem, -50%); + transform: translate(0.05rem, -50%); + animation-name: tooltip-caret-slide; + } + [data-tooltip][data-placement="right"]:focus::after, + [data-tooltip][data-placement="right"]:focus::before, + [data-tooltip][data-placement="right"]:hover::after, + [data-tooltip][data-placement="right"]:hover::before { + --pico-tooltip-slide-to: translate(0.25rem, -50%); + transform: translate(-0.75rem, -50%); + animation-name: tooltip-slide; + } + [data-tooltip][data-placement="right"]:focus::after, + [data-tooltip][data-placement="right"]:hover::after { + --pico-tooltip-caret-slide-to: translate(-0.3rem, -50%); + transform: translate(-0.05rem, -50%); + animation-name: tooltip-caret-slide; + } +} +@keyframes tooltip-slide { + to { + transform: var(--pico-tooltip-slide-to); + opacity: 1; + } +} +@keyframes tooltip-caret-slide { + 50% { + opacity: 0; + } + to { + transform: var(--pico-tooltip-caret-slide-to); + opacity: 1; + } +} +[aria-controls] { + cursor: pointer; +} +[aria-disabled="true"], +[disabled] { + cursor: not-allowed; +} +[aria-hidden="false"][hidden] { + display: initial; +} +[aria-hidden="false"][hidden]:not(:focus) { + clip: rect(0, 0, 0, 0); + position: absolute; +} +[tabindex], +a, +area, +button, +input, +label, +select, +summary, +textarea { + -ms-touch-action: manipulation; +} +[dir="rtl"] { + direction: rtl; +} +@media (prefers-reduced-motion: reduce) { + :not([aria-busy="true"]), + :not([aria-busy="true"])::after, + :not([aria-busy="true"])::before { + background-attachment: initial !important; + animation-duration: 1ms !important; + animation-delay: -1ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-delay: 0s !important; + transition-duration: 0s !important; + } +} diff --git a/src/render/libs/showdown.js.txt b/src/render/libs/showdown.js.txt new file mode 100644 index 0000000..129078b --- /dev/null +++ b/src/render/libs/showdown.js.txt @@ -0,0 +1,6286 @@ +(function(){ +/** + * Created by Tivie on 13-07-2015. + */ + +function getDefaultOpts (simple) { + 'use strict'; + + var defaultOptions = { + omitExtraWLInCodeBlocks: { + defaultValue: false, + describe: 'Omit the default extra whiteline added to code blocks', + type: 'boolean' + }, + noHeaderId: { + defaultValue: false, + describe: 'Turn on/off generated header id', + type: 'boolean' + }, + prefixHeaderId: { + defaultValue: false, + describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix', + type: 'string' + }, + rawPrefixHeaderId: { + defaultValue: false, + describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)', + type: 'boolean' + }, + ghCompatibleHeaderId: { + defaultValue: false, + describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)', + type: 'boolean' + }, + rawHeaderId: { + defaultValue: false, + describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids', + type: 'boolean' + }, + headerLevelStart: { + defaultValue: false, + describe: 'The header blocks level start', + type: 'integer' + }, + parseImgDimensions: { + defaultValue: false, + describe: 'Turn on/off image dimension parsing', + type: 'boolean' + }, + simplifiedAutoLink: { + defaultValue: false, + describe: 'Turn on/off GFM autolink style', + type: 'boolean' + }, + literalMidWordUnderscores: { + defaultValue: false, + describe: 'Parse midword underscores as literal underscores', + type: 'boolean' + }, + literalMidWordAsterisks: { + defaultValue: false, + describe: 'Parse midword asterisks as literal asterisks', + type: 'boolean' + }, + strikethrough: { + defaultValue: false, + describe: 'Turn on/off strikethrough support', + type: 'boolean' + }, + tables: { + defaultValue: false, + describe: 'Turn on/off tables support', + type: 'boolean' + }, + tablesHeaderId: { + defaultValue: false, + describe: 'Add an id to table headers', + type: 'boolean' + }, + ghCodeBlocks: { + defaultValue: true, + describe: 'Turn on/off GFM fenced code blocks support', + type: 'boolean' + }, + tasklists: { + defaultValue: false, + describe: 'Turn on/off GFM tasklist support', + type: 'boolean' + }, + smoothLivePreview: { + defaultValue: false, + describe: 'Prevents weird effects in live previews due to incomplete input', + type: 'boolean' + }, + smartIndentationFix: { + defaultValue: false, + describe: 'Tries to smartly fix indentation in es6 strings', + type: 'boolean' + }, + disableForced4SpacesIndentedSublists: { + defaultValue: false, + describe: 'Disables the requirement of indenting nested sublists by 4 spaces', + type: 'boolean' + }, + simpleLineBreaks: { + defaultValue: false, + describe: 'Parses simple line breaks as
(GFM Style)', + type: 'boolean' + }, + requireSpaceBeforeHeadingText: { + defaultValue: false, + describe: 'Makes adding a space between `#` and the header text mandatory (GFM Style)', + type: 'boolean' + }, + ghMentions: { + defaultValue: false, + describe: 'Enables github @mentions', + type: 'boolean' + }, + ghMentionsLink: { + defaultValue: 'https://github.com/{u}', + describe: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.', + type: 'string' + }, + encodeEmails: { + defaultValue: true, + describe: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities', + type: 'boolean' + }, + openLinksInNewWindow: { + defaultValue: false, + describe: 'Open all links in new windows', + type: 'boolean' + }, + backslashEscapesHTMLTags: { + defaultValue: false, + describe: 'Support for HTML Tag escaping. ex: \
foo\
', + type: 'boolean' + }, + emoji: { + defaultValue: false, + describe: 'Enable emoji support. Ex: `this is a :smile: emoji`', + type: 'boolean' + }, + underline: { + defaultValue: false, + describe: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `` and ``', + type: 'boolean' + }, + ellipsis: { + defaultValue: true, + describe: 'Replaces three dots with the ellipsis unicode character', + type: 'boolean' + }, + completeHTMLDocument: { + defaultValue: false, + describe: 'Outputs a complete html document, including ``, `` and `` tags', + type: 'boolean' + }, + metadata: { + defaultValue: false, + describe: 'Enable support for document metadata (defined at the top of the document between `ยซยซยซ` and `ยปยปยป` or between `---` and `---`).', + type: 'boolean' + }, + splitAdjacentBlockquotes: { + defaultValue: false, + describe: 'Split adjacent blockquote blocks', + type: 'boolean' + }, + moreStyling: { + defaultValue: false, + describe: 'Adds some useful styling css classes in the generated html', + type: 'boolean' + }, + relativePathBaseUrl: { + defaultValue: false, + describe: 'Prepends a base URL to relative paths', + type: 'string' + }, + }; + if (simple === false) { + return JSON.parse(JSON.stringify(defaultOptions)); + } + var ret = {}; + for (var opt in defaultOptions) { + if (defaultOptions.hasOwnProperty(opt)) { + ret[opt] = defaultOptions[opt].defaultValue; + } + } + return ret; +} + +function allOptionsOn () { + 'use strict'; + var options = getDefaultOpts(true), + ret = {}; + for (var opt in options) { + if (options.hasOwnProperty(opt)) { + ret[opt] = true; + } + } + return ret; +} + +/** + * Created by Tivie on 06-01-2015. + */ +// Private properties +var showdown = {}, + parsers = {}, + extensions = {}, + globalOptions = getDefaultOpts(true), + setFlavor = 'vanilla', + flavor = { + github: { + omitExtraWLInCodeBlocks: true, + simplifiedAutoLink: true, + literalMidWordUnderscores: true, + strikethrough: true, + tables: true, + tablesHeaderId: true, + ghCodeBlocks: true, + tasklists: true, + disableForced4SpacesIndentedSublists: true, + simpleLineBreaks: true, + requireSpaceBeforeHeadingText: true, + ghCompatibleHeaderId: true, + ghMentions: true, + backslashEscapesHTMLTags: true, + emoji: true, + splitAdjacentBlockquotes: true + }, + original: { + noHeaderId: true, + ghCodeBlocks: false + }, + ghost: { + omitExtraWLInCodeBlocks: true, + parseImgDimensions: true, + simplifiedAutoLink: true, + literalMidWordUnderscores: true, + strikethrough: true, + tables: true, + tablesHeaderId: true, + ghCodeBlocks: true, + tasklists: true, + smoothLivePreview: true, + simpleLineBreaks: true, + requireSpaceBeforeHeadingText: true, + ghMentions: false, + encodeEmails: true + }, + vanilla: getDefaultOpts(true), + allOn: allOptionsOn() + }; + +/** + * helper namespace + * @type {{}} + */ +showdown.helper = {}; + +/** + * TODO LEGACY SUPPORT CODE + * @type {{}} + */ +showdown.extensions = {}; + +/** + * Set a global option + * @static + * @param {string} key + * @param {*} value + * @returns {showdown} + */ +showdown.setOption = function (key, value) { + 'use strict'; + globalOptions[key] = value; + return this; +}; + +/** + * Get a global option + * @static + * @param {string} key + * @returns {*} + */ +showdown.getOption = function (key) { + 'use strict'; + return globalOptions[key]; +}; + +/** + * Get the global options + * @static + * @returns {{}} + */ +showdown.getOptions = function () { + 'use strict'; + return globalOptions; +}; + +/** + * Reset global options to the default values + * @static + */ +showdown.resetOptions = function () { + 'use strict'; + globalOptions = getDefaultOpts(true); +}; + +/** + * Set the flavor showdown should use as default + * @param {string} name + */ +showdown.setFlavor = function (name) { + 'use strict'; + if (!flavor.hasOwnProperty(name)) { + throw Error(name + ' flavor was not found'); + } + showdown.resetOptions(); + var preset = flavor[name]; + setFlavor = name; + for (var option in preset) { + if (preset.hasOwnProperty(option)) { + globalOptions[option] = preset[option]; + } + } +}; + +/** + * Get the currently set flavor + * @returns {string} + */ +showdown.getFlavor = function () { + 'use strict'; + return setFlavor; +}; + +/** + * Get the options of a specified flavor. Returns undefined if the flavor was not found + * @param {string} name Name of the flavor + * @returns {{}|undefined} + */ +showdown.getFlavorOptions = function (name) { + 'use strict'; + if (flavor.hasOwnProperty(name)) { + return flavor[name]; + } +}; + +/** + * Get the default options + * @static + * @param {boolean} [simple=true] + * @returns {{}} + */ +showdown.getDefaultOptions = function (simple) { + 'use strict'; + return getDefaultOpts(simple); +}; + +/** + * Get or set a subParser + * + * subParser(name) - Get a registered subParser + * subParser(name, func) - Register a subParser + * @static + * @param {string} name + * @param {function} [func] + * @returns {*} + */ +showdown.subParser = function (name, func) { + 'use strict'; + if (showdown.helper.isString(name)) { + if (typeof func !== 'undefined') { + parsers[name] = func; + } else { + if (parsers.hasOwnProperty(name)) { + return parsers[name]; + } else { + throw Error('SubParser named ' + name + ' not registered!'); + } + } + } else { + throw Error('showdown.subParser function first argument must be a string (the name of the subparser)'); + } +}; + +/** + * Gets or registers an extension + * @static + * @param {string} name + * @param {object|object[]|function=} ext + * @returns {*} + */ +showdown.extension = function (name, ext) { + 'use strict'; + + if (!showdown.helper.isString(name)) { + throw Error('Extension \'name\' must be a string'); + } + + name = showdown.helper.stdExtName(name); + + // Getter + if (showdown.helper.isUndefined(ext)) { + if (!extensions.hasOwnProperty(name)) { + throw Error('Extension named ' + name + ' is not registered!'); + } + return extensions[name]; + + // Setter + } else { + // Expand extension if it's wrapped in a function + if (typeof ext === 'function') { + ext = ext(); + } + + // Ensure extension is an array + if (!showdown.helper.isArray(ext)) { + ext = [ext]; + } + + var validExtension = validate(ext, name); + + if (validExtension.valid) { + extensions[name] = ext; + } else { + throw Error(validExtension.error); + } + } +}; + +/** + * Gets all extensions registered + * @returns {{}} + */ +showdown.getAllExtensions = function () { + 'use strict'; + return extensions; +}; + +/** + * Remove an extension + * @param {string} name + */ +showdown.removeExtension = function (name) { + 'use strict'; + delete extensions[name]; +}; + +/** + * Removes all extensions + */ +showdown.resetExtensions = function () { + 'use strict'; + extensions = {}; +}; + +/** + * Validate extension + * @param {array} extension + * @param {string} name + * @returns {{valid: boolean, error: string}} + */ +function validate (extension, name) { + 'use strict'; + + var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension', + ret = { + valid: true, + error: '' + }; + + if (!showdown.helper.isArray(extension)) { + extension = [extension]; + } + + for (var i = 0; i < extension.length; ++i) { + var baseMsg = errMsg + ' sub-extension ' + i + ': ', + ext = extension[i]; + if (typeof ext !== 'object') { + ret.valid = false; + ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given'; + return ret; + } + + if (!showdown.helper.isString(ext.type)) { + ret.valid = false; + ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given'; + return ret; + } + + var type = ext.type = ext.type.toLowerCase(); + + // normalize extension type + if (type === 'language') { + type = ext.type = 'lang'; + } + + if (type === 'html') { + type = ext.type = 'output'; + } + + if (type !== 'lang' && type !== 'output' && type !== 'listener') { + ret.valid = false; + ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"'; + return ret; + } + + if (type === 'listener') { + if (showdown.helper.isUndefined(ext.listeners)) { + ret.valid = false; + ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"'; + return ret; + } + } else { + if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) { + ret.valid = false; + ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method'; + return ret; + } + } + + if (ext.listeners) { + if (typeof ext.listeners !== 'object') { + ret.valid = false; + ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given'; + return ret; + } + for (var ln in ext.listeners) { + if (ext.listeners.hasOwnProperty(ln)) { + if (typeof ext.listeners[ln] !== 'function') { + ret.valid = false; + ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln + + ' must be a function but ' + typeof ext.listeners[ln] + ' given'; + return ret; + } + } + } + } + + if (ext.filter) { + if (typeof ext.filter !== 'function') { + ret.valid = false; + ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given'; + return ret; + } + } else if (ext.regex) { + if (showdown.helper.isString(ext.regex)) { + ext.regex = new RegExp(ext.regex, 'g'); + } + if (!(ext.regex instanceof RegExp)) { + ret.valid = false; + ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given'; + return ret; + } + if (showdown.helper.isUndefined(ext.replace)) { + ret.valid = false; + ret.error = baseMsg + '"regex" extensions must implement a replace string or function'; + return ret; + } + } + } + return ret; +} + +/** + * Validate extension + * @param {object} ext + * @returns {boolean} + */ +showdown.validateExtension = function (ext) { + 'use strict'; + + var validateExtension = validate(ext, null); + if (!validateExtension.valid) { + console.warn(validateExtension.error); + return false; + } + return true; +}; + +/** + * showdownjs helper functions + */ + +if (!showdown.hasOwnProperty('helper')) { + showdown.helper = {}; +} + +if (typeof this === 'undefined' && typeof window !== 'undefined') { + showdown.helper.document = window.document; +} else { + if (typeof this.document === 'undefined' && typeof this.window === 'undefined') { + var jsdom = require('jsdom'); + this.window = new jsdom.JSDOM('', {}).window; // jshint ignore:line + } + showdown.helper.document = this.window.document; +} + +/** + * Check if var is string + * @static + * @param {string} a + * @returns {boolean} + */ +showdown.helper.isString = function (a) { + 'use strict'; + return (typeof a === 'string' || a instanceof String); +}; + +/** + * Check if var is a function + * @static + * @param {*} a + * @returns {boolean} + */ +showdown.helper.isFunction = function (a) { + 'use strict'; + var getType = {}; + return a && getType.toString.call(a) === '[object Function]'; +}; + +/** + * isArray helper function + * @static + * @param {*} a + * @returns {boolean} + */ +showdown.helper.isArray = function (a) { + 'use strict'; + return Array.isArray(a); +}; + +/** + * Check if value is undefined + * @static + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + */ +showdown.helper.isUndefined = function (value) { + 'use strict'; + return typeof value === 'undefined'; +}; + +/** + * ForEach helper function + * Iterates over Arrays and Objects (own properties only) + * @static + * @param {*} obj + * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object + */ +showdown.helper.forEach = function (obj, callback) { + 'use strict'; + // check if obj is defined + if (showdown.helper.isUndefined(obj)) { + throw new Error('obj param is required'); + } + + if (showdown.helper.isUndefined(callback)) { + throw new Error('callback param is required'); + } + + if (!showdown.helper.isFunction(callback)) { + throw new Error('callback param must be a function/closure'); + } + + if (typeof obj.forEach === 'function') { + obj.forEach(callback); + } else if (showdown.helper.isArray(obj)) { + for (var i = 0; i < obj.length; i++) { + callback(obj[i], i, obj); + } + } else if (typeof (obj) === 'object') { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + callback(obj[prop], prop, obj); + } + } + } else { + throw new Error('obj does not seem to be an array or an iterable object'); + } +}; + +/** + * Standardidize extension name + * @static + * @param {string} s extension name + * @returns {string} + */ +showdown.helper.stdExtName = function (s) { + 'use strict'; + return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase(); +}; + +function escapeCharactersCallback (wholeMatch, m1) { + 'use strict'; + var charCodeToEscape = m1.charCodeAt(0); + return 'ยจE' + charCodeToEscape + 'E'; +} + +/** + * Callback used to escape characters when passing through String.replace + * @static + * @param {string} wholeMatch + * @param {string} m1 + * @returns {string} + */ +showdown.helper.escapeCharactersCallback = escapeCharactersCallback; + +/** + * Escape characters in a string + * @static + * @param {string} text + * @param {string} charsToEscape + * @param {boolean} afterBackslash + * @returns {string|void|*} + */ +showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) { + 'use strict'; + // First we have to escape the escape characters so that + // we can build a character class out of them + var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])'; + + if (afterBackslash) { + regexString = '\\\\' + regexString; + } + + var regex = new RegExp(regexString, 'g'); + text = text.replace(regex, escapeCharactersCallback); + + return text; +}; + +var rgxFindMatchPos = function (str, left, right, flags) { + 'use strict'; + var f = flags || '', + g = f.indexOf('g') > -1, + x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')), + l = new RegExp(left, f.replace(/g/g, '')), + pos = [], + t, s, m, start, end; + + do { + t = 0; + while ((m = x.exec(str))) { + if (l.test(m[0])) { + if (!(t++)) { + s = x.lastIndex; + start = s - m[0].length; + } + } else if (t) { + if (!--t) { + end = m.index + m[0].length; + var obj = { + left: {start: start, end: s}, + match: {start: s, end: m.index}, + right: {start: m.index, end: end}, + wholeMatch: {start: start, end: end} + }; + pos.push(obj); + if (!g) { + return pos; + } + } + } + } + } while (t && (x.lastIndex = s)); + + return pos; +}; + +/** + * matchRecursiveRegExp + * + * (c) 2007 Steven Levithan + * MIT License + * + * Accepts a string to search, a left and right format delimiter + * as regex patterns, and optional regex flags. Returns an array + * of matches, allowing nested instances of left/right delimiters. + * Use the "g" flag to return all matches, otherwise only the + * first is returned. Be careful to ensure that the left and + * right format delimiters produce mutually exclusive matches. + * Backreferences are not supported within the right delimiter + * due to how it is internally combined with the left delimiter. + * When matching strings whose format delimiters are unbalanced + * to the left or right, the output is intentionally as a + * conventional regex library with recursion support would + * produce, e.g. "<" and ">" both produce ["x"] when using + * "<" and ">" as the delimiters (both strings contain a single, + * balanced instance of ""). + * + * examples: + * matchRecursiveRegExp("test", "\\(", "\\)") + * returns: [] + * matchRecursiveRegExp(">>t<>", "<", ">", "g") + * returns: ["t<>", ""] + * matchRecursiveRegExp("
test
", "]*>", "", "gi") + * returns: ["test"] + */ +showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) { + 'use strict'; + + var matchPos = rgxFindMatchPos (str, left, right, flags), + results = []; + + for (var i = 0; i < matchPos.length; ++i) { + results.push([ + str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), + str.slice(matchPos[i].match.start, matchPos[i].match.end), + str.slice(matchPos[i].left.start, matchPos[i].left.end), + str.slice(matchPos[i].right.start, matchPos[i].right.end) + ]); + } + return results; +}; + +/** + * + * @param {string} str + * @param {string|function} replacement + * @param {string} left + * @param {string} right + * @param {string} flags + * @returns {string} + */ +showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) { + 'use strict'; + + if (!showdown.helper.isFunction(replacement)) { + var repStr = replacement; + replacement = function () { + return repStr; + }; + } + + var matchPos = rgxFindMatchPos(str, left, right, flags), + finalStr = str, + lng = matchPos.length; + + if (lng > 0) { + var bits = []; + if (matchPos[0].wholeMatch.start !== 0) { + bits.push(str.slice(0, matchPos[0].wholeMatch.start)); + } + for (var i = 0; i < lng; ++i) { + bits.push( + replacement( + str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), + str.slice(matchPos[i].match.start, matchPos[i].match.end), + str.slice(matchPos[i].left.start, matchPos[i].left.end), + str.slice(matchPos[i].right.start, matchPos[i].right.end) + ) + ); + if (i < lng - 1) { + bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start)); + } + } + if (matchPos[lng - 1].wholeMatch.end < str.length) { + bits.push(str.slice(matchPos[lng - 1].wholeMatch.end)); + } + finalStr = bits.join(''); + } + return finalStr; +}; + +/** + * Returns the index within the passed String object of the first occurrence of the specified regex, + * starting the search at fromIndex. Returns -1 if the value is not found. + * + * @param {string} str string to search + * @param {RegExp} regex Regular expression to search + * @param {int} [fromIndex = 0] Index to start the search + * @returns {Number} + * @throws InvalidArgumentError + */ +showdown.helper.regexIndexOf = function (str, regex, fromIndex) { + 'use strict'; + if (!showdown.helper.isString(str)) { + throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string'; + } + if (!(regex instanceof RegExp)) { + throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp'; + } + var indexOf = str.substring(fromIndex || 0).search(regex); + return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf; +}; + +/** + * Splits the passed string object at the defined index, and returns an array composed of the two substrings + * @param {string} str string to split + * @param {int} index index to split string at + * @returns {[string,string]} + * @throws InvalidArgumentError + */ +showdown.helper.splitAtIndex = function (str, index) { + 'use strict'; + if (!showdown.helper.isString(str)) { + throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string'; + } + return [str.substring(0, index), str.substring(index)]; +}; + +/** + * Obfuscate an e-mail address through the use of Character Entities, + * transforming ASCII characters into their equivalent decimal or hex entities. + * + * Since it has a random component, subsequent calls to this function produce different results + * + * @param {string} mail + * @param {string} seed + * @returns {string} + */ +showdown.helper.encodeEmailAddress = function (mail, seed) { + 'use strict'; + var encode = [ + function (ch) { + return '&#' + ch.charCodeAt(0) + ';'; + }, + function (ch) { + return '&#x' + ch.charCodeAt(0).toString(16) + ';'; + }, + function (ch) { + return ch; + } + ]; + + mail = mail.replace(/./g, function (ch) { + if (ch === '@') { + // this *must* be encoded. I insist. + ch = encode[Math.floor(Math.random() * 2)](ch); + } else { + var r = Math.random(); + // roughly 10% raw, 45% hex, 45% dec + ch = ( + r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch) + ); + } + return ch; + }); + + return mail; +}; + +/** + * String.prototype.repeat polyfill + * + * @param {string} str + * @param {int} count + * @returns {string} + */ +showdown.helper.repeat = function (str, count) { + 'use strict'; + // use built-in method if it's available + if (!showdown.helper.isUndefined(String.prototype.repeat)) { + return str.repeat(count); + } + str = '' + str; + if (count < 0) { + throw new RangeError('repeat count must be non-negative'); + } + if (count === Infinity) { + throw new RangeError('repeat count must be less than infinity'); + } + count = Math.floor(count); + if (str.length === 0 || count === 0) { + return ''; + } + // Ensuring count is a 31-bit integer allows us to heavily optimize the + // main part. But anyway, most current (August 2014) browsers can't handle + // strings 1 << 28 chars or longer, so: + /*jshint bitwise: false*/ + if (str.length * count >= 1 << 28) { + throw new RangeError('repeat count must not overflow maximum string size'); + } + /*jshint bitwise: true*/ + var maxCount = str.length * count; + count = Math.floor(Math.log(count) / Math.log(2)); + while (count) { + str += str; + count--; + } + str += str.substring(0, maxCount - str.length); + return str; +}; + +/** + * String.prototype.padEnd polyfill + * + * @param str + * @param targetLength + * @param padString + * @returns {string} + */ +showdown.helper.padEnd = function padEnd (str, targetLength, padString) { + 'use strict'; + /*jshint bitwise: false*/ + // eslint-disable-next-line space-infix-ops + targetLength = targetLength>>0; //floor if number or convert non-number to 0; + /*jshint bitwise: true*/ + padString = String(padString || ' '); + if (str.length > targetLength) { + return String(str); + } else { + targetLength = targetLength - str.length; + if (targetLength > padString.length) { + padString += showdown.helper.repeat(padString, targetLength / padString.length); //append to original to ensure we are longer than needed + } + return String(str) + padString.slice(0,targetLength); + } +}; + +/** + * Unescape HTML entities + * @param txt + * @returns {string} + */ +showdown.helper.unescapeHTMLEntities = function (txt) { + 'use strict'; + + return txt + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&'); +}; + +showdown.helper._hashHTMLSpan = function (html, globals) { + return 'ยจC' + (globals.gHtmlSpans.push(html) - 1) + 'C'; +}; + +/** + * Prepends a base URL to relative paths. + * + * @param {string} baseUrl the base URL to prepend to a relative path + * @param {string} url the path to modify, which may be relative + * @returns {string} the full URL + */ +showdown.helper.applyBaseUrl = function (baseUrl, url) { + // Only prepend if given a base URL and the path is not absolute. + if (baseUrl && !this.isAbsolutePath(url)) { + var urlResolve = require('url').resolve; + url = urlResolve(baseUrl, url); + } + + return url; +}; + +/** + * Checks if the given path is absolute. + * + * @param {string} path the path to test for absolution + * @returns {boolean} `true` if the given path is absolute, else `false` + */ +showdown.helper.isAbsolutePath = function (path) { + // Absolute paths begin with '[protocol:]//' or '#' (anchors) + return /(^([a-z]+:)?\/\/)|(^#)/i.test(path); +}; + +/** + * Showdown's Event Object + * @param {string} name Name of the event + * @param {string} text Text + * @param {{}} params optional. params of the event + * @constructor + */ +showdown.helper.Event = function (name, text, params) { + 'use strict'; + + var regexp = params.regexp || null; + var matches = params.matches || {}; + var options = params.options || {}; + var converter = params.converter || null; + var globals = params.globals || {}; + + /** + * Get the name of the event + * @returns {string} + */ + this.getName = function () { + return name; + }; + + this.getEventName = function () { + return name; + }; + + this._stopExecution = false; + + this.parsedText = params.parsedText || null; + + this.getRegexp = function () { + return regexp; + }; + + this.getOptions = function () { + return options; + }; + + this.getConverter = function () { + return converter; + }; + + this.getGlobals = function () { + return globals; + }; + + this.getCapturedText = function () { + return text; + }; + + this.getText = function () { + return text; + }; + + this.setText = function (newText) { + text = newText; + }; + + this.getMatches = function () { + return matches; + }; + + this.setMatches = function (newMatches) { + matches = newMatches; + }; + + this.preventDefault = function (bool) { + this._stopExecution = !bool; + }; +}; + +/** + * POLYFILLS + */ +// use this instead of builtin is undefined for IE8 compatibility +if (typeof (console) === 'undefined') { + console = { + warn: function (msg) { + 'use strict'; + alert(msg); + }, + log: function (msg) { + 'use strict'; + alert(msg); + }, + error: function (msg) { + 'use strict'; + throw msg; + } + }; +} + +/** + * Common regexes. + * We declare some common regexes to improve performance + */ +showdown.helper.regexes = { + asteriskDashTildeAndColon: /([*_:~])/g, + asteriskDashAndTilde: /([*_~])/g +}; + +/** + * EMOJIS LIST + */ +showdown.helper.emojis = { + '100': '\ud83d\udcaf', + '1234': '\ud83d\udd22', + '+1': '\ud83d\udc4d', + '-1': '\ud83d\udc4e', + '1st_place_medal': '\ud83e\udd47', + '2nd_place_medal': '\ud83e\udd48', + '3rd_place_medal': '\ud83e\udd49', + '8ball': '\ud83c\udfb1', + 'a': '\ud83c\udd70\ufe0f', + 'ab': '\ud83c\udd8e', + 'abacus': '\ud83e\uddee', + 'abc': '\ud83d\udd24', + 'abcd': '\ud83d\udd21', + 'accept': '\ud83c\ude51', + 'adhesive_bandage': '\ud83e\ude79', + 'adult': '\ud83e\uddd1', + 'aerial_tramway': '\ud83d\udea1', + 'afghanistan': '\ud83c\udde6\ud83c\uddeb', + 'airplane': '\u2708\ufe0f', + 'aland_islands': '\ud83c\udde6\ud83c\uddfd', + 'alarm_clock': '\u23f0', + 'albania': '\ud83c\udde6\ud83c\uddf1', + 'alembic': '\u2697\ufe0f', + 'algeria': '\ud83c\udde9\ud83c\uddff', + 'alien': '\ud83d\udc7d', + 'ambulance': '\ud83d\ude91', + 'american_samoa': '\ud83c\udde6\ud83c\uddf8', + 'amphora': '\ud83c\udffa', + 'anchor': '\u2693', + 'andorra': '\ud83c\udde6\ud83c\udde9', + 'angel': '\ud83d\udc7c', + 'anger': '\ud83d\udca2', + 'angola': '\ud83c\udde6\ud83c\uddf4', + 'angry': '\ud83d\ude20', + 'anguilla': '\ud83c\udde6\ud83c\uddee', + 'anguished': '\ud83d\ude27', + 'ant': '\ud83d\udc1c', + 'antarctica': '\ud83c\udde6\ud83c\uddf6', + 'antigua_barbuda': '\ud83c\udde6\ud83c\uddec', + 'apple': '\ud83c\udf4e', + 'aquarius': '\u2652', + 'argentina': '\ud83c\udde6\ud83c\uddf7', + 'aries': '\u2648', + 'armenia': '\ud83c\udde6\ud83c\uddf2', + 'arrow_backward': '\u25c0\ufe0f', + 'arrow_double_down': '\u23ec', + 'arrow_double_up': '\u23eb', + 'arrow_down': '\u2b07\ufe0f', + 'arrow_down_small': '\ud83d\udd3d', + 'arrow_forward': '\u25b6\ufe0f', + 'arrow_heading_down': '\u2935\ufe0f', + 'arrow_heading_up': '\u2934\ufe0f', + 'arrow_left': '\u2b05\ufe0f', + 'arrow_lower_left': '\u2199\ufe0f', + 'arrow_lower_right': '\u2198\ufe0f', + 'arrow_right': '\u27a1\ufe0f', + 'arrow_right_hook': '\u21aa\ufe0f', + 'arrow_up': '\u2b06\ufe0f', + 'arrow_up_down': '\u2195\ufe0f', + 'arrow_up_small': '\ud83d\udd3c', + 'arrow_upper_left': '\u2196\ufe0f', + 'arrow_upper_right': '\u2197\ufe0f', + 'arrows_clockwise': '\ud83d\udd03', + 'arrows_counterclockwise': '\ud83d\udd04', + 'art': '\ud83c\udfa8', + 'articulated_lorry': '\ud83d\ude9b', + 'artificial_satellite': '\ud83d\udef0\ufe0f', + 'artist': '\ud83e\uddd1\u200d\ud83c\udfa8', + 'aruba': '\ud83c\udde6\ud83c\uddfc', + 'ascension_island': '\ud83c\udde6\ud83c\udde8', + 'asterisk': '*\ufe0f\u20e3', + 'astonished': '\ud83d\ude32', + 'astronaut': '\ud83e\uddd1\u200d\ud83d\ude80', + 'athletic_shoe': '\ud83d\udc5f', + 'atm': '\ud83c\udfe7', + 'atom_symbol': '\u269b\ufe0f', + 'australia': '\ud83c\udde6\ud83c\uddfa', + 'austria': '\ud83c\udde6\ud83c\uddf9', + 'auto_rickshaw': '\ud83d\udefa', + 'avocado': '\ud83e\udd51', + 'axe': '\ud83e\ude93', + 'azerbaijan': '\ud83c\udde6\ud83c\uddff', + 'b': '\ud83c\udd71\ufe0f', + 'baby': '\ud83d\udc76', + 'baby_bottle': '\ud83c\udf7c', + 'baby_chick': '\ud83d\udc24', + 'baby_symbol': '\ud83d\udebc', + 'back': '\ud83d\udd19', + 'bacon': '\ud83e\udd53', + 'badger': '\ud83e\udda1', + 'badminton': '\ud83c\udff8', + 'bagel': '\ud83e\udd6f', + 'baggage_claim': '\ud83d\udec4', + 'baguette_bread': '\ud83e\udd56', + 'bahamas': '\ud83c\udde7\ud83c\uddf8', + 'bahrain': '\ud83c\udde7\ud83c\udded', + 'balance_scale': '\u2696\ufe0f', + 'bald_man': '\ud83d\udc68\u200d\ud83e\uddb2', + 'bald_woman': '\ud83d\udc69\u200d\ud83e\uddb2', + 'ballet_shoes': '\ud83e\ude70', + 'balloon': '\ud83c\udf88', + 'ballot_box': '\ud83d\uddf3\ufe0f', + 'ballot_box_with_check': '\u2611\ufe0f', + 'bamboo': '\ud83c\udf8d', + 'banana': '\ud83c\udf4c', + 'bangbang': '\u203c\ufe0f', + 'bangladesh': '\ud83c\udde7\ud83c\udde9', + 'banjo': '\ud83e\ude95', + 'bank': '\ud83c\udfe6', + 'bar_chart': '\ud83d\udcca', + 'barbados': '\ud83c\udde7\ud83c\udde7', + 'barber': '\ud83d\udc88', + 'baseball': '\u26be', + 'basket': '\ud83e\uddfa', + 'basketball': '\ud83c\udfc0', + 'basketball_man': '\u26f9\ufe0f\u200d\u2642\ufe0f', + 'basketball_woman': '\u26f9\ufe0f\u200d\u2640\ufe0f', + 'bat': '\ud83e\udd87', + 'bath': '\ud83d\udec0', + 'bathtub': '\ud83d\udec1', + 'battery': '\ud83d\udd0b', + 'beach_umbrella': '\ud83c\udfd6\ufe0f', + 'bear': '\ud83d\udc3b', + 'bearded_person': '\ud83e\uddd4', + 'bed': '\ud83d\udecf\ufe0f', + 'bee': '\ud83d\udc1d', + 'beer': '\ud83c\udf7a', + 'beers': '\ud83c\udf7b', + 'beetle': '\ud83d\udc1e', + 'beginner': '\ud83d\udd30', + 'belarus': '\ud83c\udde7\ud83c\uddfe', + 'belgium': '\ud83c\udde7\ud83c\uddea', + 'belize': '\ud83c\udde7\ud83c\uddff', + 'bell': '\ud83d\udd14', + 'bellhop_bell': '\ud83d\udece\ufe0f', + 'benin': '\ud83c\udde7\ud83c\uddef', + 'bento': '\ud83c\udf71', + 'bermuda': '\ud83c\udde7\ud83c\uddf2', + 'beverage_box': '\ud83e\uddc3', + 'bhutan': '\ud83c\udde7\ud83c\uddf9', + 'bicyclist': '\ud83d\udeb4', + 'bike': '\ud83d\udeb2', + 'biking_man': '\ud83d\udeb4\u200d\u2642\ufe0f', + 'biking_woman': '\ud83d\udeb4\u200d\u2640\ufe0f', + 'bikini': '\ud83d\udc59', + 'billed_cap': '\ud83e\udde2', + 'biohazard': '\u2623\ufe0f', + 'bird': '\ud83d\udc26', + 'birthday': '\ud83c\udf82', + 'black_circle': '\u26ab', + 'black_flag': '\ud83c\udff4', + 'black_heart': '\ud83d\udda4', + 'black_joker': '\ud83c\udccf', + 'black_large_square': '\u2b1b', + 'black_medium_small_square': '\u25fe', + 'black_medium_square': '\u25fc\ufe0f', + 'black_nib': '\u2712\ufe0f', + 'black_small_square': '\u25aa\ufe0f', + 'black_square_button': '\ud83d\udd32', + 'blond_haired_man': '\ud83d\udc71\u200d\u2642\ufe0f', + 'blond_haired_person': '\ud83d\udc71', + 'blond_haired_woman': '\ud83d\udc71\u200d\u2640\ufe0f', + 'blonde_woman': '\ud83d\udc71\u200d\u2640\ufe0f', + 'blossom': '\ud83c\udf3c', + 'blowfish': '\ud83d\udc21', + 'blue_book': '\ud83d\udcd8', + 'blue_car': '\ud83d\ude99', + 'blue_heart': '\ud83d\udc99', + 'blue_square': '\ud83d\udfe6', + 'blush': '\ud83d\ude0a', + 'boar': '\ud83d\udc17', + 'boat': '\u26f5', + 'bolivia': '\ud83c\udde7\ud83c\uddf4', + 'bomb': '\ud83d\udca3', + 'bone': '\ud83e\uddb4', + 'book': '\ud83d\udcd6', + 'bookmark': '\ud83d\udd16', + 'bookmark_tabs': '\ud83d\udcd1', + 'books': '\ud83d\udcda', + 'boom': '\ud83d\udca5', + 'boot': '\ud83d\udc62', + 'bosnia_herzegovina': '\ud83c\udde7\ud83c\udde6', + 'botswana': '\ud83c\udde7\ud83c\uddfc', + 'bouncing_ball_man': '\u26f9\ufe0f\u200d\u2642\ufe0f', + 'bouncing_ball_person': '\u26f9\ufe0f', + 'bouncing_ball_woman': '\u26f9\ufe0f\u200d\u2640\ufe0f', + 'bouquet': '\ud83d\udc90', + 'bouvet_island': '\ud83c\udde7\ud83c\uddfb', + 'bow': '\ud83d\ude47', + 'bow_and_arrow': '\ud83c\udff9', + 'bowing_man': '\ud83d\ude47\u200d\u2642\ufe0f', + 'bowing_woman': '\ud83d\ude47\u200d\u2640\ufe0f', + 'bowl_with_spoon': '\ud83e\udd63', + 'bowling': '\ud83c\udfb3', + 'boxing_glove': '\ud83e\udd4a', + 'boy': '\ud83d\udc66', + 'brain': '\ud83e\udde0', + 'brazil': '\ud83c\udde7\ud83c\uddf7', + 'bread': '\ud83c\udf5e', + 'breast_feeding': '\ud83e\udd31', + 'bricks': '\ud83e\uddf1', + 'bride_with_veil': '\ud83d\udc70', + 'bridge_at_night': '\ud83c\udf09', + 'briefcase': '\ud83d\udcbc', + 'british_indian_ocean_territory': '\ud83c\uddee\ud83c\uddf4', + 'british_virgin_islands': '\ud83c\uddfb\ud83c\uddec', + 'broccoli': '\ud83e\udd66', + 'broken_heart': '\ud83d\udc94', + 'broom': '\ud83e\uddf9', + 'brown_circle': '\ud83d\udfe4', + 'brown_heart': '\ud83e\udd0e', + 'brown_square': '\ud83d\udfeb', + 'brunei': '\ud83c\udde7\ud83c\uddf3', + 'bug': '\ud83d\udc1b', + 'building_construction': '\ud83c\udfd7\ufe0f', + 'bulb': '\ud83d\udca1', + 'bulgaria': '\ud83c\udde7\ud83c\uddec', + 'bullettrain_front': '\ud83d\ude85', + 'bullettrain_side': '\ud83d\ude84', + 'burkina_faso': '\ud83c\udde7\ud83c\uddeb', + 'burrito': '\ud83c\udf2f', + 'burundi': '\ud83c\udde7\ud83c\uddee', + 'bus': '\ud83d\ude8c', + 'business_suit_levitating': '\ud83d\udd74\ufe0f', + 'busstop': '\ud83d\ude8f', + 'bust_in_silhouette': '\ud83d\udc64', + 'busts_in_silhouette': '\ud83d\udc65', + 'butter': '\ud83e\uddc8', + 'butterfly': '\ud83e\udd8b', + 'cactus': '\ud83c\udf35', + 'cake': '\ud83c\udf70', + 'calendar': '\ud83d\udcc6', + 'call_me_hand': '\ud83e\udd19', + 'calling': '\ud83d\udcf2', + 'cambodia': '\ud83c\uddf0\ud83c\udded', + 'camel': '\ud83d\udc2b', + 'camera': '\ud83d\udcf7', + 'camera_flash': '\ud83d\udcf8', + 'cameroon': '\ud83c\udde8\ud83c\uddf2', + 'camping': '\ud83c\udfd5\ufe0f', + 'canada': '\ud83c\udde8\ud83c\udde6', + 'canary_islands': '\ud83c\uddee\ud83c\udde8', + 'cancer': '\u264b', + 'candle': '\ud83d\udd6f\ufe0f', + 'candy': '\ud83c\udf6c', + 'canned_food': '\ud83e\udd6b', + 'canoe': '\ud83d\udef6', + 'cape_verde': '\ud83c\udde8\ud83c\uddfb', + 'capital_abcd': '\ud83d\udd20', + 'capricorn': '\u2651', + 'car': '\ud83d\ude97', + 'card_file_box': '\ud83d\uddc3\ufe0f', + 'card_index': '\ud83d\udcc7', + 'card_index_dividers': '\ud83d\uddc2\ufe0f', + 'caribbean_netherlands': '\ud83c\udde7\ud83c\uddf6', + 'carousel_horse': '\ud83c\udfa0', + 'carrot': '\ud83e\udd55', + 'cartwheeling': '\ud83e\udd38', + 'cat': '\ud83d\udc31', + 'cat2': '\ud83d\udc08', + 'cayman_islands': '\ud83c\uddf0\ud83c\uddfe', + 'cd': '\ud83d\udcbf', + 'central_african_republic': '\ud83c\udde8\ud83c\uddeb', + 'ceuta_melilla': '\ud83c\uddea\ud83c\udde6', + 'chad': '\ud83c\uddf9\ud83c\udde9', + 'chains': '\u26d3\ufe0f', + 'chair': '\ud83e\ude91', + 'champagne': '\ud83c\udf7e', + 'chart': '\ud83d\udcb9', + 'chart_with_downwards_trend': '\ud83d\udcc9', + 'chart_with_upwards_trend': '\ud83d\udcc8', + 'checkered_flag': '\ud83c\udfc1', + 'cheese': '\ud83e\uddc0', + 'cherries': '\ud83c\udf52', + 'cherry_blossom': '\ud83c\udf38', + 'chess_pawn': '\u265f\ufe0f', + 'chestnut': '\ud83c\udf30', + 'chicken': '\ud83d\udc14', + 'child': '\ud83e\uddd2', + 'children_crossing': '\ud83d\udeb8', + 'chile': '\ud83c\udde8\ud83c\uddf1', + 'chipmunk': '\ud83d\udc3f\ufe0f', + 'chocolate_bar': '\ud83c\udf6b', + 'chopsticks': '\ud83e\udd62', + 'christmas_island': '\ud83c\udde8\ud83c\uddfd', + 'christmas_tree': '\ud83c\udf84', + 'church': '\u26ea', + 'cinema': '\ud83c\udfa6', + 'circus_tent': '\ud83c\udfaa', + 'city_sunrise': '\ud83c\udf07', + 'city_sunset': '\ud83c\udf06', + 'cityscape': '\ud83c\udfd9\ufe0f', + 'cl': '\ud83c\udd91', + 'clamp': '\ud83d\udddc\ufe0f', + 'clap': '\ud83d\udc4f', + 'clapper': '\ud83c\udfac', + 'classical_building': '\ud83c\udfdb\ufe0f', + 'climbing': '\ud83e\uddd7', + 'climbing_man': '\ud83e\uddd7\u200d\u2642\ufe0f', + 'climbing_woman': '\ud83e\uddd7\u200d\u2640\ufe0f', + 'clinking_glasses': '\ud83e\udd42', + 'clipboard': '\ud83d\udccb', + 'clipperton_island': '\ud83c\udde8\ud83c\uddf5', + 'clock1': '\ud83d\udd50', + 'clock10': '\ud83d\udd59', + 'clock1030': '\ud83d\udd65', + 'clock11': '\ud83d\udd5a', + 'clock1130': '\ud83d\udd66', + 'clock12': '\ud83d\udd5b', + 'clock1230': '\ud83d\udd67', + 'clock130': '\ud83d\udd5c', + 'clock2': '\ud83d\udd51', + 'clock230': '\ud83d\udd5d', + 'clock3': '\ud83d\udd52', + 'clock330': '\ud83d\udd5e', + 'clock4': '\ud83d\udd53', + 'clock430': '\ud83d\udd5f', + 'clock5': '\ud83d\udd54', + 'clock530': '\ud83d\udd60', + 'clock6': '\ud83d\udd55', + 'clock630': '\ud83d\udd61', + 'clock7': '\ud83d\udd56', + 'clock730': '\ud83d\udd62', + 'clock8': '\ud83d\udd57', + 'clock830': '\ud83d\udd63', + 'clock9': '\ud83d\udd58', + 'clock930': '\ud83d\udd64', + 'closed_book': '\ud83d\udcd5', + 'closed_lock_with_key': '\ud83d\udd10', + 'closed_umbrella': '\ud83c\udf02', + 'cloud': '\u2601\ufe0f', + 'cloud_with_lightning': '\ud83c\udf29\ufe0f', + 'cloud_with_lightning_and_rain': '\u26c8\ufe0f', + 'cloud_with_rain': '\ud83c\udf27\ufe0f', + 'cloud_with_snow': '\ud83c\udf28\ufe0f', + 'clown_face': '\ud83e\udd21', + 'clubs': '\u2663\ufe0f', + 'cn': '\ud83c\udde8\ud83c\uddf3', + 'coat': '\ud83e\udde5', + 'cocktail': '\ud83c\udf78', + 'coconut': '\ud83e\udd65', + 'cocos_islands': '\ud83c\udde8\ud83c\udde8', + 'coffee': '\u2615', + 'coffin': '\u26b0\ufe0f', + 'cold_face': '\ud83e\udd76', + 'cold_sweat': '\ud83d\ude30', + 'collision': '\ud83d\udca5', + 'colombia': '\ud83c\udde8\ud83c\uddf4', + 'comet': '\u2604\ufe0f', + 'comoros': '\ud83c\uddf0\ud83c\uddf2', + 'compass': '\ud83e\udded', + 'computer': '\ud83d\udcbb', + 'computer_mouse': '\ud83d\uddb1\ufe0f', + 'confetti_ball': '\ud83c\udf8a', + 'confounded': '\ud83d\ude16', + 'confused': '\ud83d\ude15', + 'congo_brazzaville': '\ud83c\udde8\ud83c\uddec', + 'congo_kinshasa': '\ud83c\udde8\ud83c\udde9', + 'congratulations': '\u3297\ufe0f', + 'construction': '\ud83d\udea7', + 'construction_worker': '\ud83d\udc77', + 'construction_worker_man': '\ud83d\udc77\u200d\u2642\ufe0f', + 'construction_worker_woman': '\ud83d\udc77\u200d\u2640\ufe0f', + 'control_knobs': '\ud83c\udf9b\ufe0f', + 'convenience_store': '\ud83c\udfea', + 'cook': '\ud83e\uddd1\u200d\ud83c\udf73', + 'cook_islands': '\ud83c\udde8\ud83c\uddf0', + 'cookie': '\ud83c\udf6a', + 'cool': '\ud83c\udd92', + 'cop': '\ud83d\udc6e', + 'copyright': '\u00a9\ufe0f', + 'corn': '\ud83c\udf3d', + 'costa_rica': '\ud83c\udde8\ud83c\uddf7', + 'cote_divoire': '\ud83c\udde8\ud83c\uddee', + 'couch_and_lamp': '\ud83d\udecb\ufe0f', + 'couple': '\ud83d\udc6b', + 'couple_with_heart': '\ud83d\udc91', + 'couple_with_heart_man_man': '\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68', + 'couple_with_heart_woman_man': '\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc68', + 'couple_with_heart_woman_woman': '\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc69', + 'couplekiss': '\ud83d\udc8f', + 'couplekiss_man_man': '\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68', + 'couplekiss_man_woman': '\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68', + 'couplekiss_woman_woman': '\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69', + 'cow': '\ud83d\udc2e', + 'cow2': '\ud83d\udc04', + 'cowboy_hat_face': '\ud83e\udd20', + 'crab': '\ud83e\udd80', + 'crayon': '\ud83d\udd8d\ufe0f', + 'credit_card': '\ud83d\udcb3', + 'crescent_moon': '\ud83c\udf19', + 'cricket': '\ud83e\udd97', + 'cricket_game': '\ud83c\udfcf', + 'croatia': '\ud83c\udded\ud83c\uddf7', + 'crocodile': '\ud83d\udc0a', + 'croissant': '\ud83e\udd50', + 'crossed_fingers': '\ud83e\udd1e', + 'crossed_flags': '\ud83c\udf8c', + 'crossed_swords': '\u2694\ufe0f', + 'crown': '\ud83d\udc51', + 'cry': '\ud83d\ude22', + 'crying_cat_face': '\ud83d\ude3f', + 'crystal_ball': '\ud83d\udd2e', + 'cuba': '\ud83c\udde8\ud83c\uddfa', + 'cucumber': '\ud83e\udd52', + 'cup_with_straw': '\ud83e\udd64', + 'cupcake': '\ud83e\uddc1', + 'cupid': '\ud83d\udc98', + 'curacao': '\ud83c\udde8\ud83c\uddfc', + 'curling_stone': '\ud83e\udd4c', + 'curly_haired_man': '\ud83d\udc68\u200d\ud83e\uddb1', + 'curly_haired_woman': '\ud83d\udc69\u200d\ud83e\uddb1', + 'curly_loop': '\u27b0', + 'currency_exchange': '\ud83d\udcb1', + 'curry': '\ud83c\udf5b', + 'cursing_face': '\ud83e\udd2c', + 'custard': '\ud83c\udf6e', + 'customs': '\ud83d\udec3', + 'cut_of_meat': '\ud83e\udd69', + 'cyclone': '\ud83c\udf00', + 'cyprus': '\ud83c\udde8\ud83c\uddfe', + 'czech_republic': '\ud83c\udde8\ud83c\uddff', + 'dagger': '\ud83d\udde1\ufe0f', + 'dancer': '\ud83d\udc83', + 'dancers': '\ud83d\udc6f', + 'dancing_men': '\ud83d\udc6f\u200d\u2642\ufe0f', + 'dancing_women': '\ud83d\udc6f\u200d\u2640\ufe0f', + 'dango': '\ud83c\udf61', + 'dark_sunglasses': '\ud83d\udd76\ufe0f', + 'dart': '\ud83c\udfaf', + 'dash': '\ud83d\udca8', + 'date': '\ud83d\udcc5', + 'de': '\ud83c\udde9\ud83c\uddea', + 'deaf_man': '\ud83e\uddcf\u200d\u2642\ufe0f', + 'deaf_person': '\ud83e\uddcf', + 'deaf_woman': '\ud83e\uddcf\u200d\u2640\ufe0f', + 'deciduous_tree': '\ud83c\udf33', + 'deer': '\ud83e\udd8c', + 'denmark': '\ud83c\udde9\ud83c\uddf0', + 'department_store': '\ud83c\udfec', + 'derelict_house': '\ud83c\udfda\ufe0f', + 'desert': '\ud83c\udfdc\ufe0f', + 'desert_island': '\ud83c\udfdd\ufe0f', + 'desktop_computer': '\ud83d\udda5\ufe0f', + 'detective': '\ud83d\udd75\ufe0f', + 'diamond_shape_with_a_dot_inside': '\ud83d\udca0', + 'diamonds': '\u2666\ufe0f', + 'diego_garcia': '\ud83c\udde9\ud83c\uddec', + 'disappointed': '\ud83d\ude1e', + 'disappointed_relieved': '\ud83d\ude25', + 'diving_mask': '\ud83e\udd3f', + 'diya_lamp': '\ud83e\ude94', + 'dizzy': '\ud83d\udcab', + 'dizzy_face': '\ud83d\ude35', + 'djibouti': '\ud83c\udde9\ud83c\uddef', + 'dna': '\ud83e\uddec', + 'do_not_litter': '\ud83d\udeaf', + 'dog': '\ud83d\udc36', + 'dog2': '\ud83d\udc15', + 'dollar': '\ud83d\udcb5', + 'dolls': '\ud83c\udf8e', + 'dolphin': '\ud83d\udc2c', + 'dominica': '\ud83c\udde9\ud83c\uddf2', + 'dominican_republic': '\ud83c\udde9\ud83c\uddf4', + 'door': '\ud83d\udeaa', + 'doughnut': '\ud83c\udf69', + 'dove': '\ud83d\udd4a\ufe0f', + 'dragon': '\ud83d\udc09', + 'dragon_face': '\ud83d\udc32', + 'dress': '\ud83d\udc57', + 'dromedary_camel': '\ud83d\udc2a', + 'drooling_face': '\ud83e\udd24', + 'drop_of_blood': '\ud83e\ude78', + 'droplet': '\ud83d\udca7', + 'drum': '\ud83e\udd41', + 'duck': '\ud83e\udd86', + 'dumpling': '\ud83e\udd5f', + 'dvd': '\ud83d\udcc0', + 'e-mail': '\ud83d\udce7', + 'eagle': '\ud83e\udd85', + 'ear': '\ud83d\udc42', + 'ear_of_rice': '\ud83c\udf3e', + 'ear_with_hearing_aid': '\ud83e\uddbb', + 'earth_africa': '\ud83c\udf0d', + 'earth_americas': '\ud83c\udf0e', + 'earth_asia': '\ud83c\udf0f', + 'ecuador': '\ud83c\uddea\ud83c\udde8', + 'egg': '\ud83e\udd5a', + 'eggplant': '\ud83c\udf46', + 'egypt': '\ud83c\uddea\ud83c\uddec', + 'eight': '8\ufe0f\u20e3', + 'eight_pointed_black_star': '\u2734\ufe0f', + 'eight_spoked_asterisk': '\u2733\ufe0f', + 'eject_button': '\u23cf\ufe0f', + 'el_salvador': '\ud83c\uddf8\ud83c\uddfb', + 'electric_plug': '\ud83d\udd0c', + 'elephant': '\ud83d\udc18', + 'elf': '\ud83e\udddd', + 'elf_man': '\ud83e\udddd\u200d\u2642\ufe0f', + 'elf_woman': '\ud83e\udddd\u200d\u2640\ufe0f', + 'email': '\u2709\ufe0f', + 'end': '\ud83d\udd1a', + 'england': '\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f', + 'envelope': '\u2709\ufe0f', + 'envelope_with_arrow': '\ud83d\udce9', + 'equatorial_guinea': '\ud83c\uddec\ud83c\uddf6', + 'eritrea': '\ud83c\uddea\ud83c\uddf7', + 'es': '\ud83c\uddea\ud83c\uddf8', + 'estonia': '\ud83c\uddea\ud83c\uddea', + 'ethiopia': '\ud83c\uddea\ud83c\uddf9', + 'eu': '\ud83c\uddea\ud83c\uddfa', + 'euro': '\ud83d\udcb6', + 'european_castle': '\ud83c\udff0', + 'european_post_office': '\ud83c\udfe4', + 'european_union': '\ud83c\uddea\ud83c\uddfa', + 'evergreen_tree': '\ud83c\udf32', + 'exclamation': '\u2757', + 'exploding_head': '\ud83e\udd2f', + 'expressionless': '\ud83d\ude11', + 'eye': '\ud83d\udc41\ufe0f', + 'eye_speech_bubble': '\ud83d\udc41\ufe0f\u200d\ud83d\udde8\ufe0f', + 'eyeglasses': '\ud83d\udc53', + 'eyes': '\ud83d\udc40', + 'face_with_head_bandage': '\ud83e\udd15', + 'face_with_thermometer': '\ud83e\udd12', + 'facepalm': '\ud83e\udd26', + 'facepunch': '\ud83d\udc4a', + 'factory': '\ud83c\udfed', + 'factory_worker': '\ud83e\uddd1\u200d\ud83c\udfed', + 'fairy': '\ud83e\uddda', + 'fairy_man': '\ud83e\uddda\u200d\u2642\ufe0f', + 'fairy_woman': '\ud83e\uddda\u200d\u2640\ufe0f', + 'falafel': '\ud83e\uddc6', + 'falkland_islands': '\ud83c\uddeb\ud83c\uddf0', + 'fallen_leaf': '\ud83c\udf42', + 'family': '\ud83d\udc6a', + 'family_man_boy': '\ud83d\udc68\u200d\ud83d\udc66', + 'family_man_boy_boy': '\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66', + 'family_man_girl': '\ud83d\udc68\u200d\ud83d\udc67', + 'family_man_girl_boy': '\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66', + 'family_man_girl_girl': '\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67', + 'family_man_man_boy': '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66', + 'family_man_man_boy_boy': '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66', + 'family_man_man_girl': '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67', + 'family_man_man_girl_boy': '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66', + 'family_man_man_girl_girl': '\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67', + 'family_man_woman_boy': '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66', + 'family_man_woman_boy_boy': '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66', + 'family_man_woman_girl': '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67', + 'family_man_woman_girl_boy': '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66', + 'family_man_woman_girl_girl': '\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67', + 'family_woman_boy': '\ud83d\udc69\u200d\ud83d\udc66', + 'family_woman_boy_boy': '\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66', + 'family_woman_girl': '\ud83d\udc69\u200d\ud83d\udc67', + 'family_woman_girl_boy': '\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66', + 'family_woman_girl_girl': '\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67', + 'family_woman_woman_boy': '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66', + 'family_woman_woman_boy_boy': '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66', + 'family_woman_woman_girl': '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67', + 'family_woman_woman_girl_boy': '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66', + 'family_woman_woman_girl_girl': '\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67', + 'farmer': '\ud83e\uddd1\u200d\ud83c\udf3e', + 'faroe_islands': '\ud83c\uddeb\ud83c\uddf4', + 'fast_forward': '\u23e9', + 'fax': '\ud83d\udce0', + 'fearful': '\ud83d\ude28', + 'feet': '\ud83d\udc3e', + 'female_detective': '\ud83d\udd75\ufe0f\u200d\u2640\ufe0f', + 'female_sign': '\u2640\ufe0f', + 'ferris_wheel': '\ud83c\udfa1', + 'ferry': '\u26f4\ufe0f', + 'field_hockey': '\ud83c\udfd1', + 'fiji': '\ud83c\uddeb\ud83c\uddef', + 'file_cabinet': '\ud83d\uddc4\ufe0f', + 'file_folder': '\ud83d\udcc1', + 'film_projector': '\ud83d\udcfd\ufe0f', + 'film_strip': '\ud83c\udf9e\ufe0f', + 'finland': '\ud83c\uddeb\ud83c\uddee', + 'fire': '\ud83d\udd25', + 'fire_engine': '\ud83d\ude92', + 'fire_extinguisher': '\ud83e\uddef', + 'firecracker': '\ud83e\udde8', + 'firefighter': '\ud83e\uddd1\u200d\ud83d\ude92', + 'fireworks': '\ud83c\udf86', + 'first_quarter_moon': '\ud83c\udf13', + 'first_quarter_moon_with_face': '\ud83c\udf1b', + 'fish': '\ud83d\udc1f', + 'fish_cake': '\ud83c\udf65', + 'fishing_pole_and_fish': '\ud83c\udfa3', + 'fist': '\u270a', + 'fist_left': '\ud83e\udd1b', + 'fist_oncoming': '\ud83d\udc4a', + 'fist_raised': '\u270a', + 'fist_right': '\ud83e\udd1c', + 'five': '5\ufe0f\u20e3', + 'flags': '\ud83c\udf8f', + 'flamingo': '\ud83e\udda9', + 'flashlight': '\ud83d\udd26', + 'flat_shoe': '\ud83e\udd7f', + 'fleur_de_lis': '\u269c\ufe0f', + 'flight_arrival': '\ud83d\udeec', + 'flight_departure': '\ud83d\udeeb', + 'flipper': '\ud83d\udc2c', + 'floppy_disk': '\ud83d\udcbe', + 'flower_playing_cards': '\ud83c\udfb4', + 'flushed': '\ud83d\ude33', + 'flying_disc': '\ud83e\udd4f', + 'flying_saucer': '\ud83d\udef8', + 'fog': '\ud83c\udf2b\ufe0f', + 'foggy': '\ud83c\udf01', + 'foot': '\ud83e\uddb6', + 'football': '\ud83c\udfc8', + 'footprints': '\ud83d\udc63', + 'fork_and_knife': '\ud83c\udf74', + 'fortune_cookie': '\ud83e\udd60', + 'fountain': '\u26f2', + 'fountain_pen': '\ud83d\udd8b\ufe0f', + 'four': '4\ufe0f\u20e3', + 'four_leaf_clover': '\ud83c\udf40', + 'fox_face': '\ud83e\udd8a', + 'fr': '\ud83c\uddeb\ud83c\uddf7', + 'framed_picture': '\ud83d\uddbc\ufe0f', + 'free': '\ud83c\udd93', + 'french_guiana': '\ud83c\uddec\ud83c\uddeb', + 'french_polynesia': '\ud83c\uddf5\ud83c\uddeb', + 'french_southern_territories': '\ud83c\uddf9\ud83c\uddeb', + 'fried_egg': '\ud83c\udf73', + 'fried_shrimp': '\ud83c\udf64', + 'fries': '\ud83c\udf5f', + 'frog': '\ud83d\udc38', + 'frowning': '\ud83d\ude26', + 'frowning_face': '\u2639\ufe0f', + 'frowning_man': '\ud83d\ude4d\u200d\u2642\ufe0f', + 'frowning_person': '\ud83d\ude4d', + 'frowning_woman': '\ud83d\ude4d\u200d\u2640\ufe0f', + 'fu': '\ud83d\udd95', + 'fuelpump': '\u26fd', + 'full_moon': '\ud83c\udf15', + 'full_moon_with_face': '\ud83c\udf1d', + 'funeral_urn': '\u26b1\ufe0f', + 'gabon': '\ud83c\uddec\ud83c\udde6', + 'gambia': '\ud83c\uddec\ud83c\uddf2', + 'game_die': '\ud83c\udfb2', + 'garlic': '\ud83e\uddc4', + 'gb': '\ud83c\uddec\ud83c\udde7', + 'gear': '\u2699\ufe0f', + 'gem': '\ud83d\udc8e', + 'gemini': '\u264a', + 'genie': '\ud83e\uddde', + 'genie_man': '\ud83e\uddde\u200d\u2642\ufe0f', + 'genie_woman': '\ud83e\uddde\u200d\u2640\ufe0f', + 'georgia': '\ud83c\uddec\ud83c\uddea', + 'ghana': '\ud83c\uddec\ud83c\udded', + 'ghost': '\ud83d\udc7b', + 'gibraltar': '\ud83c\uddec\ud83c\uddee', + 'gift': '\ud83c\udf81', + 'gift_heart': '\ud83d\udc9d', + 'giraffe': '\ud83e\udd92', + 'girl': '\ud83d\udc67', + 'globe_with_meridians': '\ud83c\udf10', + 'gloves': '\ud83e\udde4', + 'goal_net': '\ud83e\udd45', + 'goat': '\ud83d\udc10', + 'goggles': '\ud83e\udd7d', + 'golf': '\u26f3', + 'golfing': '\ud83c\udfcc\ufe0f', + 'golfing_man': '\ud83c\udfcc\ufe0f\u200d\u2642\ufe0f', + 'golfing_woman': '\ud83c\udfcc\ufe0f\u200d\u2640\ufe0f', + 'gorilla': '\ud83e\udd8d', + 'grapes': '\ud83c\udf47', + 'greece': '\ud83c\uddec\ud83c\uddf7', + 'green_apple': '\ud83c\udf4f', + 'green_book': '\ud83d\udcd7', + 'green_circle': '\ud83d\udfe2', + 'green_heart': '\ud83d\udc9a', + 'green_salad': '\ud83e\udd57', + 'green_square': '\ud83d\udfe9', + 'greenland': '\ud83c\uddec\ud83c\uddf1', + 'grenada': '\ud83c\uddec\ud83c\udde9', + 'grey_exclamation': '\u2755', + 'grey_question': '\u2754', + 'grimacing': '\ud83d\ude2c', + 'grin': '\ud83d\ude01', + 'grinning': '\ud83d\ude00', + 'guadeloupe': '\ud83c\uddec\ud83c\uddf5', + 'guam': '\ud83c\uddec\ud83c\uddfa', + 'guard': '\ud83d\udc82', + 'guardsman': '\ud83d\udc82\u200d\u2642\ufe0f', + 'guardswoman': '\ud83d\udc82\u200d\u2640\ufe0f', + 'guatemala': '\ud83c\uddec\ud83c\uddf9', + 'guernsey': '\ud83c\uddec\ud83c\uddec', + 'guide_dog': '\ud83e\uddae', + 'guinea': '\ud83c\uddec\ud83c\uddf3', + 'guinea_bissau': '\ud83c\uddec\ud83c\uddfc', + 'guitar': '\ud83c\udfb8', + 'gun': '\ud83d\udd2b', + 'guyana': '\ud83c\uddec\ud83c\uddfe', + 'haircut': '\ud83d\udc87', + 'haircut_man': '\ud83d\udc87\u200d\u2642\ufe0f', + 'haircut_woman': '\ud83d\udc87\u200d\u2640\ufe0f', + 'haiti': '\ud83c\udded\ud83c\uddf9', + 'hamburger': '\ud83c\udf54', + 'hammer': '\ud83d\udd28', + 'hammer_and_pick': '\u2692\ufe0f', + 'hammer_and_wrench': '\ud83d\udee0\ufe0f', + 'hamster': '\ud83d\udc39', + 'hand': '\u270b', + 'hand_over_mouth': '\ud83e\udd2d', + 'handbag': '\ud83d\udc5c', + 'handball_person': '\ud83e\udd3e', + 'handshake': '\ud83e\udd1d', + 'hankey': '\ud83d\udca9', + 'hash': '#\ufe0f\u20e3', + 'hatched_chick': '\ud83d\udc25', + 'hatching_chick': '\ud83d\udc23', + 'headphones': '\ud83c\udfa7', + 'health_worker': '\ud83e\uddd1\u200d\u2695\ufe0f', + 'hear_no_evil': '\ud83d\ude49', + 'heard_mcdonald_islands': '\ud83c\udded\ud83c\uddf2', + 'heart': '\u2764\ufe0f', + 'heart_decoration': '\ud83d\udc9f', + 'heart_eyes': '\ud83d\ude0d', + 'heart_eyes_cat': '\ud83d\ude3b', + 'heartbeat': '\ud83d\udc93', + 'heartpulse': '\ud83d\udc97', + 'hearts': '\u2665\ufe0f', + 'heavy_check_mark': '\u2714\ufe0f', + 'heavy_division_sign': '\u2797', + 'heavy_dollar_sign': '\ud83d\udcb2', + 'heavy_exclamation_mark': '\u2757', + 'heavy_heart_exclamation': '\u2763\ufe0f', + 'heavy_minus_sign': '\u2796', + 'heavy_multiplication_x': '\u2716\ufe0f', + 'heavy_plus_sign': '\u2795', + 'hedgehog': '\ud83e\udd94', + 'helicopter': '\ud83d\ude81', + 'herb': '\ud83c\udf3f', + 'hibiscus': '\ud83c\udf3a', + 'high_brightness': '\ud83d\udd06', + 'high_heel': '\ud83d\udc60', + 'hiking_boot': '\ud83e\udd7e', + 'hindu_temple': '\ud83d\uded5', + 'hippopotamus': '\ud83e\udd9b', + 'hocho': '\ud83d\udd2a', + 'hole': '\ud83d\udd73\ufe0f', + 'honduras': '\ud83c\udded\ud83c\uddf3', + 'honey_pot': '\ud83c\udf6f', + 'honeybee': '\ud83d\udc1d', + 'hong_kong': '\ud83c\udded\ud83c\uddf0', + 'horse': '\ud83d\udc34', + 'horse_racing': '\ud83c\udfc7', + 'hospital': '\ud83c\udfe5', + 'hot_face': '\ud83e\udd75', + 'hot_pepper': '\ud83c\udf36\ufe0f', + 'hotdog': '\ud83c\udf2d', + 'hotel': '\ud83c\udfe8', + 'hotsprings': '\u2668\ufe0f', + 'hourglass': '\u231b', + 'hourglass_flowing_sand': '\u23f3', + 'house': '\ud83c\udfe0', + 'house_with_garden': '\ud83c\udfe1', + 'houses': '\ud83c\udfd8\ufe0f', + 'hugs': '\ud83e\udd17', + 'hungary': '\ud83c\udded\ud83c\uddfa', + 'hushed': '\ud83d\ude2f', + 'ice_cream': '\ud83c\udf68', + 'ice_cube': '\ud83e\uddca', + 'ice_hockey': '\ud83c\udfd2', + 'ice_skate': '\u26f8\ufe0f', + 'icecream': '\ud83c\udf66', + 'iceland': '\ud83c\uddee\ud83c\uddf8', + 'id': '\ud83c\udd94', + 'ideograph_advantage': '\ud83c\ude50', + 'imp': '\ud83d\udc7f', + 'inbox_tray': '\ud83d\udce5', + 'incoming_envelope': '\ud83d\udce8', + 'india': '\ud83c\uddee\ud83c\uddf3', + 'indonesia': '\ud83c\uddee\ud83c\udde9', + 'infinity': '\u267e\ufe0f', + 'information_desk_person': '\ud83d\udc81', + 'information_source': '\u2139\ufe0f', + 'innocent': '\ud83d\ude07', + 'interrobang': '\u2049\ufe0f', + 'iphone': '\ud83d\udcf1', + 'iran': '\ud83c\uddee\ud83c\uddf7', + 'iraq': '\ud83c\uddee\ud83c\uddf6', + 'ireland': '\ud83c\uddee\ud83c\uddea', + 'isle_of_man': '\ud83c\uddee\ud83c\uddf2', + 'israel': '\ud83c\uddee\ud83c\uddf1', + 'it': '\ud83c\uddee\ud83c\uddf9', + 'izakaya_lantern': '\ud83c\udfee', + 'jack_o_lantern': '\ud83c\udf83', + 'jamaica': '\ud83c\uddef\ud83c\uddf2', + 'japan': '\ud83d\uddfe', + 'japanese_castle': '\ud83c\udfef', + 'japanese_goblin': '\ud83d\udc7a', + 'japanese_ogre': '\ud83d\udc79', + 'jeans': '\ud83d\udc56', + 'jersey': '\ud83c\uddef\ud83c\uddea', + 'jigsaw': '\ud83e\udde9', + 'jordan': '\ud83c\uddef\ud83c\uddf4', + 'joy': '\ud83d\ude02', + 'joy_cat': '\ud83d\ude39', + 'joystick': '\ud83d\udd79\ufe0f', + 'jp': '\ud83c\uddef\ud83c\uddf5', + 'judge': '\ud83e\uddd1\u200d\u2696\ufe0f', + 'juggling_person': '\ud83e\udd39', + 'kaaba': '\ud83d\udd4b', + 'kangaroo': '\ud83e\udd98', + 'kazakhstan': '\ud83c\uddf0\ud83c\uddff', + 'kenya': '\ud83c\uddf0\ud83c\uddea', + 'key': '\ud83d\udd11', + 'keyboard': '\u2328\ufe0f', + 'keycap_ten': '\ud83d\udd1f', + 'kick_scooter': '\ud83d\udef4', + 'kimono': '\ud83d\udc58', + 'kiribati': '\ud83c\uddf0\ud83c\uddee', + 'kiss': '\ud83d\udc8b', + 'kissing': '\ud83d\ude17', + 'kissing_cat': '\ud83d\ude3d', + 'kissing_closed_eyes': '\ud83d\ude1a', + 'kissing_heart': '\ud83d\ude18', + 'kissing_smiling_eyes': '\ud83d\ude19', + 'kite': '\ud83e\ude81', + 'kiwi_fruit': '\ud83e\udd5d', + 'kneeling_man': '\ud83e\uddce\u200d\u2642\ufe0f', + 'kneeling_person': '\ud83e\uddce', + 'kneeling_woman': '\ud83e\uddce\u200d\u2640\ufe0f', + 'knife': '\ud83d\udd2a', + 'koala': '\ud83d\udc28', + 'koko': '\ud83c\ude01', + 'kosovo': '\ud83c\uddfd\ud83c\uddf0', + 'kr': '\ud83c\uddf0\ud83c\uddf7', + 'kuwait': '\ud83c\uddf0\ud83c\uddfc', + 'kyrgyzstan': '\ud83c\uddf0\ud83c\uddec', + 'lab_coat': '\ud83e\udd7c', + 'label': '\ud83c\udff7\ufe0f', + 'lacrosse': '\ud83e\udd4d', + 'lantern': '\ud83c\udfee', + 'laos': '\ud83c\uddf1\ud83c\udde6', + 'large_blue_circle': '\ud83d\udd35', + 'large_blue_diamond': '\ud83d\udd37', + 'large_orange_diamond': '\ud83d\udd36', + 'last_quarter_moon': '\ud83c\udf17', + 'last_quarter_moon_with_face': '\ud83c\udf1c', + 'latin_cross': '\u271d\ufe0f', + 'latvia': '\ud83c\uddf1\ud83c\uddfb', + 'laughing': '\ud83d\ude06', + 'leafy_green': '\ud83e\udd6c', + 'leaves': '\ud83c\udf43', + 'lebanon': '\ud83c\uddf1\ud83c\udde7', + 'ledger': '\ud83d\udcd2', + 'left_luggage': '\ud83d\udec5', + 'left_right_arrow': '\u2194\ufe0f', + 'left_speech_bubble': '\ud83d\udde8\ufe0f', + 'leftwards_arrow_with_hook': '\u21a9\ufe0f', + 'leg': '\ud83e\uddb5', + 'lemon': '\ud83c\udf4b', + 'leo': '\u264c', + 'leopard': '\ud83d\udc06', + 'lesotho': '\ud83c\uddf1\ud83c\uddf8', + 'level_slider': '\ud83c\udf9a\ufe0f', + 'liberia': '\ud83c\uddf1\ud83c\uddf7', + 'libra': '\u264e', + 'libya': '\ud83c\uddf1\ud83c\uddfe', + 'liechtenstein': '\ud83c\uddf1\ud83c\uddee', + 'light_rail': '\ud83d\ude88', + 'link': '\ud83d\udd17', + 'lion': '\ud83e\udd81', + 'lips': '\ud83d\udc44', + 'lipstick': '\ud83d\udc84', + 'lithuania': '\ud83c\uddf1\ud83c\uddf9', + 'lizard': '\ud83e\udd8e', + 'llama': '\ud83e\udd99', + 'lobster': '\ud83e\udd9e', + 'lock': '\ud83d\udd12', + 'lock_with_ink_pen': '\ud83d\udd0f', + 'lollipop': '\ud83c\udf6d', + 'loop': '\u27bf', + 'lotion_bottle': '\ud83e\uddf4', + 'lotus_position': '\ud83e\uddd8', + 'lotus_position_man': '\ud83e\uddd8\u200d\u2642\ufe0f', + 'lotus_position_woman': '\ud83e\uddd8\u200d\u2640\ufe0f', + 'loud_sound': '\ud83d\udd0a', + 'loudspeaker': '\ud83d\udce2', + 'love_hotel': '\ud83c\udfe9', + 'love_letter': '\ud83d\udc8c', + 'love_you_gesture': '\ud83e\udd1f', + 'low_brightness': '\ud83d\udd05', + 'luggage': '\ud83e\uddf3', + 'luxembourg': '\ud83c\uddf1\ud83c\uddfa', + 'lying_face': '\ud83e\udd25', + 'm': '\u24c2\ufe0f', + 'macau': '\ud83c\uddf2\ud83c\uddf4', + 'macedonia': '\ud83c\uddf2\ud83c\uddf0', + 'madagascar': '\ud83c\uddf2\ud83c\uddec', + 'mag': '\ud83d\udd0d', + 'mag_right': '\ud83d\udd0e', + 'mage': '\ud83e\uddd9', + 'mage_man': '\ud83e\uddd9\u200d\u2642\ufe0f', + 'mage_woman': '\ud83e\uddd9\u200d\u2640\ufe0f', + 'magnet': '\ud83e\uddf2', + 'mahjong': '\ud83c\udc04', + 'mailbox': '\ud83d\udceb', + 'mailbox_closed': '\ud83d\udcea', + 'mailbox_with_mail': '\ud83d\udcec', + 'mailbox_with_no_mail': '\ud83d\udced', + 'malawi': '\ud83c\uddf2\ud83c\uddfc', + 'malaysia': '\ud83c\uddf2\ud83c\uddfe', + 'maldives': '\ud83c\uddf2\ud83c\uddfb', + 'male_detective': '\ud83d\udd75\ufe0f\u200d\u2642\ufe0f', + 'male_sign': '\u2642\ufe0f', + 'mali': '\ud83c\uddf2\ud83c\uddf1', + 'malta': '\ud83c\uddf2\ud83c\uddf9', + 'man': '\ud83d\udc68', + 'man_artist': '\ud83d\udc68\u200d\ud83c\udfa8', + 'man_astronaut': '\ud83d\udc68\u200d\ud83d\ude80', + 'man_cartwheeling': '\ud83e\udd38\u200d\u2642\ufe0f', + 'man_cook': '\ud83d\udc68\u200d\ud83c\udf73', + 'man_dancing': '\ud83d\udd7a', + 'man_facepalming': '\ud83e\udd26\u200d\u2642\ufe0f', + 'man_factory_worker': '\ud83d\udc68\u200d\ud83c\udfed', + 'man_farmer': '\ud83d\udc68\u200d\ud83c\udf3e', + 'man_firefighter': '\ud83d\udc68\u200d\ud83d\ude92', + 'man_health_worker': '\ud83d\udc68\u200d\u2695\ufe0f', + 'man_in_manual_wheelchair': '\ud83d\udc68\u200d\ud83e\uddbd', + 'man_in_motorized_wheelchair': '\ud83d\udc68\u200d\ud83e\uddbc', + 'man_in_tuxedo': '\ud83e\udd35', + 'man_judge': '\ud83d\udc68\u200d\u2696\ufe0f', + 'man_juggling': '\ud83e\udd39\u200d\u2642\ufe0f', + 'man_mechanic': '\ud83d\udc68\u200d\ud83d\udd27', + 'man_office_worker': '\ud83d\udc68\u200d\ud83d\udcbc', + 'man_pilot': '\ud83d\udc68\u200d\u2708\ufe0f', + 'man_playing_handball': '\ud83e\udd3e\u200d\u2642\ufe0f', + 'man_playing_water_polo': '\ud83e\udd3d\u200d\u2642\ufe0f', + 'man_scientist': '\ud83d\udc68\u200d\ud83d\udd2c', + 'man_shrugging': '\ud83e\udd37\u200d\u2642\ufe0f', + 'man_singer': '\ud83d\udc68\u200d\ud83c\udfa4', + 'man_student': '\ud83d\udc68\u200d\ud83c\udf93', + 'man_teacher': '\ud83d\udc68\u200d\ud83c\udfeb', + 'man_technologist': '\ud83d\udc68\u200d\ud83d\udcbb', + 'man_with_gua_pi_mao': '\ud83d\udc72', + 'man_with_probing_cane': '\ud83d\udc68\u200d\ud83e\uddaf', + 'man_with_turban': '\ud83d\udc73\u200d\u2642\ufe0f', + 'mandarin': '\ud83c\udf4a', + 'mango': '\ud83e\udd6d', + 'mans_shoe': '\ud83d\udc5e', + 'mantelpiece_clock': '\ud83d\udd70\ufe0f', + 'manual_wheelchair': '\ud83e\uddbd', + 'maple_leaf': '\ud83c\udf41', + 'marshall_islands': '\ud83c\uddf2\ud83c\udded', + 'martial_arts_uniform': '\ud83e\udd4b', + 'martinique': '\ud83c\uddf2\ud83c\uddf6', + 'mask': '\ud83d\ude37', + 'massage': '\ud83d\udc86', + 'massage_man': '\ud83d\udc86\u200d\u2642\ufe0f', + 'massage_woman': '\ud83d\udc86\u200d\u2640\ufe0f', + 'mate': '\ud83e\uddc9', + 'mauritania': '\ud83c\uddf2\ud83c\uddf7', + 'mauritius': '\ud83c\uddf2\ud83c\uddfa', + 'mayotte': '\ud83c\uddfe\ud83c\uddf9', + 'meat_on_bone': '\ud83c\udf56', + 'mechanic': '\ud83e\uddd1\u200d\ud83d\udd27', + 'mechanical_arm': '\ud83e\uddbe', + 'mechanical_leg': '\ud83e\uddbf', + 'medal_military': '\ud83c\udf96\ufe0f', + 'medal_sports': '\ud83c\udfc5', + 'medical_symbol': '\u2695\ufe0f', + 'mega': '\ud83d\udce3', + 'melon': '\ud83c\udf48', + 'memo': '\ud83d\udcdd', + 'men_wrestling': '\ud83e\udd3c\u200d\u2642\ufe0f', + 'menorah': '\ud83d\udd4e', + 'mens': '\ud83d\udeb9', + 'mermaid': '\ud83e\udddc\u200d\u2640\ufe0f', + 'merman': '\ud83e\udddc\u200d\u2642\ufe0f', + 'merperson': '\ud83e\udddc', + 'metal': '\ud83e\udd18', + 'metro': '\ud83d\ude87', + 'mexico': '\ud83c\uddf2\ud83c\uddfd', + 'microbe': '\ud83e\udda0', + 'micronesia': '\ud83c\uddeb\ud83c\uddf2', + 'microphone': '\ud83c\udfa4', + 'microscope': '\ud83d\udd2c', + 'middle_finger': '\ud83d\udd95', + 'milk_glass': '\ud83e\udd5b', + 'milky_way': '\ud83c\udf0c', + 'minibus': '\ud83d\ude90', + 'minidisc': '\ud83d\udcbd', + 'mobile_phone_off': '\ud83d\udcf4', + 'moldova': '\ud83c\uddf2\ud83c\udde9', + 'monaco': '\ud83c\uddf2\ud83c\udde8', + 'money_mouth_face': '\ud83e\udd11', + 'money_with_wings': '\ud83d\udcb8', + 'moneybag': '\ud83d\udcb0', + 'mongolia': '\ud83c\uddf2\ud83c\uddf3', + 'monkey': '\ud83d\udc12', + 'monkey_face': '\ud83d\udc35', + 'monocle_face': '\ud83e\uddd0', + 'monorail': '\ud83d\ude9d', + 'montenegro': '\ud83c\uddf2\ud83c\uddea', + 'montserrat': '\ud83c\uddf2\ud83c\uddf8', + 'moon': '\ud83c\udf14', + 'moon_cake': '\ud83e\udd6e', + 'morocco': '\ud83c\uddf2\ud83c\udde6', + 'mortar_board': '\ud83c\udf93', + 'mosque': '\ud83d\udd4c', + 'mosquito': '\ud83e\udd9f', + 'motor_boat': '\ud83d\udee5\ufe0f', + 'motor_scooter': '\ud83d\udef5', + 'motorcycle': '\ud83c\udfcd\ufe0f', + 'motorized_wheelchair': '\ud83e\uddbc', + 'motorway': '\ud83d\udee3\ufe0f', + 'mount_fuji': '\ud83d\uddfb', + 'mountain': '\u26f0\ufe0f', + 'mountain_bicyclist': '\ud83d\udeb5', + 'mountain_biking_man': '\ud83d\udeb5\u200d\u2642\ufe0f', + 'mountain_biking_woman': '\ud83d\udeb5\u200d\u2640\ufe0f', + 'mountain_cableway': '\ud83d\udea0', + 'mountain_railway': '\ud83d\ude9e', + 'mountain_snow': '\ud83c\udfd4\ufe0f', + 'mouse': '\ud83d\udc2d', + 'mouse2': '\ud83d\udc01', + 'movie_camera': '\ud83c\udfa5', + 'moyai': '\ud83d\uddff', + 'mozambique': '\ud83c\uddf2\ud83c\uddff', + 'mrs_claus': '\ud83e\udd36', + 'muscle': '\ud83d\udcaa', + 'mushroom': '\ud83c\udf44', + 'musical_keyboard': '\ud83c\udfb9', + 'musical_note': '\ud83c\udfb5', + 'musical_score': '\ud83c\udfbc', + 'mute': '\ud83d\udd07', + 'myanmar': '\ud83c\uddf2\ud83c\uddf2', + 'nail_care': '\ud83d\udc85', + 'name_badge': '\ud83d\udcdb', + 'namibia': '\ud83c\uddf3\ud83c\udde6', + 'national_park': '\ud83c\udfde\ufe0f', + 'nauru': '\ud83c\uddf3\ud83c\uddf7', + 'nauseated_face': '\ud83e\udd22', + 'nazar_amulet': '\ud83e\uddff', + 'necktie': '\ud83d\udc54', + 'negative_squared_cross_mark': '\u274e', + 'nepal': '\ud83c\uddf3\ud83c\uddf5', + 'nerd_face': '\ud83e\udd13', + 'netherlands': '\ud83c\uddf3\ud83c\uddf1', + 'neutral_face': '\ud83d\ude10', + 'new': '\ud83c\udd95', + 'new_caledonia': '\ud83c\uddf3\ud83c\udde8', + 'new_moon': '\ud83c\udf11', + 'new_moon_with_face': '\ud83c\udf1a', + 'new_zealand': '\ud83c\uddf3\ud83c\uddff', + 'newspaper': '\ud83d\udcf0', + 'newspaper_roll': '\ud83d\uddde\ufe0f', + 'next_track_button': '\u23ed\ufe0f', + 'ng': '\ud83c\udd96', + 'ng_man': '\ud83d\ude45\u200d\u2642\ufe0f', + 'ng_woman': '\ud83d\ude45\u200d\u2640\ufe0f', + 'nicaragua': '\ud83c\uddf3\ud83c\uddee', + 'niger': '\ud83c\uddf3\ud83c\uddea', + 'nigeria': '\ud83c\uddf3\ud83c\uddec', + 'night_with_stars': '\ud83c\udf03', + 'nine': '9\ufe0f\u20e3', + 'niue': '\ud83c\uddf3\ud83c\uddfa', + 'no_bell': '\ud83d\udd15', + 'no_bicycles': '\ud83d\udeb3', + 'no_entry': '\u26d4', + 'no_entry_sign': '\ud83d\udeab', + 'no_good': '\ud83d\ude45', + 'no_good_man': '\ud83d\ude45\u200d\u2642\ufe0f', + 'no_good_woman': '\ud83d\ude45\u200d\u2640\ufe0f', + 'no_mobile_phones': '\ud83d\udcf5', + 'no_mouth': '\ud83d\ude36', + 'no_pedestrians': '\ud83d\udeb7', + 'no_smoking': '\ud83d\udead', + 'non-potable_water': '\ud83d\udeb1', + 'norfolk_island': '\ud83c\uddf3\ud83c\uddeb', + 'north_korea': '\ud83c\uddf0\ud83c\uddf5', + 'northern_mariana_islands': '\ud83c\uddf2\ud83c\uddf5', + 'norway': '\ud83c\uddf3\ud83c\uddf4', + 'nose': '\ud83d\udc43', + 'notebook': '\ud83d\udcd3', + 'notebook_with_decorative_cover': '\ud83d\udcd4', + 'notes': '\ud83c\udfb6', + 'nut_and_bolt': '\ud83d\udd29', + 'o': '\u2b55', + 'o2': '\ud83c\udd7e\ufe0f', + 'ocean': '\ud83c\udf0a', + 'octopus': '\ud83d\udc19', + 'oden': '\ud83c\udf62', + 'office': '\ud83c\udfe2', + 'office_worker': '\ud83e\uddd1\u200d\ud83d\udcbc', + 'oil_drum': '\ud83d\udee2\ufe0f', + 'ok': '\ud83c\udd97', + 'ok_hand': '\ud83d\udc4c', + 'ok_man': '\ud83d\ude46\u200d\u2642\ufe0f', + 'ok_person': '\ud83d\ude46', + 'ok_woman': '\ud83d\ude46\u200d\u2640\ufe0f', + 'old_key': '\ud83d\udddd\ufe0f', + 'older_adult': '\ud83e\uddd3', + 'older_man': '\ud83d\udc74', + 'older_woman': '\ud83d\udc75', + 'om': '\ud83d\udd49\ufe0f', + 'oman': '\ud83c\uddf4\ud83c\uddf2', + 'on': '\ud83d\udd1b', + 'oncoming_automobile': '\ud83d\ude98', + 'oncoming_bus': '\ud83d\ude8d', + 'oncoming_police_car': '\ud83d\ude94', + 'oncoming_taxi': '\ud83d\ude96', + 'one': '1\ufe0f\u20e3', + 'one_piece_swimsuit': '\ud83e\ude71', + 'onion': '\ud83e\uddc5', + 'open_book': '\ud83d\udcd6', + 'open_file_folder': '\ud83d\udcc2', + 'open_hands': '\ud83d\udc50', + 'open_mouth': '\ud83d\ude2e', + 'open_umbrella': '\u2602\ufe0f', + 'ophiuchus': '\u26ce', + 'orange': '\ud83c\udf4a', + 'orange_book': '\ud83d\udcd9', + 'orange_circle': '\ud83d\udfe0', + 'orange_heart': '\ud83e\udde1', + 'orange_square': '\ud83d\udfe7', + 'orangutan': '\ud83e\udda7', + 'orthodox_cross': '\u2626\ufe0f', + 'otter': '\ud83e\udda6', + 'outbox_tray': '\ud83d\udce4', + 'owl': '\ud83e\udd89', + 'ox': '\ud83d\udc02', + 'oyster': '\ud83e\uddaa', + 'package': '\ud83d\udce6', + 'page_facing_up': '\ud83d\udcc4', + 'page_with_curl': '\ud83d\udcc3', + 'pager': '\ud83d\udcdf', + 'paintbrush': '\ud83d\udd8c\ufe0f', + 'pakistan': '\ud83c\uddf5\ud83c\uddf0', + 'palau': '\ud83c\uddf5\ud83c\uddfc', + 'palestinian_territories': '\ud83c\uddf5\ud83c\uddf8', + 'palm_tree': '\ud83c\udf34', + 'palms_up_together': '\ud83e\udd32', + 'panama': '\ud83c\uddf5\ud83c\udde6', + 'pancakes': '\ud83e\udd5e', + 'panda_face': '\ud83d\udc3c', + 'paperclip': '\ud83d\udcce', + 'paperclips': '\ud83d\udd87\ufe0f', + 'papua_new_guinea': '\ud83c\uddf5\ud83c\uddec', + 'parachute': '\ud83e\ude82', + 'paraguay': '\ud83c\uddf5\ud83c\uddfe', + 'parasol_on_ground': '\u26f1\ufe0f', + 'parking': '\ud83c\udd7f\ufe0f', + 'parrot': '\ud83e\udd9c', + 'part_alternation_mark': '\u303d\ufe0f', + 'partly_sunny': '\u26c5', + 'partying_face': '\ud83e\udd73', + 'passenger_ship': '\ud83d\udef3\ufe0f', + 'passport_control': '\ud83d\udec2', + 'pause_button': '\u23f8\ufe0f', + 'paw_prints': '\ud83d\udc3e', + 'peace_symbol': '\u262e\ufe0f', + 'peach': '\ud83c\udf51', + 'peacock': '\ud83e\udd9a', + 'peanuts': '\ud83e\udd5c', + 'pear': '\ud83c\udf50', + 'pen': '\ud83d\udd8a\ufe0f', + 'pencil': '\ud83d\udcdd', + 'pencil2': '\u270f\ufe0f', + 'penguin': '\ud83d\udc27', + 'pensive': '\ud83d\ude14', + 'people_holding_hands': '\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1', + 'performing_arts': '\ud83c\udfad', + 'persevere': '\ud83d\ude23', + 'person_bald': '\ud83e\uddd1\u200d\ud83e\uddb2', + 'person_curly_hair': '\ud83e\uddd1\u200d\ud83e\uddb1', + 'person_fencing': '\ud83e\udd3a', + 'person_in_manual_wheelchair': '\ud83e\uddd1\u200d\ud83e\uddbd', + 'person_in_motorized_wheelchair': '\ud83e\uddd1\u200d\ud83e\uddbc', + 'person_red_hair': '\ud83e\uddd1\u200d\ud83e\uddb0', + 'person_white_hair': '\ud83e\uddd1\u200d\ud83e\uddb3', + 'person_with_probing_cane': '\ud83e\uddd1\u200d\ud83e\uddaf', + 'person_with_turban': '\ud83d\udc73', + 'peru': '\ud83c\uddf5\ud83c\uddea', + 'petri_dish': '\ud83e\uddeb', + 'philippines': '\ud83c\uddf5\ud83c\udded', + 'phone': '\u260e\ufe0f', + 'pick': '\u26cf\ufe0f', + 'pie': '\ud83e\udd67', + 'pig': '\ud83d\udc37', + 'pig2': '\ud83d\udc16', + 'pig_nose': '\ud83d\udc3d', + 'pill': '\ud83d\udc8a', + 'pilot': '\ud83e\uddd1\u200d\u2708\ufe0f', + 'pinching_hand': '\ud83e\udd0f', + 'pineapple': '\ud83c\udf4d', + 'ping_pong': '\ud83c\udfd3', + 'pirate_flag': '\ud83c\udff4\u200d\u2620\ufe0f', + 'pisces': '\u2653', + 'pitcairn_islands': '\ud83c\uddf5\ud83c\uddf3', + 'pizza': '\ud83c\udf55', + 'place_of_worship': '\ud83d\uded0', + 'plate_with_cutlery': '\ud83c\udf7d\ufe0f', + 'play_or_pause_button': '\u23ef\ufe0f', + 'pleading_face': '\ud83e\udd7a', + 'point_down': '\ud83d\udc47', + 'point_left': '\ud83d\udc48', + 'point_right': '\ud83d\udc49', + 'point_up': '\u261d\ufe0f', + 'point_up_2': '\ud83d\udc46', + 'poland': '\ud83c\uddf5\ud83c\uddf1', + 'police_car': '\ud83d\ude93', + 'police_officer': '\ud83d\udc6e', + 'policeman': '\ud83d\udc6e\u200d\u2642\ufe0f', + 'policewoman': '\ud83d\udc6e\u200d\u2640\ufe0f', + 'poodle': '\ud83d\udc29', + 'poop': '\ud83d\udca9', + 'popcorn': '\ud83c\udf7f', + 'portugal': '\ud83c\uddf5\ud83c\uddf9', + 'post_office': '\ud83c\udfe3', + 'postal_horn': '\ud83d\udcef', + 'postbox': '\ud83d\udcee', + 'potable_water': '\ud83d\udeb0', + 'potato': '\ud83e\udd54', + 'pouch': '\ud83d\udc5d', + 'poultry_leg': '\ud83c\udf57', + 'pound': '\ud83d\udcb7', + 'pout': '\ud83d\ude21', + 'pouting_cat': '\ud83d\ude3e', + 'pouting_face': '\ud83d\ude4e', + 'pouting_man': '\ud83d\ude4e\u200d\u2642\ufe0f', + 'pouting_woman': '\ud83d\ude4e\u200d\u2640\ufe0f', + 'pray': '\ud83d\ude4f', + 'prayer_beads': '\ud83d\udcff', + 'pregnant_woman': '\ud83e\udd30', + 'pretzel': '\ud83e\udd68', + 'previous_track_button': '\u23ee\ufe0f', + 'prince': '\ud83e\udd34', + 'princess': '\ud83d\udc78', + 'printer': '\ud83d\udda8\ufe0f', + 'probing_cane': '\ud83e\uddaf', + 'puerto_rico': '\ud83c\uddf5\ud83c\uddf7', + 'punch': '\ud83d\udc4a', + 'purple_circle': '\ud83d\udfe3', + 'purple_heart': '\ud83d\udc9c', + 'purple_square': '\ud83d\udfea', + 'purse': '\ud83d\udc5b', + 'pushpin': '\ud83d\udccc', + 'put_litter_in_its_place': '\ud83d\udeae', + 'qatar': '\ud83c\uddf6\ud83c\udde6', + 'question': '\u2753', + 'rabbit': '\ud83d\udc30', + 'rabbit2': '\ud83d\udc07', + 'raccoon': '\ud83e\udd9d', + 'racehorse': '\ud83d\udc0e', + 'racing_car': '\ud83c\udfce\ufe0f', + 'radio': '\ud83d\udcfb', + 'radio_button': '\ud83d\udd18', + 'radioactive': '\u2622\ufe0f', + 'rage': '\ud83d\ude21', + 'railway_car': '\ud83d\ude83', + 'railway_track': '\ud83d\udee4\ufe0f', + 'rainbow': '\ud83c\udf08', + 'rainbow_flag': '\ud83c\udff3\ufe0f\u200d\ud83c\udf08', + 'raised_back_of_hand': '\ud83e\udd1a', + 'raised_eyebrow': '\ud83e\udd28', + 'raised_hand': '\u270b', + 'raised_hand_with_fingers_splayed': '\ud83d\udd90\ufe0f', + 'raised_hands': '\ud83d\ude4c', + 'raising_hand': '\ud83d\ude4b', + 'raising_hand_man': '\ud83d\ude4b\u200d\u2642\ufe0f', + 'raising_hand_woman': '\ud83d\ude4b\u200d\u2640\ufe0f', + 'ram': '\ud83d\udc0f', + 'ramen': '\ud83c\udf5c', + 'rat': '\ud83d\udc00', + 'razor': '\ud83e\ude92', + 'receipt': '\ud83e\uddfe', + 'record_button': '\u23fa\ufe0f', + 'recycle': '\u267b\ufe0f', + 'red_car': '\ud83d\ude97', + 'red_circle': '\ud83d\udd34', + 'red_envelope': '\ud83e\udde7', + 'red_haired_man': '\ud83d\udc68\u200d\ud83e\uddb0', + 'red_haired_woman': '\ud83d\udc69\u200d\ud83e\uddb0', + 'red_square': '\ud83d\udfe5', + 'registered': '\u00ae\ufe0f', + 'relaxed': '\u263a\ufe0f', + 'relieved': '\ud83d\ude0c', + 'reminder_ribbon': '\ud83c\udf97\ufe0f', + 'repeat': '\ud83d\udd01', + 'repeat_one': '\ud83d\udd02', + 'rescue_worker_helmet': '\u26d1\ufe0f', + 'restroom': '\ud83d\udebb', + 'reunion': '\ud83c\uddf7\ud83c\uddea', + 'revolving_hearts': '\ud83d\udc9e', + 'rewind': '\u23ea', + 'rhinoceros': '\ud83e\udd8f', + 'ribbon': '\ud83c\udf80', + 'rice': '\ud83c\udf5a', + 'rice_ball': '\ud83c\udf59', + 'rice_cracker': '\ud83c\udf58', + 'rice_scene': '\ud83c\udf91', + 'right_anger_bubble': '\ud83d\uddef\ufe0f', + 'ring': '\ud83d\udc8d', + 'ringed_planet': '\ud83e\ude90', + 'robot': '\ud83e\udd16', + 'rocket': '\ud83d\ude80', + 'rofl': '\ud83e\udd23', + 'roll_eyes': '\ud83d\ude44', + 'roll_of_paper': '\ud83e\uddfb', + 'roller_coaster': '\ud83c\udfa2', + 'romania': '\ud83c\uddf7\ud83c\uddf4', + 'rooster': '\ud83d\udc13', + 'rose': '\ud83c\udf39', + 'rosette': '\ud83c\udff5\ufe0f', + 'rotating_light': '\ud83d\udea8', + 'round_pushpin': '\ud83d\udccd', + 'rowboat': '\ud83d\udea3', + 'rowing_man': '\ud83d\udea3\u200d\u2642\ufe0f', + 'rowing_woman': '\ud83d\udea3\u200d\u2640\ufe0f', + 'ru': '\ud83c\uddf7\ud83c\uddfa', + 'rugby_football': '\ud83c\udfc9', + 'runner': '\ud83c\udfc3', + 'running': '\ud83c\udfc3', + 'running_man': '\ud83c\udfc3\u200d\u2642\ufe0f', + 'running_shirt_with_sash': '\ud83c\udfbd', + 'running_woman': '\ud83c\udfc3\u200d\u2640\ufe0f', + 'rwanda': '\ud83c\uddf7\ud83c\uddfc', + 'sa': '\ud83c\ude02\ufe0f', + 'safety_pin': '\ud83e\uddf7', + 'safety_vest': '\ud83e\uddba', + 'sagittarius': '\u2650', + 'sailboat': '\u26f5', + 'sake': '\ud83c\udf76', + 'salt': '\ud83e\uddc2', + 'samoa': '\ud83c\uddfc\ud83c\uddf8', + 'san_marino': '\ud83c\uddf8\ud83c\uddf2', + 'sandal': '\ud83d\udc61', + 'sandwich': '\ud83e\udd6a', + 'santa': '\ud83c\udf85', + 'sao_tome_principe': '\ud83c\uddf8\ud83c\uddf9', + 'sari': '\ud83e\udd7b', + 'sassy_man': '\ud83d\udc81\u200d\u2642\ufe0f', + 'sassy_woman': '\ud83d\udc81\u200d\u2640\ufe0f', + 'satellite': '\ud83d\udce1', + 'satisfied': '\ud83d\ude06', + 'saudi_arabia': '\ud83c\uddf8\ud83c\udde6', + 'sauna_man': '\ud83e\uddd6\u200d\u2642\ufe0f', + 'sauna_person': '\ud83e\uddd6', + 'sauna_woman': '\ud83e\uddd6\u200d\u2640\ufe0f', + 'sauropod': '\ud83e\udd95', + 'saxophone': '\ud83c\udfb7', + 'scarf': '\ud83e\udde3', + 'school': '\ud83c\udfeb', + 'school_satchel': '\ud83c\udf92', + 'scientist': '\ud83e\uddd1\u200d\ud83d\udd2c', + 'scissors': '\u2702\ufe0f', + 'scorpion': '\ud83e\udd82', + 'scorpius': '\u264f', + 'scotland': '\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f', + 'scream': '\ud83d\ude31', + 'scream_cat': '\ud83d\ude40', + 'scroll': '\ud83d\udcdc', + 'seat': '\ud83d\udcba', + 'secret': '\u3299\ufe0f', + 'see_no_evil': '\ud83d\ude48', + 'seedling': '\ud83c\udf31', + 'selfie': '\ud83e\udd33', + 'senegal': '\ud83c\uddf8\ud83c\uddf3', + 'serbia': '\ud83c\uddf7\ud83c\uddf8', + 'service_dog': '\ud83d\udc15\u200d\ud83e\uddba', + 'seven': '7\ufe0f\u20e3', + 'seychelles': '\ud83c\uddf8\ud83c\udde8', + 'shallow_pan_of_food': '\ud83e\udd58', + 'shamrock': '\u2618\ufe0f', + 'shark': '\ud83e\udd88', + 'shaved_ice': '\ud83c\udf67', + 'sheep': '\ud83d\udc11', + 'shell': '\ud83d\udc1a', + 'shield': '\ud83d\udee1\ufe0f', + 'shinto_shrine': '\u26e9\ufe0f', + 'ship': '\ud83d\udea2', + 'shirt': '\ud83d\udc55', + 'shit': '\ud83d\udca9', + 'shoe': '\ud83d\udc5e', + 'shopping': '\ud83d\udecd\ufe0f', + 'shopping_cart': '\ud83d\uded2', + 'shorts': '\ud83e\ude73', + 'shower': '\ud83d\udebf', + 'shrimp': '\ud83e\udd90', + 'shrug': '\ud83e\udd37', + 'shushing_face': '\ud83e\udd2b', + 'sierra_leone': '\ud83c\uddf8\ud83c\uddf1', + 'signal_strength': '\ud83d\udcf6', + 'singapore': '\ud83c\uddf8\ud83c\uddec', + 'singer': '\ud83e\uddd1\u200d\ud83c\udfa4', + 'sint_maarten': '\ud83c\uddf8\ud83c\uddfd', + 'six': '6\ufe0f\u20e3', + 'six_pointed_star': '\ud83d\udd2f', + 'skateboard': '\ud83d\udef9', + 'ski': '\ud83c\udfbf', + 'skier': '\u26f7\ufe0f', + 'skull': '\ud83d\udc80', + 'skull_and_crossbones': '\u2620\ufe0f', + 'skunk': '\ud83e\udda8', + 'sled': '\ud83d\udef7', + 'sleeping': '\ud83d\ude34', + 'sleeping_bed': '\ud83d\udecc', + 'sleepy': '\ud83d\ude2a', + 'slightly_frowning_face': '\ud83d\ude41', + 'slightly_smiling_face': '\ud83d\ude42', + 'slot_machine': '\ud83c\udfb0', + 'sloth': '\ud83e\udda5', + 'slovakia': '\ud83c\uddf8\ud83c\uddf0', + 'slovenia': '\ud83c\uddf8\ud83c\uddee', + 'small_airplane': '\ud83d\udee9\ufe0f', + 'small_blue_diamond': '\ud83d\udd39', + 'small_orange_diamond': '\ud83d\udd38', + 'small_red_triangle': '\ud83d\udd3a', + 'small_red_triangle_down': '\ud83d\udd3b', + 'smile': '\ud83d\ude04', + 'smile_cat': '\ud83d\ude38', + 'smiley': '\ud83d\ude03', + 'smiley_cat': '\ud83d\ude3a', + 'smiling_face_with_three_hearts': '\ud83e\udd70', + 'smiling_imp': '\ud83d\ude08', + 'smirk': '\ud83d\ude0f', + 'smirk_cat': '\ud83d\ude3c', + 'smoking': '\ud83d\udeac', + 'snail': '\ud83d\udc0c', + 'snake': '\ud83d\udc0d', + 'sneezing_face': '\ud83e\udd27', + 'snowboarder': '\ud83c\udfc2', + 'snowflake': '\u2744\ufe0f', + 'snowman': '\u26c4', + 'snowman_with_snow': '\u2603\ufe0f', + 'soap': '\ud83e\uddfc', + 'sob': '\ud83d\ude2d', + 'soccer': '\u26bd', + 'socks': '\ud83e\udde6', + 'softball': '\ud83e\udd4e', + 'solomon_islands': '\ud83c\uddf8\ud83c\udde7', + 'somalia': '\ud83c\uddf8\ud83c\uddf4', + 'soon': '\ud83d\udd1c', + 'sos': '\ud83c\udd98', + 'sound': '\ud83d\udd09', + 'south_africa': '\ud83c\uddff\ud83c\udde6', + 'south_georgia_south_sandwich_islands': '\ud83c\uddec\ud83c\uddf8', + 'south_sudan': '\ud83c\uddf8\ud83c\uddf8', + 'space_invader': '\ud83d\udc7e', + 'spades': '\u2660\ufe0f', + 'spaghetti': '\ud83c\udf5d', + 'sparkle': '\u2747\ufe0f', + 'sparkler': '\ud83c\udf87', + 'sparkles': '\u2728', + 'sparkling_heart': '\ud83d\udc96', + 'speak_no_evil': '\ud83d\ude4a', + 'speaker': '\ud83d\udd08', + 'speaking_head': '\ud83d\udde3\ufe0f', + 'speech_balloon': '\ud83d\udcac', + 'speedboat': '\ud83d\udea4', + 'spider': '\ud83d\udd77\ufe0f', + 'spider_web': '\ud83d\udd78\ufe0f', + 'spiral_calendar': '\ud83d\uddd3\ufe0f', + 'spiral_notepad': '\ud83d\uddd2\ufe0f', + 'sponge': '\ud83e\uddfd', + 'spoon': '\ud83e\udd44', + 'squid': '\ud83e\udd91', + 'sri_lanka': '\ud83c\uddf1\ud83c\uddf0', + 'st_barthelemy': '\ud83c\udde7\ud83c\uddf1', + 'st_helena': '\ud83c\uddf8\ud83c\udded', + 'st_kitts_nevis': '\ud83c\uddf0\ud83c\uddf3', + 'st_lucia': '\ud83c\uddf1\ud83c\udde8', + 'st_martin': '\ud83c\uddf2\ud83c\uddeb', + 'st_pierre_miquelon': '\ud83c\uddf5\ud83c\uddf2', + 'st_vincent_grenadines': '\ud83c\uddfb\ud83c\udde8', + 'stadium': '\ud83c\udfdf\ufe0f', + 'standing_man': '\ud83e\uddcd\u200d\u2642\ufe0f', + 'standing_person': '\ud83e\uddcd', + 'standing_woman': '\ud83e\uddcd\u200d\u2640\ufe0f', + 'star': '\u2b50', + 'star2': '\ud83c\udf1f', + 'star_and_crescent': '\u262a\ufe0f', + 'star_of_david': '\u2721\ufe0f', + 'star_struck': '\ud83e\udd29', + 'stars': '\ud83c\udf20', + 'station': '\ud83d\ude89', + 'statue_of_liberty': '\ud83d\uddfd', + 'steam_locomotive': '\ud83d\ude82', + 'stethoscope': '\ud83e\ude7a', + 'stew': '\ud83c\udf72', + 'stop_button': '\u23f9\ufe0f', + 'stop_sign': '\ud83d\uded1', + 'stopwatch': '\u23f1\ufe0f', + 'straight_ruler': '\ud83d\udccf', + 'strawberry': '\ud83c\udf53', + 'stuck_out_tongue': '\ud83d\ude1b', + 'stuck_out_tongue_closed_eyes': '\ud83d\ude1d', + 'stuck_out_tongue_winking_eye': '\ud83d\ude1c', + 'student': '\ud83e\uddd1\u200d\ud83c\udf93', + 'studio_microphone': '\ud83c\udf99\ufe0f', + 'stuffed_flatbread': '\ud83e\udd59', + 'sudan': '\ud83c\uddf8\ud83c\udde9', + 'sun_behind_large_cloud': '\ud83c\udf25\ufe0f', + 'sun_behind_rain_cloud': '\ud83c\udf26\ufe0f', + 'sun_behind_small_cloud': '\ud83c\udf24\ufe0f', + 'sun_with_face': '\ud83c\udf1e', + 'sunflower': '\ud83c\udf3b', + 'sunglasses': '\ud83d\ude0e', + 'sunny': '\u2600\ufe0f', + 'sunrise': '\ud83c\udf05', + 'sunrise_over_mountains': '\ud83c\udf04', + 'superhero': '\ud83e\uddb8', + 'superhero_man': '\ud83e\uddb8\u200d\u2642\ufe0f', + 'superhero_woman': '\ud83e\uddb8\u200d\u2640\ufe0f', + 'supervillain': '\ud83e\uddb9', + 'supervillain_man': '\ud83e\uddb9\u200d\u2642\ufe0f', + 'supervillain_woman': '\ud83e\uddb9\u200d\u2640\ufe0f', + 'surfer': '\ud83c\udfc4', + 'surfing_man': '\ud83c\udfc4\u200d\u2642\ufe0f', + 'surfing_woman': '\ud83c\udfc4\u200d\u2640\ufe0f', + 'suriname': '\ud83c\uddf8\ud83c\uddf7', + 'sushi': '\ud83c\udf63', + 'suspension_railway': '\ud83d\ude9f', + 'svalbard_jan_mayen': '\ud83c\uddf8\ud83c\uddef', + 'swan': '\ud83e\udda2', + 'swaziland': '\ud83c\uddf8\ud83c\uddff', + 'sweat': '\ud83d\ude13', + 'sweat_drops': '\ud83d\udca6', + 'sweat_smile': '\ud83d\ude05', + 'sweden': '\ud83c\uddf8\ud83c\uddea', + 'sweet_potato': '\ud83c\udf60', + 'swim_brief': '\ud83e\ude72', + 'swimmer': '\ud83c\udfca', + 'swimming_man': '\ud83c\udfca\u200d\u2642\ufe0f', + 'swimming_woman': '\ud83c\udfca\u200d\u2640\ufe0f', + 'switzerland': '\ud83c\udde8\ud83c\udded', + 'symbols': '\ud83d\udd23', + 'synagogue': '\ud83d\udd4d', + 'syria': '\ud83c\uddf8\ud83c\uddfe', + 'syringe': '\ud83d\udc89', + 't-rex': '\ud83e\udd96', + 'taco': '\ud83c\udf2e', + 'tada': '\ud83c\udf89', + 'taiwan': '\ud83c\uddf9\ud83c\uddfc', + 'tajikistan': '\ud83c\uddf9\ud83c\uddef', + 'takeout_box': '\ud83e\udd61', + 'tanabata_tree': '\ud83c\udf8b', + 'tangerine': '\ud83c\udf4a', + 'tanzania': '\ud83c\uddf9\ud83c\uddff', + 'taurus': '\u2649', + 'taxi': '\ud83d\ude95', + 'tea': '\ud83c\udf75', + 'teacher': '\ud83e\uddd1\u200d\ud83c\udfeb', + 'technologist': '\ud83e\uddd1\u200d\ud83d\udcbb', + 'teddy_bear': '\ud83e\uddf8', + 'telephone': '\u260e\ufe0f', + 'telephone_receiver': '\ud83d\udcde', + 'telescope': '\ud83d\udd2d', + 'tennis': '\ud83c\udfbe', + 'tent': '\u26fa', + 'test_tube': '\ud83e\uddea', + 'thailand': '\ud83c\uddf9\ud83c\udded', + 'thermometer': '\ud83c\udf21\ufe0f', + 'thinking': '\ud83e\udd14', + 'thought_balloon': '\ud83d\udcad', + 'thread': '\ud83e\uddf5', + 'three': '3\ufe0f\u20e3', + 'thumbsdown': '\ud83d\udc4e', + 'thumbsup': '\ud83d\udc4d', + 'ticket': '\ud83c\udfab', + 'tickets': '\ud83c\udf9f\ufe0f', + 'tiger': '\ud83d\udc2f', + 'tiger2': '\ud83d\udc05', + 'timer_clock': '\u23f2\ufe0f', + 'timor_leste': '\ud83c\uddf9\ud83c\uddf1', + 'tipping_hand_man': '\ud83d\udc81\u200d\u2642\ufe0f', + 'tipping_hand_person': '\ud83d\udc81', + 'tipping_hand_woman': '\ud83d\udc81\u200d\u2640\ufe0f', + 'tired_face': '\ud83d\ude2b', + 'tm': '\u2122\ufe0f', + 'togo': '\ud83c\uddf9\ud83c\uddec', + 'toilet': '\ud83d\udebd', + 'tokelau': '\ud83c\uddf9\ud83c\uddf0', + 'tokyo_tower': '\ud83d\uddfc', + 'tomato': '\ud83c\udf45', + 'tonga': '\ud83c\uddf9\ud83c\uddf4', + 'tongue': '\ud83d\udc45', + 'toolbox': '\ud83e\uddf0', + 'tooth': '\ud83e\uddb7', + 'top': '\ud83d\udd1d', + 'tophat': '\ud83c\udfa9', + 'tornado': '\ud83c\udf2a\ufe0f', + 'tr': '\ud83c\uddf9\ud83c\uddf7', + 'trackball': '\ud83d\uddb2\ufe0f', + 'tractor': '\ud83d\ude9c', + 'traffic_light': '\ud83d\udea5', + 'train': '\ud83d\ude8b', + 'train2': '\ud83d\ude86', + 'tram': '\ud83d\ude8a', + 'triangular_flag_on_post': '\ud83d\udea9', + 'triangular_ruler': '\ud83d\udcd0', + 'trident': '\ud83d\udd31', + 'trinidad_tobago': '\ud83c\uddf9\ud83c\uddf9', + 'tristan_da_cunha': '\ud83c\uddf9\ud83c\udde6', + 'triumph': '\ud83d\ude24', + 'trolleybus': '\ud83d\ude8e', + 'trophy': '\ud83c\udfc6', + 'tropical_drink': '\ud83c\udf79', + 'tropical_fish': '\ud83d\udc20', + 'truck': '\ud83d\ude9a', + 'trumpet': '\ud83c\udfba', + 'tshirt': '\ud83d\udc55', + 'tulip': '\ud83c\udf37', + 'tumbler_glass': '\ud83e\udd43', + 'tunisia': '\ud83c\uddf9\ud83c\uddf3', + 'turkey': '\ud83e\udd83', + 'turkmenistan': '\ud83c\uddf9\ud83c\uddf2', + 'turks_caicos_islands': '\ud83c\uddf9\ud83c\udde8', + 'turtle': '\ud83d\udc22', + 'tuvalu': '\ud83c\uddf9\ud83c\uddfb', + 'tv': '\ud83d\udcfa', + 'twisted_rightwards_arrows': '\ud83d\udd00', + 'two': '2\ufe0f\u20e3', + 'two_hearts': '\ud83d\udc95', + 'two_men_holding_hands': '\ud83d\udc6c', + 'two_women_holding_hands': '\ud83d\udc6d', + 'u5272': '\ud83c\ude39', + 'u5408': '\ud83c\ude34', + 'u55b6': '\ud83c\ude3a', + 'u6307': '\ud83c\ude2f', + 'u6708': '\ud83c\ude37\ufe0f', + 'u6709': '\ud83c\ude36', + 'u6e80': '\ud83c\ude35', + 'u7121': '\ud83c\ude1a', + 'u7533': '\ud83c\ude38', + 'u7981': '\ud83c\ude32', + 'u7a7a': '\ud83c\ude33', + 'uganda': '\ud83c\uddfa\ud83c\uddec', + 'uk': '\ud83c\uddec\ud83c\udde7', + 'ukraine': '\ud83c\uddfa\ud83c\udde6', + 'umbrella': '\u2614', + 'unamused': '\ud83d\ude12', + 'underage': '\ud83d\udd1e', + 'unicorn': '\ud83e\udd84', + 'united_arab_emirates': '\ud83c\udde6\ud83c\uddea', + 'united_nations': '\ud83c\uddfa\ud83c\uddf3', + 'unlock': '\ud83d\udd13', + 'up': '\ud83c\udd99', + 'upside_down_face': '\ud83d\ude43', + 'uruguay': '\ud83c\uddfa\ud83c\uddfe', + 'us': '\ud83c\uddfa\ud83c\uddf8', + 'us_outlying_islands': '\ud83c\uddfa\ud83c\uddf2', + 'us_virgin_islands': '\ud83c\uddfb\ud83c\uddee', + 'uzbekistan': '\ud83c\uddfa\ud83c\uddff', + 'v': '\u270c\ufe0f', + 'vampire': '\ud83e\udddb', + 'vampire_man': '\ud83e\udddb\u200d\u2642\ufe0f', + 'vampire_woman': '\ud83e\udddb\u200d\u2640\ufe0f', + 'vanuatu': '\ud83c\uddfb\ud83c\uddfa', + 'vatican_city': '\ud83c\uddfb\ud83c\udde6', + 'venezuela': '\ud83c\uddfb\ud83c\uddea', + 'vertical_traffic_light': '\ud83d\udea6', + 'vhs': '\ud83d\udcfc', + 'vibration_mode': '\ud83d\udcf3', + 'video_camera': '\ud83d\udcf9', + 'video_game': '\ud83c\udfae', + 'vietnam': '\ud83c\uddfb\ud83c\uddf3', + 'violin': '\ud83c\udfbb', + 'virgo': '\u264d', + 'volcano': '\ud83c\udf0b', + 'volleyball': '\ud83c\udfd0', + 'vomiting_face': '\ud83e\udd2e', + 'vs': '\ud83c\udd9a', + 'vulcan_salute': '\ud83d\udd96', + 'waffle': '\ud83e\uddc7', + 'wales': '\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f', + 'walking': '\ud83d\udeb6', + 'walking_man': '\ud83d\udeb6\u200d\u2642\ufe0f', + 'walking_woman': '\ud83d\udeb6\u200d\u2640\ufe0f', + 'wallis_futuna': '\ud83c\uddfc\ud83c\uddeb', + 'waning_crescent_moon': '\ud83c\udf18', + 'waning_gibbous_moon': '\ud83c\udf16', + 'warning': '\u26a0\ufe0f', + 'wastebasket': '\ud83d\uddd1\ufe0f', + 'watch': '\u231a', + 'water_buffalo': '\ud83d\udc03', + 'water_polo': '\ud83e\udd3d', + 'watermelon': '\ud83c\udf49', + 'wave': '\ud83d\udc4b', + 'wavy_dash': '\u3030\ufe0f', + 'waxing_crescent_moon': '\ud83c\udf12', + 'waxing_gibbous_moon': '\ud83c\udf14', + 'wc': '\ud83d\udebe', + 'weary': '\ud83d\ude29', + 'wedding': '\ud83d\udc92', + 'weight_lifting': '\ud83c\udfcb\ufe0f', + 'weight_lifting_man': '\ud83c\udfcb\ufe0f\u200d\u2642\ufe0f', + 'weight_lifting_woman': '\ud83c\udfcb\ufe0f\u200d\u2640\ufe0f', + 'western_sahara': '\ud83c\uddea\ud83c\udded', + 'whale': '\ud83d\udc33', + 'whale2': '\ud83d\udc0b', + 'wheel_of_dharma': '\u2638\ufe0f', + 'wheelchair': '\u267f', + 'white_check_mark': '\u2705', + 'white_circle': '\u26aa', + 'white_flag': '\ud83c\udff3\ufe0f', + 'white_flower': '\ud83d\udcae', + 'white_haired_man': '\ud83d\udc68\u200d\ud83e\uddb3', + 'white_haired_woman': '\ud83d\udc69\u200d\ud83e\uddb3', + 'white_heart': '\ud83e\udd0d', + 'white_large_square': '\u2b1c', + 'white_medium_small_square': '\u25fd', + 'white_medium_square': '\u25fb\ufe0f', + 'white_small_square': '\u25ab\ufe0f', + 'white_square_button': '\ud83d\udd33', + 'wilted_flower': '\ud83e\udd40', + 'wind_chime': '\ud83c\udf90', + 'wind_face': '\ud83c\udf2c\ufe0f', + 'wine_glass': '\ud83c\udf77', + 'wink': '\ud83d\ude09', + 'wolf': '\ud83d\udc3a', + 'woman': '\ud83d\udc69', + 'woman_artist': '\ud83d\udc69\u200d\ud83c\udfa8', + 'woman_astronaut': '\ud83d\udc69\u200d\ud83d\ude80', + 'woman_cartwheeling': '\ud83e\udd38\u200d\u2640\ufe0f', + 'woman_cook': '\ud83d\udc69\u200d\ud83c\udf73', + 'woman_dancing': '\ud83d\udc83', + 'woman_facepalming': '\ud83e\udd26\u200d\u2640\ufe0f', + 'woman_factory_worker': '\ud83d\udc69\u200d\ud83c\udfed', + 'woman_farmer': '\ud83d\udc69\u200d\ud83c\udf3e', + 'woman_firefighter': '\ud83d\udc69\u200d\ud83d\ude92', + 'woman_health_worker': '\ud83d\udc69\u200d\u2695\ufe0f', + 'woman_in_manual_wheelchair': '\ud83d\udc69\u200d\ud83e\uddbd', + 'woman_in_motorized_wheelchair': '\ud83d\udc69\u200d\ud83e\uddbc', + 'woman_judge': '\ud83d\udc69\u200d\u2696\ufe0f', + 'woman_juggling': '\ud83e\udd39\u200d\u2640\ufe0f', + 'woman_mechanic': '\ud83d\udc69\u200d\ud83d\udd27', + 'woman_office_worker': '\ud83d\udc69\u200d\ud83d\udcbc', + 'woman_pilot': '\ud83d\udc69\u200d\u2708\ufe0f', + 'woman_playing_handball': '\ud83e\udd3e\u200d\u2640\ufe0f', + 'woman_playing_water_polo': '\ud83e\udd3d\u200d\u2640\ufe0f', + 'woman_scientist': '\ud83d\udc69\u200d\ud83d\udd2c', + 'woman_shrugging': '\ud83e\udd37\u200d\u2640\ufe0f', + 'woman_singer': '\ud83d\udc69\u200d\ud83c\udfa4', + 'woman_student': '\ud83d\udc69\u200d\ud83c\udf93', + 'woman_teacher': '\ud83d\udc69\u200d\ud83c\udfeb', + 'woman_technologist': '\ud83d\udc69\u200d\ud83d\udcbb', + 'woman_with_headscarf': '\ud83e\uddd5', + 'woman_with_probing_cane': '\ud83d\udc69\u200d\ud83e\uddaf', + 'woman_with_turban': '\ud83d\udc73\u200d\u2640\ufe0f', + 'womans_clothes': '\ud83d\udc5a', + 'womans_hat': '\ud83d\udc52', + 'women_wrestling': '\ud83e\udd3c\u200d\u2640\ufe0f', + 'womens': '\ud83d\udeba', + 'woozy_face': '\ud83e\udd74', + 'world_map': '\ud83d\uddfa\ufe0f', + 'worried': '\ud83d\ude1f', + 'wrench': '\ud83d\udd27', + 'wrestling': '\ud83e\udd3c', + 'writing_hand': '\u270d\ufe0f', + 'x': '\u274c', + 'yarn': '\ud83e\uddf6', + 'yawning_face': '\ud83e\udd71', + 'yellow_circle': '\ud83d\udfe1', + 'yellow_heart': '\ud83d\udc9b', + 'yellow_square': '\ud83d\udfe8', + 'yemen': '\ud83c\uddfe\ud83c\uddea', + 'yen': '\ud83d\udcb4', + 'yin_yang': '\u262f\ufe0f', + 'yo_yo': '\ud83e\ude80', + 'yum': '\ud83d\ude0b', + 'zambia': '\ud83c\uddff\ud83c\uddf2', + 'zany_face': '\ud83e\udd2a', + 'zap': '\u26a1', + 'zebra': '\ud83e\udd93', + 'zero': '0\ufe0f\u20e3', + 'zimbabwe': '\ud83c\uddff\ud83c\uddfc', + 'zipper_mouth_face': '\ud83e\udd10', + 'zombie': '\ud83e\udddf', + 'zombie_man': '\ud83e\udddf\u200d\u2642\ufe0f', + 'zombie_woman': '\ud83e\udddf\u200d\u2640\ufe0f', + 'zzz': '\ud83d\udca4', + + /* special emojis :P */ + 'atom': '', + 'basecamp': '', + 'basecampy': '', + 'bowtie': '', + 'electron': '', + 'feelsgood': '', + 'finnadie': '', + 'goberserk': '', + 'godmode': '', + 'hurtrealbad': '', + 'neckbeard': '', + 'octocat': '', + 'rage1': '', + 'rage2': '', + 'rage3': '', + 'rage4': '', + 'shipit': '', + 'suspect': '', + 'trollface': '', + 'showdown': '' +}; + +/** + * These are all the transformations that form block-level + * tags like paragraphs, headers, and list items. + */ +showdown.subParser('makehtml.blockGamut', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.blockGamut.before', text, options, globals).getText(); + + // we parse blockquotes first so that we can have headings and hrs + // inside blockquotes + text = showdown.subParser('makehtml.blockQuotes')(text, options, globals); + text = showdown.subParser('makehtml.headers')(text, options, globals); + + // Do Horizontal Rules: + text = showdown.subParser('makehtml.horizontalRule')(text, options, globals); + + text = showdown.subParser('makehtml.lists')(text, options, globals); + text = showdown.subParser('makehtml.codeBlocks')(text, options, globals); + text = showdown.subParser('makehtml.tables')(text, options, globals); + + // We already ran _HashHTMLBlocks() before, in Markdown(), but that + // was to escape raw HTML in the original Markdown source. This time, + // we're escaping the markup we've just created, so that we don't wrap + //

tags around block-level tags. + text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals); + text = showdown.subParser('makehtml.paragraphs')(text, options, globals); + + text = globals.converter._dispatch('makehtml.blockGamut.after', text, options, globals).getText(); + + return text; +}); + +showdown.subParser('makehtml.blockQuotes', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.blockQuotes.before', text, options, globals).getText(); + + // add a couple extra lines after the text and endtext mark + text = text + '\n\n'; + + var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm; + + if (options.splitAdjacentBlockquotes) { + rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm; + } + + text = text.replace(rgx, function (bq) { + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting + + // attacklab: clean up hack + bq = bq.replace(/ยจ0/g, ''); + + bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines + bq = showdown.subParser('makehtml.githubCodeBlocks')(bq, options, globals); + bq = showdown.subParser('makehtml.blockGamut')(bq, options, globals); // recurse + + bq = bq.replace(/(^|\n)/g, '$1 '); + // These leading spaces screw with

 content, so we need to fix that:
+    bq = bq.replace(/(\s*
[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
+      var pre = m1;
+      // attacklab: hack around Konqueror 3.5.4 bug:
+      pre = pre.replace(/^  /mg, 'ยจ0');
+      pre = pre.replace(/ยจ0/g, '');
+      return pre;
+    });
+
+    return showdown.subParser('makehtml.hashBlock')('
\n' + bq + '\n
', options, globals); + }); + + text = globals.converter._dispatch('makehtml.blockQuotes.after', text, options, globals).getText(); + return text; +}); + +/** + * Process Markdown `
` blocks.
+ */
+showdown.subParser('makehtml.codeBlocks', function (text, options, globals) {
+  'use strict';
+
+  text = globals.converter._dispatch('makehtml.codeBlocks.before', text, options, globals).getText();
+
+  // sentinel workarounds for lack of \A and \Z, safari\khtml bug
+  text += 'ยจ0';
+
+  var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=ยจ0))/g;
+  text = text.replace(pattern, function (wholeMatch, m1, m2) {
+    var codeblock = m1,
+        nextChar = m2,
+        end = '\n';
+
+    codeblock = showdown.subParser('makehtml.outdent')(codeblock, options, globals);
+    codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals);
+    codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals);
+    codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
+    codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
+
+    if (options.omitExtraWLInCodeBlocks) {
+      end = '';
+    }
+
+    codeblock = '
' + codeblock + end + '
'; + + return showdown.subParser('makehtml.hashBlock')(codeblock, options, globals) + nextChar; + }); + + // strip sentinel + text = text.replace(/ยจ0/, ''); + + text = globals.converter._dispatch('makehtml.codeBlocks.after', text, options, globals).getText(); + return text; +}); + +/** + * + * * Backtick quotes are used for spans. + * + * * You can use multiple backticks as the delimiters if you want to + * include literal backticks in the code span. So, this input: + * + * Just type ``foo `bar` baz`` at the prompt. + * + * Will translate to: + * + *

Just type foo `bar` baz at the prompt.

+ * + * There's no arbitrary limit to the number of backticks you + * can use as delimters. If you need three consecutive backticks + * in your code, use four for delimiters, etc. + * + * * You can use spaces to get literal backticks at the edges: + * + * ... type `` `bar` `` ... + * + * Turns to: + * + * ... type `bar` ... + */ +showdown.subParser('makehtml.codeSpans', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.codeSpans.before', text, options, globals).getText(); + + if (typeof (text) === 'undefined') { + text = ''; + } + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, + function (wholeMatch, m1, m2, m3) { + var c = m3; + c = c.replace(/^([ \t]*)/g, ''); // leading whitespace + c = c.replace(/[ \t]*$/g, ''); // trailing whitespace + c = showdown.subParser('makehtml.encodeCode')(c, options, globals); + c = m1 + '' + c + ''; + c = showdown.subParser('makehtml.hashHTMLSpans')(c, options, globals); + return c; + } + ); + + text = globals.converter._dispatch('makehtml.codeSpans.after', text, options, globals).getText(); + return text; +}); + +/** + * Create a full HTML document from the processed markdown + */ +showdown.subParser('makehtml.completeHTMLDocument', function (text, options, globals) { + 'use strict'; + + if (!options.completeHTMLDocument) { + return text; + } + + text = globals.converter._dispatch('makehtml.completeHTMLDocument.before', text, options, globals).getText(); + + var doctype = 'html', + doctypeParsed = '\n', + title = '', + charset = '\n', + lang = '', + metadata = ''; + + if (typeof globals.metadata.parsed.doctype !== 'undefined') { + doctypeParsed = '\n'; + doctype = globals.metadata.parsed.doctype.toString().toLowerCase(); + if (doctype === 'html' || doctype === 'html5') { + charset = ''; + } + } + + for (var meta in globals.metadata.parsed) { + if (globals.metadata.parsed.hasOwnProperty(meta)) { + switch (meta.toLowerCase()) { + case 'doctype': + break; + + case 'title': + title = '' + globals.metadata.parsed.title + '\n'; + break; + + case 'charset': + if (doctype === 'html' || doctype === 'html5') { + charset = '\n'; + } else { + charset = '\n'; + } + break; + + case 'language': + case 'lang': + lang = ' lang="' + globals.metadata.parsed[meta] + '"'; + metadata += '\n'; + break; + + default: + metadata += '\n'; + } + } + } + + text = doctypeParsed + '\n\n' + title + charset + metadata + '\n\n' + text.trim() + '\n\n'; + + text = globals.converter._dispatch('makehtml.completeHTMLDocument.after', text, options, globals).getText(); + return text; +}); + +/** + * Convert all tabs to spaces + */ +showdown.subParser('makehtml.detab', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.detab.before', text, options, globals).getText(); + + // expand first n-1 tabs + text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width + + // replace the nth with two sentinels + text = text.replace(/\t/g, 'ยจAยจB'); + + // use the sentinel to anchor our regex so it doesn't explode + text = text.replace(/ยจB(.+?)ยจA/g, function (wholeMatch, m1) { + var leadingText = m1, + numSpaces = 4 - leadingText.length % 4; // g_tab_width + + // there *must* be a better way to do this: + for (var i = 0; i < numSpaces; i++) { + leadingText += ' '; + } + + return leadingText; + }); + + // clean up sentinels + text = text.replace(/ยจA/g, ' '); // g_tab_width + text = text.replace(/ยจB/g, ''); + + text = globals.converter._dispatch('makehtml.detab.after', text, options, globals).getText(); + return text; +}); + +showdown.subParser('makehtml.ellipsis', function (text, options, globals) { + 'use strict'; + + if (!options.ellipsis) { + return text; + } + + text = globals.converter._dispatch('makehtml.ellipsis.before', text, options, globals).getText(); + + text = text.replace(/\.\.\./g, 'โ€ฆ'); + + text = globals.converter._dispatch('makehtml.ellipsis.after', text, options, globals).getText(); + + return text; +}); + +/** + * Turn emoji codes into emojis + * + * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis + */ +showdown.subParser('makehtml.emoji', function (text, options, globals) { + 'use strict'; + + if (!options.emoji) { + return text; + } + + text = globals.converter._dispatch('makehtml.emoji.before', text, options, globals).getText(); + + var emojiRgx = /:([\S]+?):/g; + + text = text.replace(emojiRgx, function (wm, emojiCode) { + if (showdown.helper.emojis.hasOwnProperty(emojiCode)) { + return showdown.helper.emojis[emojiCode]; + } + return wm; + }); + + text = globals.converter._dispatch('makehtml.emoji.after', text, options, globals).getText(); + + return text; +}); + +/** + * Smart processing for ampersands and angle brackets that need to be encoded. + */ +showdown.subParser('makehtml.encodeAmpsAndAngles', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.before', text, options, globals).getText(); + + // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: + // http://bumppo.net/projects/amputator/ + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&'); + + // Encode naked <'s + text = text.replace(/<(?![a-z\/?$!])/gi, '<'); + + // Encode < + text = text.replace(/ + text = text.replace(/>/g, '>'); + + text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.after', text, options, globals).getText(); + return text; +}); + +/** + * Returns the string, with after processing the following backslash escape sequences. + * + * attacklab: The polite way to do this is with the new escapeCharacters() function: + * + * text = escapeCharacters(text,"\\",true); + * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); + * + * ...but we're sidestepping its use of the (slow) RegExp constructor + * as an optimization for Firefox. This function gets called a LOT. + */ +showdown.subParser('makehtml.encodeBackslashEscapes', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.before', text, options, globals).getText(); + + text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback); + text = text.replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g, showdown.helper.escapeCharactersCallback); + + text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.after', text, options, globals).getText(); + return text; +}); + +/** + * Encode/escape certain characters inside Markdown code runs. + * The point is that in code, these characters are literals, + * and lose their special Markdown meanings. + */ +showdown.subParser('makehtml.encodeCode', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.encodeCode.before', text, options, globals).getText(); + + // Encode all ampersands; HTML entities are not + // entities within a Markdown code span. + text = text + .replace(/&/g, '&') + // Do the angle bracket song and dance: + .replace(//g, '>') + // Now, escape characters that are magic in Markdown: + .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback); + + text = globals.converter._dispatch('makehtml.encodeCode.after', text, options, globals).getText(); + return text; +}); + +/** + * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they + * don't conflict with their use in Markdown for code, italics and strong. + */ +showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.before', text, options, globals).getText(); + + // Build a regex to find HTML tags. + var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi, + comments = /-]|-[^>])(?:[^-]|-[^-])*)--)>/gi; + + text = text.replace(tags, function (wholeMatch) { + return wholeMatch + .replace(/(.)<\/?code>(?=.)/g, '$1`') + .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback); + }); + + text = text.replace(comments, function (wholeMatch) { + return wholeMatch + .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback); + }); + + text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.after', text, options, globals).getText(); + return text; +}); + +/** + * Handle github codeblocks prior to running HashHTML so that + * HTML contained within the codeblock gets escaped properly + * Example: + * ```ruby + * def hello_world(x) + * puts "Hello, #{x}" + * end + * ``` + */ +showdown.subParser('makehtml.githubCodeBlocks', function (text, options, globals) { + 'use strict'; + + // early exit if option is not enabled + if (!options.ghCodeBlocks) { + return text; + } + + text = globals.converter._dispatch('makehtml.githubCodeBlocks.before', text, options, globals).getText(); + + text += 'ยจ0'; + + text = text.replace(/(?:^|\n) {0,3}(```+|~~~+) *([^\n\t`~]*)\n([\s\S]*?)\n {0,3}\1/g, function (wholeMatch, delim, language, codeblock) { + var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n'; + + // if the language has spaces followed by some other chars, according to the spec we should just ignore everything + // after the first space + language = language.trim().split(' ')[0]; + + // First parse the github code block + codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals); + codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals); + codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines + codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace + + codeblock = '
' + codeblock + end + '
'; + + codeblock = showdown.subParser('makehtml.hashBlock')(codeblock, options, globals); + + // Since GHCodeblocks can be false positives, we need to + // store the primitive text and the parsed text in a global var, + // and then return a token + return '\n\nยจG' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n'; + }); + + // attacklab: strip sentinel + text = text.replace(/ยจ0/, ''); + + return globals.converter._dispatch('makehtml.githubCodeBlocks.after', text, options, globals).getText(); +}); + +showdown.subParser('makehtml.hashBlock', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.hashBlock.before', text, options, globals).getText(); + text = text.replace(/(^\n+|\n+$)/g, ''); + text = '\n\nยจK' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n'; + text = globals.converter._dispatch('makehtml.hashBlock.after', text, options, globals).getText(); + return text; +}); + +/** + * Hash and escape elements that should not be parsed as markdown + */ +showdown.subParser('makehtml.hashCodeTags', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.hashCodeTags.before', text, options, globals).getText(); + + var repFunc = function (wholeMatch, match, left, right) { + var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right; + return 'ยจC' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C'; + }; + + // Hash naked + text = showdown.helper.replaceRecursiveRegExp(text, repFunc, ']*>', '', 'gim'); + + text = globals.converter._dispatch('makehtml.hashCodeTags.after', text, options, globals).getText(); + return text; +}); + +showdown.subParser('makehtml.hashElement', function (text, options, globals) { + 'use strict'; + + return function (wholeMatch, m1) { + var blockText = m1; + + // Undo double lines + blockText = blockText.replace(/\n\n/g, '\n'); + blockText = blockText.replace(/^\n/, ''); + + // strip trailing blank lines + blockText = blockText.replace(/\n+$/g, ''); + + // Replace the element text with a marker ("ยจKxK" where x is its key) + blockText = '\n\nยจK' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n'; + + return blockText; + }; +}); + +showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.hashHTMLBlocks.before', text, options, globals).getText(); + + var blockTags = [ + 'pre', + 'div', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'blockquote', + 'table', + 'dl', + 'ol', + 'ul', + 'script', + 'noscript', + 'form', + 'fieldset', + 'iframe', + 'math', + 'style', + 'section', + 'header', + 'footer', + 'nav', + 'article', + 'aside', + 'address', + 'audio', + 'canvas', + 'figure', + 'hgroup', + 'output', + 'video', + 'details', + 'p' + ], + repFunc = function (wholeMatch, match, left, right) { + var txt = wholeMatch; + // check if this html element is marked as markdown + // if so, it's contents should be parsed as markdown + if (left.search(/\bmarkdown\b/) !== -1) { + txt = left + globals.converter.makeHtml(match) + right; + } + return '\n\nยจK' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n'; + }; + + if (options.backslashEscapesHTMLTags) { + // encode backslash escaped HTML tags + text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) { + return '<' + inside + '>'; + }); + } + + // hash HTML Blocks + for (var i = 0; i < blockTags.length; ++i) { + + var opTagPos, + rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'), + patLeft = '<' + blockTags[i] + '\\b[^>]*>', + patRight = ''; + // 1. Look for the first position of the first opening HTML tag in the text + while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) { + + // if the HTML tag is \ escaped, we need to escape it and break + + + //2. Split the text in that position + var subTexts = showdown.helper.splitAtIndex(text, opTagPos), + //3. Match recursively + newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im'); + + // prevent an infinite loop + if (newSubText1 === subTexts[1]) { + break; + } + text = subTexts[0].concat(newSubText1); + } + } + // HR SPECIAL CASE + text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, + showdown.subParser('makehtml.hashElement')(text, options, globals)); + + // Special case for standalone HTML comments + text = showdown.helper.replaceRecursiveRegExp(text, function (txt) { + return '\n\nยจK' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n'; + }, '^ {0,3}', 'gm'); + + // PHP and ASP-style processor instructions ( and <%...%>) + text = text.replace(/\n\n( {0,3}<([?%])[^\r]*?\2>[ \t]*(?=\n{2,}))/g, + showdown.subParser('makehtml.hashElement')(text, options, globals)); + + text = globals.converter._dispatch('makehtml.hashHTMLBlocks.after', text, options, globals).getText(); + return text; +}); + +/** + * Hash span elements that should not be parsed as markdown + */ +showdown.subParser('makehtml.hashHTMLSpans', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.hashHTMLSpans.before', text, options, globals).getText(); + + // Hash Self Closing tags + text = text.replace(/<[^>]+?\/>/gi, function (wm) { + return showdown.helper._hashHTMLSpan(wm, globals); + }); + + // Hash tags without properties + text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) { + return showdown.helper._hashHTMLSpan(wm, globals); + }); + + // Hash tags with properties + text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) { + return showdown.helper._hashHTMLSpan(wm, globals); + }); + + // Hash self closing tags without /> + text = text.replace(/<[^>]+?>/gi, function (wm) { + return showdown.helper._hashHTMLSpan(wm, globals); + }); + + text = globals.converter._dispatch('makehtml.hashHTMLSpans.after', text, options, globals).getText(); + return text; +}); + +/** + * Unhash HTML spans + */ +showdown.subParser('makehtml.unhashHTMLSpans', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.unhashHTMLSpans.before', text, options, globals).getText(); + + for (var i = 0; i < globals.gHtmlSpans.length; ++i) { + var repText = globals.gHtmlSpans[i], + // limiter to prevent infinite loop (assume 10 as limit for recurse) + limit = 0; + + while (/ยจC(\d+)C/.test(repText)) { + var num = RegExp.$1; + repText = repText.replace('ยจC' + num + 'C', globals.gHtmlSpans[num]); + if (limit === 10) { + console.error('maximum nesting of 10 spans reached!!!'); + break; + } + ++limit; + } + text = text.replace('ยจC' + i + 'C', repText); + } + + text = globals.converter._dispatch('makehtml.unhashHTMLSpans.after', text, options, globals).getText(); + return text; +}); + +/** + * Hash and escape
 elements that should not be parsed as markdown
+ */
+showdown.subParser('makehtml.hashPreCodeTags', function (text, options, globals) {
+  'use strict';
+  text = globals.converter._dispatch('makehtml.hashPreCodeTags.before', text, options, globals).getText();
+
+  var repFunc = function (wholeMatch, match, left, right) {
+    // encode html entities
+    var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right;
+    return '\n\nยจG' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
+  };
+
+  // Hash 

+  text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}]*>\\s*]*>', '^ {0,3}\\s*
', 'gim'); + + text = globals.converter._dispatch('makehtml.hashPreCodeTags.after', text, options, globals).getText(); + return text; +}); + +showdown.subParser('makehtml.headers', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.headers.before', text, options, globals).getText(); + + var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart), + + // Set text-style headers: + // Header 1 + // ======== + // + // Header 2 + // -------- + // + setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm, + setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm; + + text = text.replace(setextRegexH1, function (wholeMatch, m1) { + + var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals), + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', + hLevel = headerLevelStart, + hashBlock = '' + spanGamut + ''; + return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals); + }); + + text = text.replace(setextRegexH2, function (matchFound, m1) { + var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals), + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', + hLevel = headerLevelStart + 1, + hashBlock = '' + spanGamut + ''; + return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals); + }); + + // atx-style headers: + // # Header 1 + // ## Header 2 + // ## Header 2 with closing hashes ## + // ... + // ###### Header 6 + // + var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm; + + text = text.replace(atxStyle, function (wholeMatch, m1, m2) { + var hText = m2; + if (options.customizedHeaderId) { + hText = m2.replace(/\s?{([^{]+?)}\s*$/, ''); + } + + var span = showdown.subParser('makehtml.spanGamut')(hText, options, globals), + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"', + hLevel = headerLevelStart - 1 + m1.length, + header = '' + span + ''; + + return showdown.subParser('makehtml.hashBlock')(header, options, globals); + }); + + function headerId (m) { + var title, + prefix; + + // It is separate from other options to allow combining prefix and customized + if (options.customizedHeaderId) { + var match = m.match(/{([^{]+?)}\s*$/); + if (match && match[1]) { + m = match[1]; + } + } + + title = m; + + // Prefix id to prevent causing inadvertent pre-existing style matches. + if (showdown.helper.isString(options.prefixHeaderId)) { + prefix = options.prefixHeaderId; + } else if (options.prefixHeaderId === true) { + prefix = 'section-'; + } else { + prefix = ''; + } + + if (!options.rawPrefixHeaderId) { + title = prefix + title; + } + + if (options.ghCompatibleHeaderId) { + title = title + .replace(/ /g, '-') + // replace previously escaped chars (&, ยจ and $) + .replace(/&/g, '') + .replace(/ยจT/g, '') + .replace(/ยจD/g, '') + // replace rest of the chars (&~$ are repeated as they might have been escaped) + // borrowed from github's redcarpet (some they should produce similar results) + .replace(/[&+$,\/:;=?@"#{}|^ยจ~\[\]`\\*)(%.!'<>]/g, '') + .toLowerCase(); + } else if (options.rawHeaderId) { + title = title + .replace(/ /g, '-') + // replace previously escaped chars (&, ยจ and $) + .replace(/&/g, '&') + .replace(/ยจT/g, 'ยจ') + .replace(/ยจD/g, '$') + // replace " and ' + .replace(/["']/g, '-') + .toLowerCase(); + } else { + title = title + .replace(/[^\w]/g, '') + .toLowerCase(); + } + + if (options.rawPrefixHeaderId) { + title = prefix + title; + } + + if (globals.hashLinkCounts[title]) { + title = title + '-' + (globals.hashLinkCounts[title]++); + } else { + globals.hashLinkCounts[title] = 1; + } + return title; + } + + text = globals.converter._dispatch('makehtml.headers.after', text, options, globals).getText(); + return text; +}); + +/** + * Turn Markdown horizontal rule shortcuts into
tags. + * + * Any 3 or more unindented consecutive hyphens, asterisks or underscores with or without a space beetween them + * in a single line is considered a horizontal rule + */ +showdown.subParser('makehtml.horizontalRule', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.horizontalRule.before', text, options, globals).getText(); + + var key = showdown.subParser('makehtml.hashBlock')('
', options, globals); + text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key); + text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key); + text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key); + + text = globals.converter._dispatch('makehtml.horizontalRule.after', text, options, globals).getText(); + return text; +}); + +/** + * Turn Markdown image shortcuts into tags. + */ +showdown.subParser('makehtml.images', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.images.before', text, options, globals).getText(); + + var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, + crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g, + base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, + referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g, + refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g; + + function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) { + url = url.replace(/\s/g, ''); + return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title); + } + + function writeImageTagBaseUrl (wholeMatch, altText, linkId, url, width, height, m5, title) { + url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); + + return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title); + } + + function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) { + + var gUrls = globals.gUrls, + gTitles = globals.gTitles, + gDims = globals.gDimensions; + + linkId = linkId.toLowerCase(); + + if (!title) { + title = ''; + } + // Special case for explicit empty url + if (wholeMatch.search(/\(? ?(['"].*['"])?\)$/m) > -1) { + url = ''; + + } else if (url === '' || url === null) { + if (linkId === '' || linkId === null) { + // lower-case and turn embedded newlines into spaces + linkId = altText.toLowerCase().replace(/ ?\n/g, ' '); + } + url = '#' + linkId; + + if (!showdown.helper.isUndefined(gUrls[linkId])) { + url = gUrls[linkId]; + if (!showdown.helper.isUndefined(gTitles[linkId])) { + title = gTitles[linkId]; + } + if (!showdown.helper.isUndefined(gDims[linkId])) { + width = gDims[linkId].width; + height = gDims[linkId].height; + } + } else { + return wholeMatch; + } + } + + altText = altText + .replace(/"/g, '"') + //altText = showdown.helper.escapeCharacters(altText, '*_', false); + .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + //url = showdown.helper.escapeCharacters(url, '*_', false); + url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + var result = '' + altText + 'x "optional title") + + // base64 encoded images + text = text.replace(base64RegExp, writeImageTagBase64); + + // cases with crazy urls like ./image/cat1).png + text = text.replace(crazyRegExp, writeImageTagBaseUrl); + + // normal cases + text = text.replace(inlineRegExp, writeImageTagBaseUrl); + + // handle reference-style shortcuts: ![img text] + text = text.replace(refShortcutRegExp, writeImageTag); + + text = globals.converter._dispatch('makehtml.images.after', text, options, globals).getText(); + return text; +}); + +showdown.subParser('makehtml.italicsAndBold', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.italicsAndBold.before', text, options, globals).getText(); + + // it's faster to have 3 separate regexes for each case than have just one + // because of backtracing, in some cases, it could lead to an exponential effect + // called "catastrophic backtrace". Ominous! + + function parseInside (txt, left, right) { + return left + txt + right; + } + + // Parse underscores + if (options.literalMidWordUnderscores) { + text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { + return parseInside (txt, '', ''); + }); + text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { + return parseInside (txt, '', ''); + }); + text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) { + return parseInside (txt, '', ''); + }); + } else { + text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; + }); + text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; + }); + text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) { + // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it) + return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; + }); + } + + // Now parse asterisks + /* + if (options.literalMidWordAsterisks) { + text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]+?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) { + return parseInside (txt, lead + '', ''); + }); + text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]+?)\*\*\B(?!\*)/g, function (wm, lead, txt) { + return parseInside (txt, lead + '', ''); + }); + text = text.replace(/([^*]|^)\B\*(\S[\s\S]+?)\*\B(?!\*)/g, function (wm, lead, txt) { + return parseInside (txt, lead + '', ''); + }); + } else { + */ + text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; + }); + text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; + }); + text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) { + // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it) + return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; + }); + //} + + text = globals.converter._dispatch('makehtml.italicsAndBold.after', text, options, globals).getText(); + return text; +}); + +//// +// makehtml/links.js +// Copyright (c) 2018 ShowdownJS +// +// Transforms MD links into `` html anchors +// +// A link contains link text (the visible text), a link destination (the URI that is the link destination), and +// optionally a link title. There are two basic kinds of links in Markdown. +// In inline links the destination and title are given immediately after the link text. +// In reference links the destination and title are defined elsewhere in the document. +// +// ***Author:*** +// - Estevรฃo Soares dos Santos (Tivie) +//// + +(function () { + /** + * Helper function: Wrapper function to pass as second replace parameter + * + * @param {RegExp} rgx + * @param {string} evtRootName + * @param {{}} options + * @param {{}} globals + * @returns {Function} + */ + function replaceAnchorTagReference (rgx, evtRootName, options, globals, emptyCase) { + emptyCase = !!emptyCase; + return function (wholeMatch, text, id, url, m5, m6, title) { + // bail we we find 2 newlines somewhere + if (/\n\n/.test(wholeMatch)) { + return wholeMatch; + } + + var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals); + return writeAnchorTag(evt, options, globals, emptyCase); + }; + } + + function replaceAnchorTagBaseUrl (rgx, evtRootName, options, globals, emptyCase) { + return function (wholeMatch, text, id, url, m5, m6, title) { + url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); + + var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals); + return writeAnchorTag(evt, options, globals, emptyCase); + }; + } + + /** + * TODO Normalize this + * Helper function: Create a capture event + * @param {RegExp} rgx + * @param {String} evtName Event name + * @param {String} wholeMatch + * @param {String} text + * @param {String} id + * @param {String} url + * @param {String} title + * @param {{}} options + * @param {{}} globals + * @returns {showdown.helper.Event|*} + */ + function createEvent (rgx, evtName, wholeMatch, text, id, url, title, options, globals) { + return globals.converter._dispatch(evtName, wholeMatch, options, globals, { + regexp: rgx, + matches: { + wholeMatch: wholeMatch, + text: text, + id: id, + url: url, + title: title + } + }); + } + + /** + * Helper Function: Normalize and write an anchor tag based on passed parameters + * @param evt + * @param options + * @param globals + * @param {boolean} emptyCase + * @returns {string} + */ + function writeAnchorTag (evt, options, globals, emptyCase) { + + var wholeMatch = evt.getMatches().wholeMatch; + var text = evt.getMatches().text; + var id = evt.getMatches().id; + var url = evt.getMatches().url; + var title = evt.getMatches().title; + var target = ''; + + if (!title) { + title = ''; + } + id = (id) ? id.toLowerCase() : ''; + + if (emptyCase) { + url = ''; + } else if (!url) { + if (!id) { + // lower-case and turn embedded newlines into spaces + id = text.toLowerCase().replace(/ ?\n/g, ' '); + } + url = '#' + id; + + if (!showdown.helper.isUndefined(globals.gUrls[id])) { + url = globals.gUrls[id]; + if (!showdown.helper.isUndefined(globals.gTitles[id])) { + title = globals.gTitles[id]; + } + } else { + return wholeMatch; + } + } + //url = showdown.helper.escapeCharacters(url, '*_:~', false); // replaced line to improve performance + url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + + if (title !== '' && title !== null) { + title = title.replace(/"/g, '"'); + //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance + title = title.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + title = ' title="' + title + '"'; + } + + // optionLinksInNewWindow only applies + // to external links. Hash links (#) open in same page + if (options.openLinksInNewWindow && !/^#/.test(url)) { + // escaped _ + target = ' rel="noopener noreferrer" target="ยจE95Eblank"'; + } + + // Text can be a markdown element, so we run through the appropriate parsers + text = showdown.subParser('makehtml.codeSpans')(text, options, globals); + text = showdown.subParser('makehtml.emoji')(text, options, globals); + text = showdown.subParser('makehtml.underline')(text, options, globals); + text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals); + text = showdown.subParser('makehtml.strikethrough')(text, options, globals); + text = showdown.subParser('makehtml.ellipsis')(text, options, globals); + text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals); + + //evt = createEvent(rgx, evtRootName + '.captureEnd', wholeMatch, text, id, url, title, options, globals); + + var result = '' + text + ''; + + //evt = createEvent(rgx, evtRootName + '.beforeHash', wholeMatch, text, id, url, title, options, globals); + + result = showdown.subParser('makehtml.hashHTMLSpans')(result, options, globals); + + return result; + } + + var evtRootName = 'makehtml.links'; + + /** + * Turn Markdown link shortcuts into XHTML tags. + */ + showdown.subParser('makehtml.links', function (text, options, globals) { + + text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); + + // 1. Handle reference-style links: [link text] [id] + text = showdown.subParser('makehtml.links.reference')(text, options, globals); + + // 2. Handle inline-style links: [link text](url "optional title") + text = showdown.subParser('makehtml.links.inline')(text, options, globals); + + // 3. Handle reference-style shortcuts: [link text] + // These must come last in case there's a [link text][1] or [link text](/foo) + text = showdown.subParser('makehtml.links.referenceShortcut')(text, options, globals); + + // 4. Handle angle brackets links -> `` + // Must come after links, because you can use < and > delimiters in inline links like [this](). + text = showdown.subParser('makehtml.links.angleBrackets')(text, options, globals); + + // 5. Handle GithubMentions (if option is enabled) + text = showdown.subParser('makehtml.links.ghMentions')(text, options, globals); + + // 6. Handle tags and img tags + text = text.replace(/]*>[\s\S]*<\/a>/g, function (wholeMatch) { + return showdown.helper._hashHTMLSpan(wholeMatch, globals); + }); + + text = text.replace(/]*\/?>/g, function (wholeMatch) { + return showdown.helper._hashHTMLSpan(wholeMatch, globals); + }); + + // 7. Handle naked links (if option is enabled) + text = showdown.subParser('makehtml.links.naked')(text, options, globals); + + text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); + return text; + }); + + /** + * TODO WRITE THIS DOCUMENTATION + */ + showdown.subParser('makehtml.links.inline', function (text, options, globals) { + var evtRootName = evtRootName + '.inline'; + + text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); + + // 1. Look for empty cases: []() and [empty]() and []("title") + var rgxEmpty = /\[(.*?)]()()()()\(? ?(?:["'](.*)["'])?\)/g; + text = text.replace(rgxEmpty, replaceAnchorTagBaseUrl(rgxEmpty, evtRootName, options, globals, true)); + + // 2. Look for cases with crazy urls like ./image/cat1).png + var rgxCrazy = /\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g; + text = text.replace(rgxCrazy, replaceAnchorTagBaseUrl(rgxCrazy, evtRootName, options, globals)); + + // 3. inline links with no title or titles wrapped in ' or ": + // [text](url.com) || [text]() || [text](url.com "title") || [text]( "title") + //var rgx2 = /\[[ ]*[\s]?[ ]*([^\n\[\]]*?)[ ]*[\s]?[ ]*] ?()\(?(?:[ ]*[\n]?[ ]*()(['"])(.*?)\5)?[ ]*[\s]?[ ]*\)/; // this regex is too slow!!! + var rgx2 = /\[([\S ]*?)]\s?()\( *?\s*(?:()(['"])(.*?)\5)? *\)/g; + text = text.replace(rgx2, replaceAnchorTagBaseUrl(rgx2, evtRootName, options, globals)); + + // 4. inline links with titles wrapped in (): [foo](bar.com (title)) + var rgx3 = /\[([\S ]*?)]\s?()\( *?\s+()()\((.*?)\) *\)/g; + text = text.replace(rgx3, replaceAnchorTagBaseUrl(rgx3, evtRootName, options, globals)); + + text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); + + return text; + }); + + /** + * TODO WRITE THIS DOCUMENTATION + */ + showdown.subParser('makehtml.links.reference', function (text, options, globals) { + var evtRootName = evtRootName + '.reference'; + + text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); + + var rgx = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g; + text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals)); + + text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); + + return text; + }); + + /** + * TODO WRITE THIS DOCUMENTATION + */ + showdown.subParser('makehtml.links.referenceShortcut', function (text, options, globals) { + var evtRootName = evtRootName + '.referenceShortcut'; + + text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); + + var rgx = /\[([^\[\]]+)]()()()()()/g; + text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals)); + + text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); + + return text; + }); + + /** + * TODO WRITE THIS DOCUMENTATION + */ + showdown.subParser('makehtml.links.ghMentions', function (text, options, globals) { + var evtRootName = evtRootName + 'ghMentions'; + + if (!options.ghMentions) { + return text; + } + + text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); + + var rgx = /(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi; + + text = text.replace(rgx, function (wholeMatch, st, escape, mentions, username) { + // bail if the mentions was escaped + if (escape === '\\') { + return st + mentions; + } + + // check if options.ghMentionsLink is a string + // TODO Validation should be done at initialization not at runtime + if (!showdown.helper.isString(options.ghMentionsLink)) { + throw new Error('ghMentionsLink option must be a string'); + } + var url = options.ghMentionsLink.replace(/{u}/g, username); + var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, mentions, null, url, null, options, globals); + // captureEnd Event is triggered inside writeAnchorTag function + return st + writeAnchorTag(evt, options, globals); + }); + + text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); + + return text; + }); + + /** + * TODO WRITE THIS DOCUMENTATION + */ + showdown.subParser('makehtml.links.angleBrackets', function (text, options, globals) { + var evtRootName = 'makehtml.links.angleBrackets'; + + text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); + + // 1. Parse links first + var urlRgx = /<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi; + text = text.replace(urlRgx, function (wholeMatch, url, urlStart) { + var text = url; + url = (urlStart === 'www.') ? 'http://' + url : url; + var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals); + return writeAnchorTag(evt, options, globals); + }); + + // 2. Then Mail Addresses + var mailRgx = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi; + text = text.replace(mailRgx, function (wholeMatch, mail) { + var url = 'mailto:'; + mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals); + if (options.encodeEmails) { + url = showdown.helper.encodeEmailAddress(url + mail); + mail = showdown.helper.encodeEmailAddress(mail); + } else { + url = url + mail; + } + var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals); + return writeAnchorTag(evt, options, globals); + }); + + text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); + return text; + }); + + /** + * TODO MAKE THIS WORK (IT'S NOT ACTIVATED) + * TODO WRITE THIS DOCUMENTATION + */ + showdown.subParser('makehtml.links.naked', function (text, options, globals) { + if (!options.simplifiedAutoLink) { + return text; + } + + var evtRootName = 'makehtml.links.naked'; + + text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); + + // 2. Now we check for + // we also include leading markdown magic chars [_*~] for cases like __https://www.google.com/foobar__ + var urlRgx = /([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`ยด.-][^\s<>"'`ยด]*?\.[a-z\d.]+[^\s<>"']*)\1/gi; + text = text.replace(urlRgx, function (wholeMatch, leadingMDChars, url, urlPrefix) { + + // we now will start traversing the url from the front to back, looking for punctuation chars [_*~,;:.!?\)\]] + var len = url.length; + var suffix = ''; + for (var i = len - 1; i >= 0; --i) { + var char = url.charAt(i); + + if (/[_*~,;:.!?]/.test(char)) { + // it's a punctuation char + // we remove it from the url + url = url.slice(0, -1); + // and prepend it to the suffix + suffix = char + suffix; + } else if (/\)/.test(char)) { + var opPar = url.match(/\(/g) || []; + var clPar = url.match(/\)/g); + + // it's a curved parenthesis so we need to check for "balance" (kinda) + if (opPar.length < clPar.length) { + // there are more closing Parenthesis than opening so chop it!!!!! + url = url.slice(0, -1); + // and prepend it to the suffix + suffix = char + suffix; + } else { + // it's (kinda) balanced so our work is done + break; + } + } else if (/]/.test(char)) { + var opPar2 = url.match(/\[/g) || []; + var clPar2 = url.match(/\]/g); + // it's a squared parenthesis so we need to check for "balance" (kinda) + if (opPar2.length < clPar2.length) { + // there are more closing Parenthesis than opening so chop it!!!!! + url = url.slice(0, -1); + // and prepend it to the suffix + suffix = char + suffix; + } else { + // it's (kinda) balanced so our work is done + break; + } + } else { + // it's not a punctuation or a parenthesis so our work is done + break; + } + } + + // we copy the treated url to the text variable + var text = url; + // finally, if it's a www shortcut, we prepend http + url = (urlPrefix === 'www.') ? 'http://' + url : url; + + // url part is done so let's take care of text now + // we need to escape the text (because of links such as www.example.com/foo__bar__baz) + text = text.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + + // finally we dispatch the event + var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals); + + // and return the link tag, with the leadingMDChars and suffix. The leadingMDChars are added at the end too because + // we consumed those characters in the regexp + return leadingMDChars + writeAnchorTag(evt, options, globals) + suffix + leadingMDChars; + }); + + // 2. Then mails + var mailRgx = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi; + text = text.replace(mailRgx, function (wholeMatch, leadingChar, mail) { + var url = 'mailto:'; + mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals); + if (options.encodeEmails) { + url = showdown.helper.encodeEmailAddress(url + mail); + mail = showdown.helper.encodeEmailAddress(mail); + } else { + url = url + mail; + } + var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals); + return leadingChar + writeAnchorTag(evt, options, globals); + }); + + + text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); + return text; + }); +})(); + +/** + * Form HTML ordered (numbered) and unordered (bulleted) lists. + */ +showdown.subParser('makehtml.lists', function (text, options, globals) { + 'use strict'; + + /** + * Process the contents of a single ordered or unordered list, splitting it + * into individual list items. + * @param {string} listStr + * @param {boolean} trimTrailing + * @returns {string} + */ + function processListItems (listStr, trimTrailing) { + // The $g_list_level global keeps track of when we're inside a list. + // Each time we enter a list, we increment it; when we leave a list, + // we decrement. If it's zero, we're not in a list anymore. + // + // We do this because when we're not inside a list, we want to treat + // something like this: + // + // I recommend upgrading to version + // 8. Oops, now this line is treated + // as a sub-list. + // + // As a single paragraph, despite the fact that the second line starts + // with a digit-period-space sequence. + // + // Whereas when we're inside a list (or sub-list), that line will be + // treated as the start of a sub-list. What a kludge, huh? This is + // an aspect of Markdown's syntax that's hard to parse perfectly + // without resorting to mind-reading. Perhaps the solution is to + // change the syntax rules such that sub-lists must start with a + // starting cardinal number; e.g. "1." or "a.". + globals.gListLevel++; + + // trim trailing blank lines: + listStr = listStr.replace(/\n{2,}$/, '\n'); + + // attacklab: add sentinel to emulate \z + listStr += 'ยจ0'; + + var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[([xX ])])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(ยจ0| {0,3}([*+-]|\d+[.])[ \t]+))/gm, + isParagraphed = (/\n[ \t]*\n(?!ยจ0)/.test(listStr)); + + // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation, + // which is a syntax breaking change + // activating this option reverts to old behavior + // This will be removed in version 2.0 + if (options.disableForced4SpacesIndentedSublists) { + rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[([xX ])])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(ยจ0|\2([*+-]|\d+[.])[ \t]+))/gm; + } + + listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) { + checked = (checked && checked.trim() !== ''); + + var item = showdown.subParser('makehtml.outdent')(m4, options, globals), + bulletStyle = ''; + + // Support for github tasklists + if (taskbtn && options.tasklists) { + + // Style used for tasklist bullets + bulletStyle = ' class="task-list-item'; + if (options.moreStyling) {bulletStyle += checked ? ' task-list-item-complete' : '';} + bulletStyle += '" style="list-style-type: none;"'; + + item = item.replace(/^[ \t]*\[([xX ])?]/m, function () { + var otp = '
  • a
  • + // instead of: + //
    • - - a
    + // So, to prevent it, we will put a marker (ยจA)in the beginning of the line + // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser + item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) { + return 'ยจA' + wm2; + }); + + // SPECIAL CASE: a heading followed by a paragraph of text that is not separated by a double newline + // or/nor indented. ex: + // + // - # foo + // bar is great + // + // While this does now follow the spec per se, not allowing for this might cause confusion since + // header blocks don't need double-newlines after + if (/^#+.+\n.+/.test(item)) { + item = item.replace(/^(#+.+)$/m, '$1\n'); + } + + // m1 - Leading line or + // Has a double return (multi paragraph) + if (m1 || (item.search(/\n{2,}/) > -1)) { + item = showdown.subParser('makehtml.githubCodeBlocks')(item, options, globals); + item = showdown.subParser('makehtml.blockQuotes')(item, options, globals); + item = showdown.subParser('makehtml.headers')(item, options, globals); + item = showdown.subParser('makehtml.lists')(item, options, globals); + item = showdown.subParser('makehtml.codeBlocks')(item, options, globals); + item = showdown.subParser('makehtml.tables')(item, options, globals); + item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals); + //item = showdown.subParser('makehtml.paragraphs')(item, options, globals); + + // TODO: This is a copy of the paragraph parser + // This is a provisory fix for issue #494 + // For a permanente fix we need to rewrite the paragraph parser, passing the unhashify logic outside + // so that we can call the paragraph parser without accidently unashifying previously parsed blocks + + // Strip leading and trailing lines: + item = item.replace(/^\n+/g, ''); + item = item.replace(/\n+$/g, ''); + + var grafs = item.split(/\n{2,}/g), + grafsOut = [], + end = grafs.length; // Wrap

    tags + + for (var i = 0; i < end; i++) { + var str = grafs[i]; + // if this is an HTML marker, copy it + if (str.search(/ยจ([KG])(\d+)\1/g) >= 0) { + grafsOut.push(str); + + // test for presence of characters to prevent empty lines being parsed + // as paragraphs (resulting in undesired extra empty paragraphs) + } else if (str.search(/\S/) >= 0) { + str = showdown.subParser('makehtml.spanGamut')(str, options, globals); + str = str.replace(/^([ \t]*)/g, '

    '); + str += '

    '; + grafsOut.push(str); + } + } + item = grafsOut.join('\n'); + // Strip leading and trailing lines: + item = item.replace(/^\n+/g, ''); + item = item.replace(/\n+$/g, ''); + + } else { + + // Recursion for sub-lists: + item = showdown.subParser('makehtml.lists')(item, options, globals); + item = item.replace(/\n$/, ''); // chomp(item) + item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals); + + // Colapse double linebreaks + item = item.replace(/\n\n+/g, '\n\n'); + + if (isParagraphed) { + item = showdown.subParser('makehtml.paragraphs')(item, options, globals); + } else { + item = showdown.subParser('makehtml.spanGamut')(item, options, globals); + } + } + + // now we need to remove the marker (ยจA) + item = item.replace('ยจA', ''); + // we can finally wrap the line in list item tags + item = '' + item + '\n'; + + return item; + }); + + // attacklab: strip sentinel + listStr = listStr.replace(/ยจ0/g, ''); + + globals.gListLevel--; + + if (trimTrailing) { + listStr = listStr.replace(/\s+$/, ''); + } + + return listStr; + } + + function styleStartNumber (list, listType) { + // check if ol and starts by a number different than 1 + if (listType === 'ol') { + var res = list.match(/^ *(\d+)\./); + if (res && res[1] !== '1') { + return ' start="' + res[1] + '"'; + } + } + return ''; + } + + /** + * Check and parse consecutive lists (better fix for issue #142) + * @param {string} list + * @param {string} listType + * @param {boolean} trimTrailing + * @returns {string} + */ + function parseConsecutiveLists (list, listType, trimTrailing) { + // check if we caught 2 or more consecutive lists by mistake + // we use the counterRgx, meaning if listType is UL we look for OL and vice versa + var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm, + ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm, + counterRxg = (listType === 'ul') ? olRgx : ulRgx, + result = ''; + + if (list.search(counterRxg) !== -1) { + (function parseCL (txt) { + var pos = txt.search(counterRxg), + style = styleStartNumber(list, listType); + if (pos !== -1) { + // slice + result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '\n'; + + // invert counterType and listType + listType = (listType === 'ul') ? 'ol' : 'ul'; + counterRxg = (listType === 'ul') ? olRgx : ulRgx; + + //recurse + parseCL(txt.slice(pos)); + } else { + result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '\n'; + } + })(list); + } else { + var style = styleStartNumber(list, listType); + result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '\n'; + } + + return result; + } + + // Start of list parsing + var subListRgx = /^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(ยจ0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + var mainListRgx = /(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(ยจ0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + + text = globals.converter._dispatch('lists.before', text, options, globals).getText(); + // add sentinel to hack around khtml/safari bug: + // http://bugs.webkit.org/show_bug.cgi?id=11231 + text += 'ยจ0'; + + if (globals.gListLevel) { + text = text.replace(subListRgx, function (wholeMatch, list, m2) { + var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; + return parseConsecutiveLists(list, listType, true); + }); + } else { + text = text.replace(mainListRgx, function (wholeMatch, m1, list, m3) { + var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; + return parseConsecutiveLists(list, listType, false); + }); + } + + // strip sentinel + text = text.replace(/ยจ0/, ''); + text = globals.converter._dispatch('makehtml.lists.after', text, options, globals).getText(); + return text; +}); + +/** + * Parse metadata at the top of the document + */ +showdown.subParser('makehtml.metadata', function (text, options, globals) { + 'use strict'; + + if (!options.metadata) { + return text; + } + + text = globals.converter._dispatch('makehtml.metadata.before', text, options, globals).getText(); + + function parseMetadataContents (content) { + // raw is raw so it's not changed in any way + globals.metadata.raw = content; + + // escape chars forbidden in html attributes + // double quotes + content = content + // ampersand first + .replace(/&/g, '&') + // double quotes + .replace(/"/g, '"'); + + // Restore dollar signs and tremas + content = content + .replace(/ยจD/g, '$$') + .replace(/ยจT/g, 'ยจ'); + + content = content.replace(/\n {4}/g, ' '); + content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) { + globals.metadata.parsed[key] = value; + return ''; + }); + } + + text = text.replace(/^\s*ยซยซยซ+(\S*?)\n([\s\S]+?)\nยปยปยป+\n/, function (wholematch, format, content) { + parseMetadataContents(content); + return 'ยจM'; + }); + + text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) { + if (format) { + globals.metadata.format = format; + } + parseMetadataContents(content); + return 'ยจM'; + }); + + text = text.replace(/ยจM/g, ''); + + text = globals.converter._dispatch('makehtml.metadata.after', text, options, globals).getText(); + return text; +}); + +/** + * Remove one level of line-leading tabs or spaces + */ +showdown.subParser('makehtml.outdent', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.outdent.before', text, options, globals).getText(); + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + text = text.replace(/^(\t|[ ]{1,4})/gm, 'ยจ0'); // attacklab: g_tab_width + + // attacklab: clean up hack + text = text.replace(/ยจ0/g, ''); + + text = globals.converter._dispatch('makehtml.outdent.after', text, options, globals).getText(); + return text; +}); + +/** + * + */ +showdown.subParser('makehtml.paragraphs', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.paragraphs.before', text, options, globals).getText(); + // Strip leading and trailing lines: + text = text.replace(/^\n+/g, ''); + text = text.replace(/\n+$/g, ''); + + var grafs = text.split(/\n{2,}/g), + grafsOut = [], + end = grafs.length; // Wrap

    tags + + for (var i = 0; i < end; i++) { + var str = grafs[i]; + // if this is an HTML marker, copy it + if (str.search(/ยจ(K|G)(\d+)\1/g) >= 0) { + grafsOut.push(str); + + // test for presence of characters to prevent empty lines being parsed + // as paragraphs (resulting in undesired extra empty paragraphs) + } else if (str.search(/\S/) >= 0) { + str = showdown.subParser('makehtml.spanGamut')(str, options, globals); + str = str.replace(/^([ \t]*)/g, '

    '); + str += '

    '; + grafsOut.push(str); + } + } + + /** Unhashify HTML blocks */ + end = grafsOut.length; + for (i = 0; i < end; i++) { + var blockText = '', + grafsOutIt = grafsOut[i], + codeFlag = false; + // if this is a marker for an html block... + // use RegExp.test instead of string.search because of QML bug + while (/ยจ(K|G)(\d+)\1/.test(grafsOutIt)) { + var delim = RegExp.$1, + num = RegExp.$2; + + if (delim === 'K') { + blockText = globals.gHtmlBlocks[num]; + } else { + // we need to check if ghBlock is a false positive + if (codeFlag) { + // use encoded version of all text + blockText = showdown.subParser('makehtml.encodeCode')(globals.ghCodeBlocks[num].text, options, globals); + } else { + blockText = globals.ghCodeBlocks[num].codeblock; + } + } + blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs + + grafsOutIt = grafsOutIt.replace(/(\n\n)?ยจ(K|G)\d+\2(\n\n)?/, blockText); + // Check if grafsOutIt is a pre->code + if (/^]*>\s*]*>/.test(grafsOutIt)) { + codeFlag = true; + } + } + grafsOut[i] = grafsOutIt; + } + text = grafsOut.join('\n'); + // Strip leading and trailing lines: + text = text.replace(/^\n+/g, ''); + text = text.replace(/\n+$/g, ''); + return globals.converter._dispatch('makehtml.paragraphs.after', text, options, globals).getText(); +}); + +/** + * Run extension + */ +showdown.subParser('makehtml.runExtension', function (ext, text, options, globals) { + 'use strict'; + + if (ext.filter) { + text = ext.filter(text, globals.converter, options); + + } else if (ext.regex) { + // TODO remove this when old extension loading mechanism is deprecated + var re = ext.regex; + if (!(re instanceof RegExp)) { + re = new RegExp(re, 'g'); + } + text = text.replace(re, ext.replace); + } + + return text; +}); + +/** + * These are all the transformations that occur *within* block-level + * tags like paragraphs, headers, and list items. + */ +showdown.subParser('makehtml.spanGamut', function (text, options, globals) { + 'use strict'; + + text = globals.converter._dispatch('makehtml.span.before', text, options, globals).getText(); + + text = showdown.subParser('makehtml.codeSpans')(text, options, globals); + text = showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes')(text, options, globals); + text = showdown.subParser('makehtml.encodeBackslashEscapes')(text, options, globals); + + // Process link and image tags. Images must come first, + // because ![foo][f] looks like a link. + text = showdown.subParser('makehtml.images')(text, options, globals); + + text = globals.converter._dispatch('smakehtml.links.before', text, options, globals).getText(); + text = showdown.subParser('makehtml.links')(text, options, globals); + text = globals.converter._dispatch('smakehtml.links.after', text, options, globals).getText(); + + //text = showdown.subParser('makehtml.autoLinks')(text, options, globals); + //text = showdown.subParser('makehtml.simplifiedAutoLinks')(text, options, globals); + text = showdown.subParser('makehtml.emoji')(text, options, globals); + text = showdown.subParser('makehtml.underline')(text, options, globals); + text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals); + text = showdown.subParser('makehtml.strikethrough')(text, options, globals); + text = showdown.subParser('makehtml.ellipsis')(text, options, globals); + + // we need to hash HTML tags inside spans + text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals); + + // now we encode amps and angles + text = showdown.subParser('makehtml.encodeAmpsAndAngles')(text, options, globals); + + // Do hard breaks + if (options.simpleLineBreaks) { + // GFM style hard breaks + // only add line breaks if the text does not contain a block (special case for lists) + if (!/\n\nยจK/.test(text)) { + text = text.replace(/\n+/g, '
    \n'); + } + } else { + // Vanilla hard breaks + text = text.replace(/ +\n/g, '
    \n'); + } + + text = globals.converter._dispatch('makehtml.spanGamut.after', text, options, globals).getText(); + return text; +}); + +showdown.subParser('makehtml.strikethrough', function (text, options, globals) { + 'use strict'; + + if (options.strikethrough) { + text = globals.converter._dispatch('makehtml.strikethrough.before', text, options, globals).getText(); + text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return '' + txt + ''; }); + text = globals.converter._dispatch('makehtml.strikethrough.after', text, options, globals).getText(); + } + + return text; +}); + +/** + * Strips link definitions from text, stores the URLs and titles in + * hash references. + * Link defs are in the form: ^[id]: url "optional title" + */ +showdown.subParser('makehtml.stripLinkDefinitions', function (text, options, globals) { + 'use strict'; + + var regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=ยจ0))/gm, + base64Regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=ยจ0)|(?=\n\[))/gm; + + // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug + text += 'ยจ0'; + + var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) { + + // if there aren't two instances of linkId it must not be a reference link so back out + linkId = linkId.toLowerCase(); + if (text.toLowerCase().split(linkId).length - 1 < 2) { + return wholeMatch; + } + if (url.match(/^data:.+?\/.+?;base64,/)) { + // remove newlines + globals.gUrls[linkId] = url.replace(/\s/g, ''); + } else { + url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); + + globals.gUrls[linkId] = showdown.subParser('makehtml.encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive + } + + if (blankLines) { + // Oops, found blank lines, so it's not a title. + // Put back the parenthetical statement we stole. + return blankLines + title; + + } else { + if (title) { + globals.gTitles[linkId] = title.replace(/"|'/g, '"'); + } + if (options.parseImgDimensions && width && height) { + globals.gDimensions[linkId] = { + width: width, + height: height + }; + } + } + // Completely remove the definition from the text + return ''; + }; + + // first we try to find base64 link references + text = text.replace(base64Regex, replaceFunc); + + text = text.replace(regex, replaceFunc); + + // attacklab: strip sentinel + text = text.replace(/ยจ0/, ''); + + return text; +}); + +showdown.subParser('makehtml.tables', function (text, options, globals) { + 'use strict'; + + if (!options.tables) { + return text; + } + + var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*[-=]{2,}[\s\S]+?(?:\n\n|ยจ0)/gm, + //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|ยจ0)/gm; + singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|ยจ0)/gm; + + function parseStyles (sLine) { + if (/^:[ \t]*--*$/.test(sLine)) { + return ' style="text-align:left;"'; + } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) { + return ' style="text-align:right;"'; + } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) { + return ' style="text-align:center;"'; + } else { + return ''; + } + } + + function parseHeaders (header, style) { + var id = ''; + header = header.trim(); + // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility + if (options.tablesHeaderId || options.tableHeaderId) { + id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"'; + } + header = showdown.subParser('makehtml.spanGamut')(header, options, globals); + + return '' + header + '\n'; + } + + function parseCells (cell, style) { + var subText = showdown.subParser('makehtml.spanGamut')(cell, options, globals); + return '' + subText + '\n'; + } + + function buildTable (headers, cells) { + var tb = '\n\n\n', + tblLgn = headers.length; + + for (var i = 0; i < tblLgn; ++i) { + tb += headers[i]; + } + tb += '\n\n\n'; + + for (i = 0; i < cells.length; ++i) { + tb += '\n'; + for (var ii = 0; ii < tblLgn; ++ii) { + tb += cells[i][ii]; + } + tb += '\n'; + } + tb += '\n
    \n'; + return tb; + } + + function parseTable (rawTable) { + var i, tableLines = rawTable.split('\n'); + + for (i = 0; i < tableLines.length; ++i) { + // strip wrong first and last column if wrapped tables are used + if (/^ {0,3}\|/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, ''); + } + if (/\|[ \t]*$/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, ''); + } + // parse code spans first, but we only support one line code spans + + tableLines[i] = showdown.subParser('makehtml.codeSpans')(tableLines[i], options, globals); + } + + var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}), + rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}), + rawCells = [], + headers = [], + styles = [], + cells = []; + + tableLines.shift(); + tableLines.shift(); + + for (i = 0; i < tableLines.length; ++i) { + if (tableLines[i].trim() === '') { + continue; + } + rawCells.push( + tableLines[i] + .split('|') + .map(function (s) { + return s.trim(); + }) + ); + } + + if (rawHeaders.length < rawStyles.length) { + return rawTable; + } + + for (i = 0; i < rawStyles.length; ++i) { + styles.push(parseStyles(rawStyles[i])); + } + + for (i = 0; i < rawHeaders.length; ++i) { + if (showdown.helper.isUndefined(styles[i])) { + styles[i] = ''; + } + headers.push(parseHeaders(rawHeaders[i], styles[i])); + } + + for (i = 0; i < rawCells.length; ++i) { + var row = []; + for (var ii = 0; ii < headers.length; ++ii) { + if (showdown.helper.isUndefined(rawCells[i][ii])) { + + } + row.push(parseCells(rawCells[i][ii], styles[ii])); + } + cells.push(row); + } + + return buildTable(headers, cells); + } + + text = globals.converter._dispatch('makehtml.tables.before', text, options, globals).getText(); + + // find escaped pipe characters + text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback); + + // parse multi column tables + text = text.replace(tableRgx, parseTable); + + // parse one column tables + text = text.replace(singeColTblRgx, parseTable); + + text = globals.converter._dispatch('makehtml.tables.after', text, options, globals).getText(); + + return text; +}); + +showdown.subParser('makehtml.underline', function (text, options, globals) { + 'use strict'; + + if (!options.underline) { + return text; + } + + text = globals.converter._dispatch('makehtml.underline.before', text, options, globals).getText(); + + if (options.literalMidWordUnderscores) { + text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { + return '' + txt + ''; + }); + text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { + return '' + txt + ''; + }); + } else { + text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { + return (/\S$/.test(m)) ? '' + m + '' : wm; + }); + text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { + return (/\S$/.test(m)) ? '' + m + '' : wm; + }); + } + + // escape remaining underscores to prevent them being parsed by italic and bold + text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback); + + text = globals.converter._dispatch('makehtml.underline.after', text, options, globals).getText(); + + return text; +}); + +/** + * Swap back in all the special characters we've hidden. + */ +showdown.subParser('makehtml.unescapeSpecialChars', function (text, options, globals) { + 'use strict'; + text = globals.converter._dispatch('makehtml.unescapeSpecialChars.before', text, options, globals).getText(); + + text = text.replace(/ยจE(\d+)E/g, function (wholeMatch, m1) { + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + }); + + text = globals.converter._dispatch('makehtml.unescapeSpecialChars.after', text, options, globals).getText(); + return text; +}); + +showdown.subParser('makeMarkdown.blockquote', function (node, globals) { + 'use strict'; + + var txt = ''; + if (node.hasChildNodes()) { + var children = node.childNodes, + childrenLength = children.length; + + for (var i = 0; i < childrenLength; ++i) { + var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals); + + if (innerTxt === '') { + continue; + } + txt += innerTxt; + } + } + // cleanup + txt = txt.trim(); + txt = '> ' + txt.split('\n').join('\n> '); + return txt; +}); + +showdown.subParser('makeMarkdown.break', function () { + 'use strict'; + + return ' \n'; +}); + +showdown.subParser('makeMarkdown.codeBlock', function (node, globals) { + 'use strict'; + + var lang = node.getAttribute('language'), + num = node.getAttribute('precodenum'); + return '```' + lang + '\n' + globals.preList[num] + '\n```'; +}); + +showdown.subParser('makeMarkdown.codeSpan', function (node) { + 'use strict'; + + return '`' + node.innerHTML + '`'; +}); + +showdown.subParser('makeMarkdown.emphasis', function (node, globals) { + 'use strict'; + + var txt = ''; + if (node.hasChildNodes()) { + txt += '*'; + var children = node.childNodes, + childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + txt += '*'; + } + return txt; +}); + +showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) { + 'use strict'; + + var headerMark = new Array(headerLevel + 1).join('#'), + txt = ''; + + if (node.hasChildNodes()) { + txt = headerMark + ' '; + var children = node.childNodes, + childrenLength = children.length; + + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + } + return txt; +}); + +showdown.subParser('makeMarkdown.hr', function () { + 'use strict'; + + return '---'; +}); + +showdown.subParser('makeMarkdown.image', function (node) { + 'use strict'; + + var txt = ''; + if (node.hasAttribute('src')) { + txt += '![' + node.getAttribute('alt') + ']('; + txt += '<' + node.getAttribute('src') + '>'; + if (node.hasAttribute('width') && node.hasAttribute('height')) { + txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height'); + } + + if (node.hasAttribute('title')) { + txt += ' "' + node.getAttribute('title') + '"'; + } + txt += ')'; + } + return txt; +}); + +showdown.subParser('makeMarkdown.input', function (node, globals) { + 'use strict'; + + var txt = ''; + if (node.getAttribute('checked') !== null) { + txt += '[x]'; + } else { + txt += '[ ]'; + } + var children = node.childNodes, + childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + return txt; +}); + +showdown.subParser('makeMarkdown.links', function (node, globals) { + 'use strict'; + + var txt = ''; + if (node.hasChildNodes() && node.hasAttribute('href')) { + var children = node.childNodes, + childrenLength = children.length; + txt = '['; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + txt += ']('; + txt += '<' + node.getAttribute('href') + '>'; + if (node.hasAttribute('title')) { + txt += ' "' + node.getAttribute('title') + '"'; + } + txt += ')'; + } + return txt; +}); + +showdown.subParser('makeMarkdown.list', function (node, globals, type) { + 'use strict'; + + var txt = ''; + if (!node.hasChildNodes()) { + return ''; + } + var listItems = node.childNodes, + listItemsLenght = listItems.length, + listNum = node.getAttribute('start') || 1; + + for (var i = 0; i < listItemsLenght; ++i) { + if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') { + continue; + } + + // define the bullet to use in list + var bullet = ''; + if (type === 'ol') { + bullet = listNum.toString() + '. '; + } else { + bullet = '- '; + } + + // parse list item + txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals); + ++listNum; + } + + return txt.trim(); +}); + +showdown.subParser('makeMarkdown.listItem', function (node, globals) { + 'use strict'; + + var listItemTxt = ''; + + var children = node.childNodes, + childrenLenght = children.length; + + for (var i = 0; i < childrenLenght; ++i) { + listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + // if it's only one liner, we need to add a newline at the end + if (!/\n$/.test(listItemTxt)) { + listItemTxt += '\n'; + } else { + // it's multiparagraph, so we need to indent + listItemTxt = listItemTxt + .split('\n') + .join('\n ') + .replace(/^ {4}$/gm, '') + .replace(/\n\n+/g, '\n\n'); + } + + return listItemTxt; +}); + + + +showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) { + 'use strict'; + + spansOnly = spansOnly || false; + + var txt = ''; + + // edge case of text without wrapper paragraph + if (node.nodeType === 3) { + return showdown.subParser('makeMarkdown.txt')(node, globals); + } + + // HTML comment + if (node.nodeType === 8) { + return '\n\n'; + } + + // process only node elements + if (node.nodeType !== 1) { + return ''; + } + + var tagName = node.tagName.toLowerCase(); + + switch (tagName) { + + // + // BLOCKS + // + case 'h1': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; } + break; + case 'h2': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; } + break; + case 'h3': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; } + break; + case 'h4': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; } + break; + case 'h5': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; } + break; + case 'h6': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; } + break; + + case 'p': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; } + break; + + case 'blockquote': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; } + break; + + case 'hr': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; } + break; + + case 'ol': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; } + break; + + case 'ul': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; } + break; + + case 'precode': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; } + break; + + case 'pre': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; } + break; + + case 'table': + if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; } + break; + + // + // SPANS + // + case 'code': + txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals); + break; + + case 'em': + case 'i': + txt = showdown.subParser('makeMarkdown.emphasis')(node, globals); + break; + + case 'strong': + case 'b': + txt = showdown.subParser('makeMarkdown.strong')(node, globals); + break; + + case 'del': + txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals); + break; + + case 'a': + txt = showdown.subParser('makeMarkdown.links')(node, globals); + break; + + case 'img': + txt = showdown.subParser('makeMarkdown.image')(node, globals); + break; + + case 'br': + txt = showdown.subParser('makeMarkdown.break')(node, globals); + break; + + case 'input': + txt = showdown.subParser('makeMarkdown.input')(node, globals); + break; + + default: + txt = node.outerHTML + '\n\n'; + } + + // common normalization + // TODO eventually + + return txt; +}); + +showdown.subParser('makeMarkdown.paragraph', function (node, globals) { + 'use strict'; + + var txt = ''; + if (node.hasChildNodes()) { + var children = node.childNodes, + childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + } + + // some text normalization + txt = txt.trim(); + + return txt; +}); + +showdown.subParser('makeMarkdown.pre', function (node, globals) { + 'use strict'; + + var num = node.getAttribute('prenum'); + return '
    ' + globals.preList[num] + '
    '; +}); + +showdown.subParser('makeMarkdown.strikethrough', function (node, globals) { + 'use strict'; + + var txt = ''; + if (node.hasChildNodes()) { + txt += '~~'; + var children = node.childNodes, + childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + txt += '~~'; + } + return txt; +}); + +showdown.subParser('makeMarkdown.strong', function (node, globals) { + 'use strict'; + + var txt = ''; + if (node.hasChildNodes()) { + txt += '**'; + var children = node.childNodes, + childrenLength = children.length; + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals); + } + txt += '**'; + } + return txt; +}); + +showdown.subParser('makeMarkdown.table', function (node, globals) { + 'use strict'; + + var txt = '', + tableArray = [[], []], + headings = node.querySelectorAll('thead>tr>th'), + rows = node.querySelectorAll('tbody>tr'), + i, ii; + for (i = 0; i < headings.length; ++i) { + var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals), + allign = '---'; + + if (headings[i].hasAttribute('style')) { + var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, ''); + switch (style) { + case 'text-align:left;': + allign = ':---'; + break; + case 'text-align:right;': + allign = '---:'; + break; + case 'text-align:center;': + allign = ':---:'; + break; + } + } + tableArray[0][i] = headContent.trim(); + tableArray[1][i] = allign; + } + + for (i = 0; i < rows.length; ++i) { + var r = tableArray.push([]) - 1, + cols = rows[i].getElementsByTagName('td'); + + for (ii = 0; ii < headings.length; ++ii) { + var cellContent = ' '; + if (typeof cols[ii] !== 'undefined') { + cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals); + } + tableArray[r].push(cellContent); + } + } + + var cellSpacesCount = 3; + for (i = 0; i < tableArray.length; ++i) { + for (ii = 0; ii < tableArray[i].length; ++ii) { + var strLen = tableArray[i][ii].length; + if (strLen > cellSpacesCount) { + cellSpacesCount = strLen; + } + } + } + + for (i = 0; i < tableArray.length; ++i) { + for (ii = 0; ii < tableArray[i].length; ++ii) { + if (i === 1) { + if (tableArray[i][ii].slice(-1) === ':') { + tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(0, -1), cellSpacesCount - 1, '-') + ':'; + } else { + tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-'); + } + } else { + tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount); + } + } + txt += '| ' + tableArray[i].join(' | ') + ' |\n'; + } + + return txt.trim(); +}); + +showdown.subParser('makeMarkdown.tableCell', function (node, globals) { + 'use strict'; + + var txt = ''; + if (!node.hasChildNodes()) { + return ''; + } + var children = node.childNodes, + childrenLength = children.length; + + for (var i = 0; i < childrenLength; ++i) { + txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true); + } + return txt.trim(); +}); + +showdown.subParser('makeMarkdown.txt', function (node) { + 'use strict'; + + var txt = node.nodeValue; + + // multiple spaces are collapsed + txt = txt.replace(/ +/g, ' '); + + // replace the custom ยจNBSP; with a space + txt = txt.replace(/ยจNBSP;/g, ' '); + + // ", <, > and & should replace escaped html entities + txt = showdown.helper.unescapeHTMLEntities(txt); + + // escape markdown magic characters + // emphasis, strong and strikethrough - can appear everywhere + // we also escape pipe (|) because of tables + // and escape ` because of code blocks and spans + txt = txt.replace(/([*_~|`])/g, '\\$1'); + + // escape > because of blockquotes + txt = txt.replace(/^(\s*)>/g, '\\$1>'); + + // hash character, only troublesome at the beginning of a line because of headers + txt = txt.replace(/^#/gm, '\\#'); + + // horizontal rules + txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3'); + + // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer + txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.'); + + // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped) + txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2'); + + // images and links, ] followed by ( is problematic, so we escape it + txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\('); + + // reference URIs must also be escaped + txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:'); + + return txt; +}); + +/** + * Created by Estevao on 31-05-2015. + */ + +/** + * Showdown Converter class + * @class + * @param {object} [converterOptions] + * @returns {Converter} + */ +showdown.Converter = function (converterOptions) { + 'use strict'; + + var + /** + * Options used by this converter + * @private + * @type {{}} + */ + options = {}, + + /** + * Language extensions used by this converter + * @private + * @type {Array} + */ + langExtensions = [], + + /** + * Output modifiers extensions used by this converter + * @private + * @type {Array} + */ + outputModifiers = [], + + /** + * Event listeners + * @private + * @type {{}} + */ + listeners = {}, + + /** + * The flavor set in this converter + */ + setConvFlavor = setFlavor, + + /** + * Metadata of the document + * @type {{parsed: {}, raw: string, format: string}} + */ + metadata = { + parsed: {}, + raw: '', + format: '' + }; + + _constructor(); + + /** + * Converter constructor + * @private + */ + function _constructor () { + converterOptions = converterOptions || {}; + + for (var gOpt in globalOptions) { + if (globalOptions.hasOwnProperty(gOpt)) { + options[gOpt] = globalOptions[gOpt]; + } + } + + // Merge options + if (typeof converterOptions === 'object') { + for (var opt in converterOptions) { + if (converterOptions.hasOwnProperty(opt)) { + options[opt] = converterOptions[opt]; + } + } + } else { + throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions + + ' was passed instead.'); + } + + if (options.extensions) { + showdown.helper.forEach(options.extensions, _parseExtension); + } + } + + /** + * Parse extension + * @param {*} ext + * @param {string} [name=''] + * @private + */ + function _parseExtension (ext, name) { + + name = name || null; + // If it's a string, the extension was previously loaded + if (showdown.helper.isString(ext)) { + ext = showdown.helper.stdExtName(ext); + name = ext; + + // LEGACY_SUPPORT CODE + if (showdown.extensions[ext]) { + console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' + + 'Please inform the developer that the extension should be updated!'); + legacyExtensionLoading(showdown.extensions[ext], ext); + return; + // END LEGACY SUPPORT CODE + + } else if (!showdown.helper.isUndefined(extensions[ext])) { + ext = extensions[ext]; + + } else { + throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.'); + } + } + + if (typeof ext === 'function') { + ext = ext(); + } + + if (!showdown.helper.isArray(ext)) { + ext = [ext]; + } + + var validExt = validate(ext, name); + if (!validExt.valid) { + throw Error(validExt.error); + } + + for (var i = 0; i < ext.length; ++i) { + switch (ext[i].type) { + + case 'lang': + langExtensions.push(ext[i]); + break; + + case 'output': + outputModifiers.push(ext[i]); + break; + } + if (ext[i].hasOwnProperty('listeners')) { + for (var ln in ext[i].listeners) { + if (ext[i].listeners.hasOwnProperty(ln)) { + listen(ln, ext[i].listeners[ln]); + } + } + } + } + + } + + /** + * LEGACY_SUPPORT + * @param {*} ext + * @param {string} name + */ + function legacyExtensionLoading (ext, name) { + if (typeof ext === 'function') { + ext = ext(new showdown.Converter()); + } + if (!showdown.helper.isArray(ext)) { + ext = [ext]; + } + var valid = validate(ext, name); + + if (!valid.valid) { + throw Error(valid.error); + } + + for (var i = 0; i < ext.length; ++i) { + switch (ext[i].type) { + case 'lang': + langExtensions.push(ext[i]); + break; + case 'output': + outputModifiers.push(ext[i]); + break; + default:// should never reach here + throw Error('Extension loader error: Type unrecognized!!!'); + } + } + } + + /** + * Listen to an event + * @param {string} name + * @param {function} callback + */ + function listen (name, callback) { + if (!showdown.helper.isString(name)) { + throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given'); + } + + if (typeof callback !== 'function') { + throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given'); + } + name = name.toLowerCase(); + if (!listeners.hasOwnProperty(name)) { + listeners[name] = []; + } + listeners[name].push(callback); + } + + function rTrimInputText (text) { + var rsp = text.match(/^\s*/)[0].length, + rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm'); + return text.replace(rgx, ''); + } + + /** + * + * @param {string} evtName Event name + * @param {string} text Text + * @param {{}} options Converter Options + * @param {{}} globals Converter globals + * @param {{}} [pParams] extra params for event + * @returns showdown.helper.Event + * @private + */ + this._dispatch = function dispatch (evtName, text, options, globals, pParams) { + evtName = evtName.toLowerCase(); + var params = pParams || {}; + params.converter = this; + params.text = text; + params.options = options; + params.globals = globals; + var event = new showdown.helper.Event(evtName, text, params); + + if (listeners.hasOwnProperty(evtName)) { + for (var ei = 0; ei < listeners[evtName].length; ++ei) { + var nText = listeners[evtName][ei](event); + if (nText && typeof nText !== 'undefined') { + event.setText(nText); + } + } + } + return event; + }; + + /** + * Listen to an event + * @param {string} name + * @param {function} callback + * @returns {showdown.Converter} + */ + this.listen = function (name, callback) { + listen(name, callback); + return this; + }; + + /** + * Converts a markdown string into HTML string + * @param {string} text + * @returns {*} + */ + this.makeHtml = function (text) { + //check if text is not falsy + if (!text) { + return text; + } + + var globals = { + gHtmlBlocks: [], + gHtmlMdBlocks: [], + gHtmlSpans: [], + gUrls: {}, + gTitles: {}, + gDimensions: {}, + gListLevel: 0, + hashLinkCounts: {}, + langExtensions: langExtensions, + outputModifiers: outputModifiers, + converter: this, + ghCodeBlocks: [], + metadata: { + parsed: {}, + raw: '', + format: '' + } + }; + + // This lets us use ยจ trema as an escape char to avoid md5 hashes + // The choice of character is arbitrary; anything that isn't + // magic in Markdown will work. + text = text.replace(/ยจ/g, 'ยจT'); + + // Replace $ with ยจD + // RegExp interprets $ as a special character + // when it's in a replacement string + text = text.replace(/\$/g, 'ยจD'); + + // Standardize line endings + text = text.replace(/\r\n/g, '\n'); // DOS to Unix + text = text.replace(/\r/g, '\n'); // Mac to Unix + + // Stardardize line spaces + text = text.replace(/\u00A0/g, ' '); + + if (options.smartIndentationFix) { + text = rTrimInputText(text); + } + + // Make sure text begins and ends with a couple of newlines: + text = '\n\n' + text + '\n\n'; + + // detab + text = showdown.subParser('makehtml.detab')(text, options, globals); + + /** + * Strip any lines consisting only of spaces and tabs. + * This makes subsequent regexs easier to write, because we can + * match consecutive blank lines with /\n+/ instead of something + * contorted like /[ \t]*\n+/ + */ + text = text.replace(/^[ \t]+$/mg, ''); + + //run languageExtensions + showdown.helper.forEach(langExtensions, function (ext) { + text = showdown.subParser('makehtml.runExtension')(ext, text, options, globals); + }); + + // run the sub parsers + text = showdown.subParser('makehtml.metadata')(text, options, globals); + text = showdown.subParser('makehtml.hashPreCodeTags')(text, options, globals); + text = showdown.subParser('makehtml.githubCodeBlocks')(text, options, globals); + text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals); + text = showdown.subParser('makehtml.hashCodeTags')(text, options, globals); + text = showdown.subParser('makehtml.stripLinkDefinitions')(text, options, globals); + text = showdown.subParser('makehtml.blockGamut')(text, options, globals); + text = showdown.subParser('makehtml.unhashHTMLSpans')(text, options, globals); + text = showdown.subParser('makehtml.unescapeSpecialChars')(text, options, globals); + + // attacklab: Restore dollar signs + text = text.replace(/ยจD/g, '$$'); + + // attacklab: Restore tremas + text = text.replace(/ยจT/g, 'ยจ'); + + // render a complete html document instead of a partial if the option is enabled + text = showdown.subParser('makehtml.completeHTMLDocument')(text, options, globals); + + // Run output modifiers + showdown.helper.forEach(outputModifiers, function (ext) { + text = showdown.subParser('makehtml.runExtension')(ext, text, options, globals); + }); + + // update metadata + metadata = globals.metadata; + return text; + }; + + /** + * Converts an HTML string into a markdown string + * @param src + * @returns {string} + */ + this.makeMarkdown = function (src) { + + // replace \r\n with \n + src = src.replace(/\r\n/g, '\n'); + src = src.replace(/\r/g, '\n'); // old macs + + // due to an edge case, we need to find this: > < + // to prevent removing of non silent white spaces + // ex: this is sparta + src = src.replace(/>[ \t]+ยจNBSP;<'); + + var doc = showdown.helper.document.createElement('div'); + doc.innerHTML = src; + + var globals = { + preList: substitutePreCodeTags(doc) + }; + + // remove all newlines and collapse spaces + clean(doc); + + // some stuff, like accidental reference links must now be escaped + // TODO + // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/); + + var nodes = doc.childNodes, + mdDoc = ''; + + for (var i = 0; i < nodes.length; i++) { + mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals); + } + + function clean (node) { + for (var n = 0; n < node.childNodes.length; ++n) { + var child = node.childNodes[n]; + if (child.nodeType === 3) { + if (!/\S/.test(child.nodeValue) && !/^[ ]+$/.test(child.nodeValue)) { + node.removeChild(child); + --n; + } else { + child.nodeValue = child.nodeValue.split('\n').join(' '); + child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1'); + } + } else if (child.nodeType === 1) { + clean(child); + } + } + } + + // find all pre tags and replace contents with placeholder + // we need this so that we can remove all indentation from html + // to ease up parsing + function substitutePreCodeTags (doc) { + + var pres = doc.querySelectorAll('pre'), + presPH = []; + + for (var i = 0; i < pres.length; ++i) { + + if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') { + var content = pres[i].firstChild.innerHTML.trim(), + language = pres[i].firstChild.getAttribute('data-language') || ''; + + // if data-language attribute is not defined, then we look for class language-* + if (language === '') { + var classes = pres[i].firstChild.className.split(' '); + for (var c = 0; c < classes.length; ++c) { + var matches = classes[c].match(/^language-(.+)$/); + if (matches !== null) { + language = matches[1]; + break; + } + } + } + + // unescape html entities in content + content = showdown.helper.unescapeHTMLEntities(content); + + presPH.push(content); + pres[i].outerHTML = ''; + } else { + presPH.push(pres[i].innerHTML); + pres[i].innerHTML = ''; + pres[i].setAttribute('prenum', i.toString()); + } + } + return presPH; + } + + return mdDoc; + }; + + /** + * Set an option of this Converter instance + * @param {string} key + * @param {*} value + */ + this.setOption = function (key, value) { + options[key] = value; + }; + + /** + * Get the option of this Converter instance + * @param {string} key + * @returns {*} + */ + this.getOption = function (key) { + return options[key]; + }; + + /** + * Get the options of this Converter instance + * @returns {{}} + */ + this.getOptions = function () { + return options; + }; + + /** + * Add extension to THIS converter + * @param {{}} extension + * @param {string} [name=null] + */ + this.addExtension = function (extension, name) { + name = name || null; + _parseExtension(extension, name); + }; + + /** + * Use a global registered extension with THIS converter + * @param {string} extensionName Name of the previously registered extension + */ + this.useExtension = function (extensionName) { + _parseExtension(extensionName); + }; + + /** + * Set the flavor THIS converter should use + * @param {string} name + */ + this.setFlavor = function (name) { + if (!flavor.hasOwnProperty(name)) { + throw Error(name + ' flavor was not found'); + } + var preset = flavor[name]; + setConvFlavor = name; + for (var option in preset) { + if (preset.hasOwnProperty(option)) { + options[option] = preset[option]; + } + } + }; + + /** + * Get the currently set flavor of this converter + * @returns {string} + */ + this.getFlavor = function () { + return setConvFlavor; + }; + + /** + * Remove an extension from THIS converter. + * Note: This is a costly operation. It's better to initialize a new converter + * and specify the extensions you wish to use + * @param {Array} extension + */ + this.removeExtension = function (extension) { + if (!showdown.helper.isArray(extension)) { + extension = [extension]; + } + for (var a = 0; a < extension.length; ++a) { + var ext = extension[a]; + for (var i = 0; i < langExtensions.length; ++i) { + if (langExtensions[i] === ext) { + langExtensions.splice(i, 1); + } + } + for (var ii = 0; ii < outputModifiers.length; ++ii) { + if (outputModifiers[ii] === ext) { + outputModifiers.splice(ii, 1); + } + } + } + }; + + /** + * Get all extension of THIS converter + * @returns {{language: Array, output: Array}} + */ + this.getAllExtensions = function () { + return { + language: langExtensions, + output: outputModifiers + }; + }; + + /** + * Get the metadata of the previously parsed document + * @param raw + * @returns {string|{}} + */ + this.getMetadata = function (raw) { + if (raw) { + return metadata.raw; + } else { + return metadata.parsed; + } + }; + + /** + * Get the metadata format of the previously parsed document + * @returns {string} + */ + this.getMetadataFormat = function () { + return metadata.format; + }; + + /** + * Private: set a single key, value metadata pair + * @param {string} key + * @param {string} value + */ + this._setMetadataPair = function (key, value) { + metadata.parsed[key] = value; + }; + + /** + * Private: set metadata format + * @param {string} format + */ + this._setMetadataFormat = function (format) { + metadata.format = format; + }; + + /** + * Private: set metadata raw text + * @param {string} raw + */ + this._setMetadataRaw = function (raw) { + metadata.raw = raw; + }; +}; + +var root = this; + +// AMD Loader +if (typeof define === 'function' && define.amd) { + define(function () { + 'use strict'; + return showdown; + }); + +// CommonJS/nodeJS Loader +} else if (typeof module !== 'undefined' && module.exports) { + module.exports = showdown; + +// Regular Browser loader +} else { + root.showdown = showdown; +} +}).call(this); diff --git a/src/render/main.css.txt b/src/render/main.css.txt new file mode 100644 index 0000000..806a7d3 --- /dev/null +++ b/src/render/main.css.txt @@ -0,0 +1,87 @@ +svg { + width: 24px; + height: 24px; +} + +header a { + float: right; +} + +footer { + display: flex; + align-items: center; + + .category, + .format, + .language, + .level { + font-style: normal; + list-style-type: none; + color: white; + border-radius: 1rem; + padding: 0.25rem 0.5rem; + margin: 0.15rem; + font-size: 0.75rem; + background-color: rgb(59 183 143 / 1); + text-wrap: nowrap; + } + + .language, + .level { + background-color: rgb(242 223 13 / 1); + color: black; + } + + div { + flex-grow: 1; + display: flex; + justify-content: end; + align-items: center; + + span { + margin-left: 1rem; + } + } +} + +.talk { + display: flex; + flex-direction: row; + align-items: stretch; + + .abstract { + flex-grow: 1; + } + + .speakers { + margin-left: 1rem; + padding-left: 1rem; + border-left: 1px solid var(--pico-card-border-color); + display: flex; + flex-direction: column; + width: 120px; + + .speaker { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-bottom: 0.5rem; + + img { + width: 96px; + border-radius: 50%; + } + h4, + h5 { + margin-bottom: 0; + font-size: 0.7rem; + text-align: center; + } + } + } +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/src/render/main.js.txt b/src/render/main.js.txt new file mode 100644 index 0000000..ddac090 --- /dev/null +++ b/src/render/main.js.txt @@ -0,0 +1,141 @@ +function slugify(str) { + return str + .toString() + .normalize("NFD") // split an accented letter in the base letter and the acent + .replace(/[\u0300-\u036f]/g, "") // remove all previously split accents + .toLowerCase() + .trim() + .replace(/[^a-z0-9 .]/g, "") // remove all chars not letters, numbers and spaces (to be replaced) + .replace(/\s+/g, "-"); +} + +const converter = new showdown.Converter(); + +const linkIcon = ` + +`; + +const lovesIcon = ` + +`; + +const hatesIcon = ` + +`; + +const ratingIcon = ` + +`; + +document.querySelector("h1").innerText = exportJSON.name; + +const datas = { + categories: exportJSON.categories, + formats: exportJSON.formats, + speakers: [], + companies: [], +}; + +const speakers = {}; + +exportJSON.speakers.forEach((speaker) => { + datas.speakers.push({ + id: speaker.uid, + name: speaker.displayName, + }); + datas.companies.push({ + id: slugify(speaker.company?.trim() || ""), + name: speaker.company?.trim() || "", + }); + speakers[speaker.uid] = speaker; +}); + +const categories = datas.categories.reduce( + (acc, obj) => ({ ...acc, [obj.id]: obj }), + {} +); + +const formats = datas.formats.reduce( + (acc, obj) => ({ ...acc, [obj.id]: obj }), + {} +); + +["categories", "formats", "speakers", "companies"].forEach((key) => { + document.getElementById(key).innerHTML = [ + "", + Object.values( + datas[key].reduce((acc, obj) => ({ ...acc, [obj.id]: obj }), {}) + ) + .sort((a, b) => (a.name < b.name ? -1 : 1)) + .filter(({ name }) => name.trim() !== "") + .map(({ id, name }) => ``) + .join(""), + ].join(""); +}); + +const joliSpeaker = (speaker) => ` +
    + +

    ${speaker.displayName}

    + ${speaker.company ? `
    ${speaker.company}
    ` : ""} +
    +`; + +document.getElementById("talks").innerHTML = exportJSON.talks + .sort((a, b) => (a.rating <= b.rating ? 1 : -1)) + .map( + (talk) => ` +
    +
    + ${ + options.links + ? `${linkIcon}` + : "" + } +

    ${talk.title}

    +
    +
    +
    ${converter.makeHtml(talk.abstract)}
    +
    + ${talk.speakers + .map((speaker) => joliSpeaker(speakers[speaker])) + .join("")} +
    +
    + +
    + ` + ) + .join(""); + +window.filterTalks = () => { + const articles = document.querySelectorAll("article"); + articles.forEach((article) => { + article.classList.remove("hidden"); + }); + + ["categories", "formats", "speakers", "companies"].forEach((key) => { + const choice = document.getElementById(key).value.trim(); + if (choice !== "") + articles.forEach((article) => { + if (article.getAttribute(`data-${key}`).indexOf(` ${choice} `) === -1) + article.classList.add("hidden"); + }); + }); +}; diff --git a/src/types.ts b/src/types.ts index dd4e524..e747956 100644 --- a/src/types.ts +++ b/src/types.ts @@ -50,6 +50,7 @@ export type Options = { withLanguages: boolean; withAddresses: boolean; titlelength: number; - links: string; + render: boolean; + links?: string; export?: string; };