markupeditor 0.9.27 → 0.9.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/markup-editor.js +502 -273
- package/package.json +1 -1
- package/styles/markup.css +9 -8
- package/styles/toolbar.css +7 -7
package/dist/markup-editor.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const sheet$4 = new CSSStyleSheet();sheet$4.replaceSync("/**\n The CSS here was adapted from the ProseMirror example.\n The adaptations mainly consisted of removing styling when it interfered with\n markup.css in some way. These changes were commented-out and moved to the end of\n this file. Top-level Prosemirror styling was brought to the top of the file.\n Styling from search.css in prosemirror-search were added and modified.\n */\n\n .ProseMirror {\n position: relative;\n padding: 4px 8px 4px 8px;\n line-height: 1.2;\n outline: none;\n word-wrap: break-word;\n white-space: pre-wrap;\n white-space: break-spaces;\n font-variant-ligatures: none;\n }\n \n .ProseMirror pre {\n white-space: pre-wrap;\n }\n \n .ProseMirror li {\n position: relative;\n }\n \n .ProseMirror-hideselection *::selection { background: transparent; }\n .ProseMirror-hideselection *::-moz-selection { background: transparent; }\n .ProseMirror-hideselection { caret-color: transparent; }\n \n /* See https://github.com/ProseMirror/prosemirror/issues/1421#issuecomment-1759320191 */\n .ProseMirror [draggable][contenteditable=false] { user-select: text }\n \n .ProseMirror-selectednode {\n outline: 2px solid #8cf;\n }\n \n /* Make sure li selections wrap around markers */\n \n li.ProseMirror-selectednode {\n outline: none;\n }\n \n li.ProseMirror-selectednode:after {\n content: \"\";\n position: absolute;\n left: -32px;\n right: -2px; top: -2px; bottom: -2px;\n border: 2px solid #8cf;\n pointer-events: none;\n }\n \n /* Protect against generic img rules */\n \n img.ProseMirror-separator {\n display: inline !important;\n border: none !important;\n margin: 0 !important;\n }\n .ProseMirror-textblock-dropdown {\n min-width: 3em;\n }\n \n .ProseMirror-icon svg {\n fill: currentColor;\n height: 1em;\n }\n \n .ProseMirror-icon span {\n vertical-align: text-top;\n }\n .ProseMirror-gapcursor {\n display: none;\n pointer-events: none;\n position: absolute;\n }\n \n .ProseMirror-gapcursor:after {\n content: \"\";\n display: block;\n position: absolute;\n top: -2px;\n width: 20px;\n border-top: 1px solid black;\n animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;\n }\n \n @keyframes ProseMirror-cursor-blink {\n to {\n visibility: hidden;\n }\n }\n \n .ProseMirror-focused .ProseMirror-gapcursor {\n display: block;\n }\n \n .ProseMirror-prompt {\n background: white;\n padding: 5px 10px 5px 15px;\n border: 1px solid silver;\n position: fixed;\n border-radius: 3px;\n z-index: 11;\n box-shadow: -.5px 2px 5px rgba(0, 0, 0, .2);\n }\n \n .ProseMirror-prompt h5 {\n margin: 0;\n font-weight: normal;\n font-size: 100%;\n color: #444;\n }\n \n .ProseMirror-prompt input[type=\"text\"],\n .ProseMirror-prompt textarea {\n background: #eee;\n border: none;\n outline: none;\n }\n \n .ProseMirror-prompt input[type=\"text\"] {\n padding: 0 4px;\n }\n \n .ProseMirror-prompt-close {\n position: absolute;\n left: 2px; top: 1px;\n color: #666;\n border: none; background: transparent; padding: 0;\n }\n \n .ProseMirror-prompt-close:after {\n content: \"✕\";\n font-size: 12px;\n }\n \n .ProseMirror-invalid {\n background: #ffc;\n border: 1px solid #cc7;\n border-radius: 4px;\n padding: 5px 10px;\n position: absolute;\n min-width: 10em;\n }\n \n .ProseMirror-prompt-buttons {\n margin-top: 5px;\n /* display: none; */\n }\n \n /*\n \n #editor, .editor {\n border-radius: 4px;\n border: 2px solid rgba(0, 0, 0, 0.2);\n }\n \n .ProseMirror-example-setup-style hr {\n padding: 2px 10px;\n border: none;\n margin: 1em 0;\n }\n \n .ProseMirror-example-setup-style hr:after {\n content: \"\";\n display: block;\n height: 1px;\n background-color: silver;\n line-height: 2px;\n }\n \n .ProseMirror ul, .ProseMirror ol {\n padding-left: 30px;\n }\n \n .ProseMirror blockquote {\n padding-left: 1em;\n border-left: 3px solid #eee;\n margin-left: 0; margin-right: 0;\n }\n \n .ProseMirror-example-setup-style img {\n cursor: default;\n }\n \n .ProseMirror p { margin-bottom: 1em }\n */\n ");
|
|
2
2
|
|
|
3
|
-
const sheet$3 = new CSSStyleSheet();sheet$3.replaceSync("#editor, .editor {\n font-family: system-ui, sans-serif;\n background: white;\n color: black;\n background-clip: padding-box;\n margin: -8px; /* Set so that the .ProseMirror padding starts from edges */\n --padBottom: 0; /* MU.padBottom() sets this value in px based on fullHeight */\n padding-block: 0 var(--padBottom);\n overflow-x: clip;\n overflow-y: scroll;\n height: 100vh;\n padding-right: 12px;\n}\n@media (prefers-color-scheme: dark) {\n #editor, .editor {\n background: black;\n color: white;\n }\n}\n\nbody {\n font-family: system-ui, sans-serif;\n}\n\na {\n color: blue;\n text-decoration: none;\n}\n@media (prefers-color-scheme: dark) {\n a {\n color: #4183c4;\n }\n}\n\na:hover {\n text-decoration: underline;\n}\n\np, pre {\n font-size: 1.0rem;\n}\n\np, ul, ol, dl, table, pre {\n margin: 0 0 15px;\n}\n\nul, ol {\n padding-left: 30px;\n}\n\nh1 {\n font-size: 2.5rem;\n}\n\nh2 {\n font-size: 2.0rem;\n}\n\nh3 {\n font-size: 1.5rem;\n}\n\nh4 {\n font-size: 1.2rem;\n}\n\nh5 {\n font-size: 1.0rem;\n}\n\nh6 {\n font-size: .83rem;\n}\n\nh1, h2, h3, h4, h5, h6 {\n font-weight: bold;\n margin: 0 0 10px 0;\n}\n\nh1 + p, h2 + p, h3 + p {\n margin-top: 10px;\n}\n\ntable {\n table-layout: fixed;\n border-collapse: collapse;\n width: 100%;\n}\n\ntable th, table td {\n padding: 4px;\n}\n\ntable th {\n font-weight: normal; /* The default is bold, but we want to use paragraph styles and formatting */\n}\n\n/* Make the styling compact inside of a table */\ntable p, table h1, table h2, table h3, table h4, table h5, table h6 {\n margin: 0;\n}\n\n/* Table bordering options */\n.bordered-table-none {\n border: none;\n}\n\n.bordered-table-outer, .bordered-table-header, .bordered-table-cell {\n border: 1px solid #DDD;\n}\n\n.bordered-table-header th { /* border th not thead to refresh properly */\n border: 1px solid #DDD;\n}\n\n.bordered-table-cell th, .bordered-table-cell td {\n border: 1px solid #DDD;\n}\n\n/* Default table bordering is same as .bordered-table-cell but is only used when not specified */\ntable:not(.bordered-table-none, .bordered-table-outer, .bordered-table-header, .bordered-table-cell) {\n border: 1px solid #DDD;\n}\n\ntable:not(.bordered-table-none, .bordered-table-outer, .bordered-table-header, .bordered-table-cell) td {\n border: 1px solid #DDD;\n}\n\ntable:not(.bordered-table-none, .bordered-table-outer, .bordered-table-header, .bordered-table-cell) th {\n border: 1px solid #DDD;\n}\n\nli p {\n margin: 0px 0;\n}\n\nli > ul, li > ol {\n margin-bottom: 0;\n}\n\nli > h1, li > h2, li > h3, li > h4, li > h5, li > h6 {\n margin-bottom: 0;\n}\n\nblockquote {\n margin-right: 0px; /* Because nested blockquotes just keep getting narrower */\n}\n\ncode {\n overflow-x: scroll;\n display: block;\n background-color: #F8F8F8;\n border-radius: 3px;\n font-family: 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono', Menlo, Consolas, monospace;\n white-space: pre;\n}\n@media (prefers-color-scheme: dark) {\n code {\n background-color: #808080;\n }\n}\n\np code, h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {\n display: inline;\n}\n\n.resize-container {\n position: relative;\n display: inline-block;\n margin: 0;\n}\n\nimg {\n max-width: 100%;\n height: auto;\n}\n\n/* Provide a slightly darkened or lightened overlay while search is active */\n.searching {\n background-color: rgba(0, 0, 0, 0.10);\n}\n@media (prefers-color-scheme: dark) {\n .searching {\n background: rgba(255, 255, 255, 0.10);\n }\n}\n\n.resize-container img {\n display: block;\n outline: 1px black dashed;\n outline-offset: 4px;\n outline-width: 1px;\n}\n@media (prefers-color-scheme: dark) {\n .resize-container img {\n outline: 1px white dashed;\n }\n}\n\n.resize-handle-nw,\n.resize-handle-ne,\n.resize-handle-sw,\n.resize-handle-se {\n position: absolute;\n display: block;\n width: 6px;\n height: 6px;\n outline: 1px black solid;\n background: white;\n z-index: 999;\n}\n@media (prefers-color-scheme: dark) {\n .resize-handle-nw,\n .resize-handle-ne,\n .resize-handle-sw,\n .resize-handle-se {\n outline: 1px white solid;\n background: black;\n }\n}\n\n/* A transparent child for each resize-handle that expands the clickable area */\n.resize-handle-nw:after,\n.resize-handle-ne:after,\n.resize-handle-sw:after,\n.resize-handle-se:after {\n content: \"\";\n position: absolute;\n left: -5px;\n top: -5px;\n width: 16px;\n height: 16px;\n}\n\n/* The *-resize cursors do not work, at least in MacCatalyst.\n * Still specifying them below. They default to a pointer instead\n */\n.resize-handle-nw {\n cursor: nw-resize;\n top: -8px;\n left: -7px;\n}\n\n.resize-handle-ne {\n cursor: ne-resize;\n top: -8px;\n right: -7px;\n}\n\n.resize-handle-sw {\n cursor: sw-resize;\n bottom: -8px;\n left: -7px;\n}\n\n.resize-handle-se {\n cursor: se-resize;\n bottom: -8px;\n right: -7px;\n}\n\n.placeholder[placeholder]:before {\n content: attr(placeholder);\n position: absolute;\n color: #ccc;\n}\n\n/* Scoped to :has() rather than styling pre unconditionally, since a code_block's\n <pre> should only become a positioning context when it's actually carrying the\n language
|
|
3
|
+
const sheet$3 = new CSSStyleSheet();sheet$3.replaceSync("#editor, .editor {\n font-family: system-ui, sans-serif;\n background: white;\n color: black;\n background-clip: padding-box;\n margin: -8px; /* Set so that the .ProseMirror padding starts from edges */\n --padBottom: 0; /* MU.padBottom() sets this value in px based on fullHeight */\n padding-block: 0 var(--padBottom);\n overflow-x: clip;\n overflow-y: scroll;\n height: 100vh;\n padding-right: 12px;\n}\n@media (prefers-color-scheme: dark) {\n #editor, .editor {\n background: black;\n color: white;\n }\n}\n\nbody {\n font-family: system-ui, sans-serif;\n}\n\na {\n color: blue;\n text-decoration: none;\n}\n@media (prefers-color-scheme: dark) {\n a {\n color: #4183c4;\n }\n}\n\na:hover {\n text-decoration: underline;\n}\n\np, pre {\n font-size: 1.0rem;\n}\n\np, ul, ol, dl, table, pre {\n margin: 0 0 15px;\n}\n\nul, ol {\n padding-left: 30px;\n}\n\nh1 {\n font-size: 2.5rem;\n}\n\nh2 {\n font-size: 2.0rem;\n}\n\nh3 {\n font-size: 1.5rem;\n}\n\nh4 {\n font-size: 1.2rem;\n}\n\nh5 {\n font-size: 1.0rem;\n}\n\nh6 {\n font-size: .83rem;\n}\n\nh1, h2, h3, h4, h5, h6 {\n font-weight: bold;\n margin: 0 0 10px 0;\n}\n\nh1 + p, h2 + p, h3 + p {\n margin-top: 10px;\n}\n\ntable {\n table-layout: fixed;\n border-collapse: collapse;\n width: 100%;\n}\n\ntable th, table td {\n padding: 4px;\n}\n\ntable th {\n font-weight: normal; /* The default is bold, but we want to use paragraph styles and formatting */\n}\n\n/* Make the styling compact inside of a table */\ntable p, table h1, table h2, table h3, table h4, table h5, table h6 {\n margin: 0;\n}\n\n/* Table bordering options */\n.bordered-table-none {\n border: none;\n}\n\n.bordered-table-outer, .bordered-table-header, .bordered-table-cell {\n border: 1px solid #DDD;\n}\n\n.bordered-table-header th { /* border th not thead to refresh properly */\n border: 1px solid #DDD;\n}\n\n.bordered-table-cell th, .bordered-table-cell td {\n border: 1px solid #DDD;\n}\n\n/* Default table bordering is same as .bordered-table-cell but is only used when not specified */\ntable:not(.bordered-table-none, .bordered-table-outer, .bordered-table-header, .bordered-table-cell) {\n border: 1px solid #DDD;\n}\n\ntable:not(.bordered-table-none, .bordered-table-outer, .bordered-table-header, .bordered-table-cell) td {\n border: 1px solid #DDD;\n}\n\ntable:not(.bordered-table-none, .bordered-table-outer, .bordered-table-header, .bordered-table-cell) th {\n border: 1px solid #DDD;\n}\n\nli p {\n margin: 0px 0;\n}\n\nli > ul, li > ol {\n margin-bottom: 0;\n}\n\nli > h1, li > h2, li > h3, li > h4, li > h5, li > h6 {\n margin-bottom: 0;\n}\n\nblockquote {\n margin-right: 0px; /* Because nested blockquotes just keep getting narrower */\n}\n\ncode {\n overflow-x: scroll;\n display: block;\n background-color: #F8F8F8;\n border-radius: 3px;\n font-family: 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono', Menlo, Consolas, monospace;\n white-space: pre;\n}\n@media (prefers-color-scheme: dark) {\n code {\n background-color: #808080;\n }\n}\n\np code, h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {\n display: inline;\n}\n\n.resize-container {\n position: relative;\n display: inline-block;\n margin: 0;\n}\n\nimg {\n max-width: 100%;\n height: auto;\n}\n\n/* Provide a slightly darkened or lightened overlay while search is active */\n.searching {\n background-color: rgba(0, 0, 0, 0.10);\n}\n@media (prefers-color-scheme: dark) {\n .searching {\n background: rgba(255, 255, 255, 0.10);\n }\n}\n\n.resize-container img {\n display: block;\n outline: 1px black dashed;\n outline-offset: 4px;\n outline-width: 1px;\n}\n@media (prefers-color-scheme: dark) {\n .resize-container img {\n outline: 1px white dashed;\n }\n}\n\n.resize-handle-nw,\n.resize-handle-ne,\n.resize-handle-sw,\n.resize-handle-se {\n position: absolute;\n display: block;\n width: 6px;\n height: 6px;\n outline: 1px black solid;\n background: white;\n z-index: 999;\n}\n@media (prefers-color-scheme: dark) {\n .resize-handle-nw,\n .resize-handle-ne,\n .resize-handle-sw,\n .resize-handle-se {\n outline: 1px white solid;\n background: black;\n }\n}\n\n/* A transparent child for each resize-handle that expands the clickable area */\n.resize-handle-nw:after,\n.resize-handle-ne:after,\n.resize-handle-sw:after,\n.resize-handle-se:after {\n content: \"\";\n position: absolute;\n left: -5px;\n top: -5px;\n width: 16px;\n height: 16px;\n}\n\n/* The *-resize cursors do not work, at least in MacCatalyst.\n * Still specifying them below. They default to a pointer instead\n */\n.resize-handle-nw {\n cursor: nw-resize;\n top: -8px;\n left: -7px;\n}\n\n.resize-handle-ne {\n cursor: ne-resize;\n top: -8px;\n right: -7px;\n}\n\n.resize-handle-sw {\n cursor: sw-resize;\n bottom: -8px;\n left: -7px;\n}\n\n.resize-handle-se {\n cursor: se-resize;\n bottom: -8px;\n right: -7px;\n}\n\n.placeholder[placeholder]:before {\n content: attr(placeholder);\n position: absolute;\n color: #ccc;\n}\n\n/* Scoped to :has() rather than styling pre unconditionally, since a code_block's\n <pre> should only become a positioning context when it's actually carrying the\n language tab (highlightCode on, block selected) — not for every code block. */\npre:has(.Markup-code-language-tab) {\n position: relative;\n}\n\n.Markup-code-language-tab {\n position: absolute;\n bottom: 100%;\n right: 0;\n font-size: 0.75rem;\n padding: 2px 6px;\n border: none;\n border-radius: 4px 4px 0 0;\n cursor: pointer;\n opacity: 0.6;\n color: white;\n background: var(--Markup-accent-color, blue);\n}\n\n.Markup-code-language-tab:hover {\n opacity: 0.9;\n}\n\n/* Applied (setup/index.js, CodeView.hasRoomAbove) when the code_block is too close to\n the top of the view for the tab to fit above it — attach to the bottom instead. */\n.Markup-code-language-tab-below {\n bottom: auto;\n top: 100%;\n border-radius: 0 0 4px 4px;\n}\n\n/* Matches .Markup-menuitem-active's selected-button color scheme. */\n@media (prefers-color-scheme: dark) {\n .Markup-code-language-tab {\n background: var(--Markup-accent-color, lightblue);\n color: black;\n }\n}\n\n/* Classes set by prosemirror-search module, modified for MarkupEditor */\n/* Note the dark and light mode are the same */\n\n.ProseMirror-search-match {\n background-color: yellow;\n color: black;\n}\n\n.ProseMirror-active-search-match {\n background-color: orange;\n color: black;\n outline: 1px orangered solid;\n z-index: 2;\n}");
|
|
4
4
|
|
|
5
|
-
const sheet$2 = new CSSStyleSheet();sheet$2.replaceSync("/* Spacing at the top */\n/* Note that toolbar-overlay below is also set to these values */\n\n.Markup-searchbar-showing {\n height: 38px;\n top: 76px;\n}\n\n/* The wrapper lets us automatically embed a toolbar and scroll under it */\n.Markup-toolbar-wrapper {\n margin-right: -12px; /* Prevent side scroll even when menu fits */\n height: inherit;\n overflow-y: scroll;\n position: relative; \n}\n\n/* We add Markup-prompt-showing to the wrapper to prevent scroll, and remove it when done */\n.Markup-prompt-showing {\n overflow-y: hidden;\n}\n\n/* Z-indexes in one place */\n\n.body-content { \n z-index: 1; \n}\n\n.Markup-prompt-overlay { \n z-index: 2; \n}\n\n.Markup-prompt, .Markup-selection {\n z-index: 3;\n}\n\n.Markup-searchbar {\n z-index: 4;\n}\n\n.Markup-toolbar, .Markup-toolbar-more {\n z-index: 5;\n}\n\n.Markup-toolbar-overlay { \n z-index: 6; \n}\n\n.Markup-menu-dropdown-menu {\n z-index: 7;\n}\n\n/* Toolbar, menu item, and dropdown styling */\n\n.Markup-toolbar {\n display: inline-flex;\n position: sticky;\n overflow: visible;\n width: 100%;\n font-size: var(--Markup-button-font-size, 24px);\n vertical-align: middle;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n top: 0;\n max-height: calc(var(--Markup-button-size, 28px) + 10px);\n padding: 2px 8px;\n color: var(--Markup-accent-color, blue);\n background: var(--Markup-toolbar-bg, rgba(250, 249, 246, 0.95));\n border-bottom: 1px solid var(--Markup-border-color, lightgray);\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-toolbar {\n color: var(--Markup-accent-color, lightblue);\n background: var(--Markup-toolbar-bg, rgba(40, 40, 43, 0.9));\n border-bottom: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n.Markup-toolbar-hidden {\n display: none;\n}\n\n.Markup-menuitem {\n display: inline-block;\n flex-shrink: 0; /* Otherwise, the drop-downs with icons shrink */\n overflow-y: visible;\n vertical-align: middle;\n min-width: var(--Markup-button-size, 28px);\n height: var(--Markup-button-size, 28px);\n cursor: pointer;\n margin-right: 4px;\n border-radius: 4px;\n color: var(--Markup-accent-color, blue);\n border: 1px solid var(--Markup-accent-color, blue);\n background: var(--Markup-button-bg, white);\n fill: var(--Markup-accent-color, blue);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuitem {\n color: var(--Markup-accent-color, lightblue);\n border: 1px solid var(--Markup-accent-color, lightblue);\n /* border: 1px solid #4183c4; */\n background: var(--Markup-button-bg, black);\n fill: var(--Markup-accent-color, lightblue);\n }\n}\n\n.Markup-menuitem-active {\n fill: white;\n color: white;\n background: var(--Markup-accent-color, blue);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuitem-active {\n fill: black;\n color: black;\n background: var(--Markup-accent-color, lightblue);\n }\n}\n\n.Markup-menuitem-disabled {\n cursor: default;\n opacity: .3;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuitem-disabled {\n opacity: .6;\n }\n}\n\n.Markup-icon {\n display: inline-block;\n width: var(--Markup-button-size, 28px);\n height: var(--Markup-button-size, 28px);\n border: 0;\n}\n\n.Markup-icon span {\n vertical-align: middle;\n}\n\n.Markup-icon svg {\n width: var(--Markup-button-font-size, 24px);\n height: var(--Markup-button-font-size, 24px);\n padding: 2px;\n border: 0;\n fill: inherit;\n}\n\n.Markup-menuseparator {\n display: inline-block;\n vertical-align: middle;\n height: var(--Markup-button-size, 28px);\n border-right: 1px solid var(--Markup-border-color, lightgray);\n margin-right: 4px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuseparator {\n border-right: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n.Markup-menu-disabled .Markup-icon {\n cursor: default;\n}\n\n.Markup-menu-dropdown, .Markup-menu-dropdown-menu {\n background: inherit;\n text-align: left;\n white-space: nowrap;\n}\n\n.Markup-menu-dropdown span {\n vertical-align: middle;\n}\n\n.Markup-menu-dropdown-icon span {\n vertical-align: middle;\n}\n\n.Markup-menu-dropdown-wrap {\n display: flex;\n justify-content: space-between;\n padding: 0 4px;\n height: inherit;\n border-radius: 4px;\n background: inherit;\n}\n\n.Markup-menu-dropdown-icon-wrap {\n display: flex;\n justify-content: space-between;\n padding-right: 4px;\n width: 1.8em;\n height: inherit;\n border-radius: 4px;\n background: inherit;\n}\n\n.Markup-menu-dropdown-icon-wrap-noindicator {\n display: inline-flex;\n padding-right: 4px;\n width: 1em;\n height: inherit;\n border-radius: 4px;\n background: inherit;\n}\n\n/* For the paragraph style dropdown with a label, make the font smaller */\n.Markup-menu-dropdown {\n display: flex;\n justify-content: space-between;\n align-items: center;\n box-sizing: border-box;\n font-size: 0.8em;\n width: inherit;\n height: inherit;\n background: inherit;\n position: absolute;\n}\n\n/* But for the indicator, bump size up to match the icon-style dropdown */\n.Markup-menu-dropdown .Markup-menu-dropdown-indicator {\n font-size: 1.25em;\n}\n\n.Markup-menu-dropdown-icon {\n display: inline-flex;\n justify-content: space-between;\n font-size: inherit;\n width: inherit;\n cursor: pointer;\n position: absolute;\n}\n\n.Markup-menu-dropdown-indicator {\n opacity: .6;\n}\n\n.Markup-tooltip .Markup-menu {\n width: -webkit-fit-content;\n width: fit-content;\n white-space: pre;\n}\n\n.Markup-menu-dropdown-menu, .Markup-menu-submenu {\n position: absolute;\n background: inherit;\n padding: 2px;\n background: inherit;\n border: 1px solid var(--Markup-border-color, gray);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-menu, .Markup-menu-submenu {\n border: 1px solid var(--Markup-border-color, lightgray);\n }\n}\n\n.Markup-menu-dropdown-menu {\n margin-top: calc(1em + 6px);\n min-width: 4em;\n}\n\n.Markup-menu-dropdown-item {\n cursor: pointer;\n padding: 2px 8px 2px 4px;\n}\n\n.Markup-menu-dropdown-separator {\n border-top: 1px solid var(--Markup-border-color, lightgray);\n margin: 4px 0;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-separator {\n border-top: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n/* Used to overlfow and ellipsis-truncate text in Dropdown menu items */\n.Markup-menuitem-clipped {\n white-space: nowrap; /* Required for text-overflow */\n overflow-x: hidden; /* Required for text-overflow */\n max-width: 30em;\n text-overflow: ellipsis;\n}\n\n.Markup-menu-dropdown-item:hover, .Markup-menu-submenu-wrap:hover {\n background: var(--Markup-hover-bg, #f2f2f2);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-item:hover, .Markup-menu-submenu-wrap:hover {\n background: var(--Markup-hover-bg, rgb(80, 80, 80));\n }\n}\n\n.Markup-menu-dropdown-item p, \n.Markup-menu-dropdown-item h1, \n.Markup-menu-dropdown-item h2, \n.Markup-menu-dropdown-item h3, \n.Markup-menu-dropdown-item h4, \n.Markup-menu-dropdown-item h5, \n.Markup-menu-dropdown-item h6, \n.Markup-menu-dropdown-item pre {\n padding: 0;\n margin: 0;\n min-height: 24px;\n}\n\n.Markup-stylelabel {\n display: flex;\n justify-content: space-between;\n align-items: center;\n white-space: pre;\n width: 100%;\n}\n\n.Markup-stylelabel-keymap {\n display: flex;\n justify-content: flex-end;\n font-size: 1.0rem;\n font-weight: normal;\n color: gray;\n}\n\n.Markup-menu-submenu-wrap:hover .Markup-menu-submenu, .Markup-menu-submenu-wrap-active .Markup-menu-submenu {\n display: block;\n}\n\n.Markup-menu-submenu-wrap {\n position: relative;\n margin-right: -4px;\n background: inherit;\n}\n\n.Markup-menu-submenu {\n display: none;\n min-width: 4em;\n left: 100%;\n top: -5px;\n max-height: 80vh;\n overflow-y: auto;\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, white);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-submenu {\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, black);\n }\n}\n\n.Markup-menu-submenu-label:after {\n content: \"\";\n border-top: 4px solid transparent;\n border-bottom: 4px solid transparent;\n border-left: 4px solid currentColor;\n opacity: .6;\n position: absolute;\n right: 4px;\n top: calc(50% - 4px);\n}\n\n.Markup-selection {\n position: absolute;\n border: 1px solid var(--Markup-accent-color, blue);\n background: transparent;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-selection {\n border: 1px solid var(--Markup-accent-color, lightblue);\n }\n}\n\n/* Toolbar-more styling */\n\n.Markup-toolbar-more {\n display: inline-flex;\n position: sticky;\n overflow: visible;\n width: 100%;\n font-size: var(--Markup-button-font-size, 24px);\n vertical-align: middle;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n top: calc(var(--Markup-button-size, 28px) + 7px);\n max-height: calc(var(--Markup-button-size, 28px) + 10px);\n padding: 2px 8px;\n color: var(--Markup-accent-color, blue);\n background: var(--Markup-toolbar-bg, rgba(250, 249, 246, 0.95));\n border-bottom: 1px solid var(--Markup-border-color, lightgray);\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-toolbar-more {\n color: var(--Markup-accent-color, lightblue);\n background: var(--Markup-toolbar-bg, rgba(40, 40, 43, 0.9));\n border-bottom: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n/* Searchbar styling */\n\n.Markup-searchbar {\n display: inline-block;\n font-size: var(--Markup-button-font-size, 24px);\n vertical-align: middle;\n position: sticky;\n top: calc(var(--Markup-button-size, 28px) + 7px);\n width: 100%;\n line-height: 30px;\n height: 37px;\n color: var(--Markup-accent-color, blue);\n background: var(--Markup-toolbar-bg, rgba(250, 249, 246, 0.95));\n border-bottom: 1px solid var(--Markup-border-color, lightgray);\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n overflow: hidden;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-searchbar {\n color: var(--Markup-accent-color, lightblue);\n background: var(--Markup-toolbar-bg, rgba(40, 40, 43, 0.9));\n border-bottom: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n.Markup-searchbar input {\n appearance: none; /* Otherwise, in Safari/WebKit, the height is small and fixed */\n position: relative;\n font-size: 18px;\n line-height: 30px;\n height: 30px;\n width: calc(100% - 128px);\n margin: 0 8px;\n padding: 0 4px;\n outline: none;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n border: 1px solid lightgray;\n border-radius: 6px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-searchbar input {\n color: rgb(250, 249, 246);\n background: rgb(40, 40, 43);\n border: 1px solid gray;\n }\n}\n\n.Markup-searchbar .Markup-searchbar-status {\n position: absolute;\n display: flex;\n justify-content: flex-end;\n align-items: center;\n white-space: nowrap;\n font-size: 12px;\n overflow-x: visible;\n height: 28px;\n top: 5px;\n left: calc(100% - 13em);\n width: 1px;\n color: gray;\n user-select: none;\n}\n\n/* Dialog/prompt styling for insert/edit actions */\n\n.Markup-prompt-overlay {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground-color: rgba(0, 0, 0, 0.2);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt-overlay {\n background-color: rgba(255, 255, 255, 0.2);\n }\n}\n\n.Markup-toolbar-overlay {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tbackground-color: rgba(0, 0, 0, 0.1);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-toolbar-overlay {\n background-color: rgba(255, 255, 255, 0.1);\n }\n}\n\n.Markup-toolbar-overlay.Markup-searchbar-hidden {\n height: 38px;\n}\n\n.Markup-toolbar-overlay.Markup-searchbar-showing {\n height: 76px;\n}\n\n.Markup-prompt {\n margin: 0;\n font-size: 18px;\n background: white;\n padding: 8px;\n border: 1px solid silver;\n position: absolute;\n border-radius: 3px;\n box-shadow: -.5px 2px 5px rgba(0, 0, 0, 0.2);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt {\n background: black;\n box-shadow: -.5px 2px 5px rgba(255, 255, 255, 0.8);\n }\n}\n\n.Markup-prompt-link {\n height: 96px;\n width: 300px;\n}\n\n.Markup-prompt-image {\n height: 130px;\n width: 300px;\n}\n\n.Markup-prompt-language {\n height: 96px;\n width: 300px;\n}\n\n.Markup-prompt img {\n display: inline-block;\n vertical-align: middle;\n min-width: 28px;\n height: 28px;\n margin-right: 4px;\n}\n\n.Markup-prompt p {\n margin: 0 0 4px 0;\n font-weight: normal;\n color: black;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt p {\n color: white;\n }\n}\n\n.Markup-prompt input[type=\"text\"] {\n font-size: 100%;\n line-height: 28px;\n margin-top: 2px;\n padding: 1px 4px;\n width: 100%;\n appearance: none;\n background: #eee;\n outline: none;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n border: 1px solid lightgray;\n border-radius: 6px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt input[type=\"text\"] {\n color: rgb(250, 249, 246);\n background: rgb(40, 40, 43);\n border: 1px solid gray;\n }\n}\n\n.Markup-prompt input.invalid {\n color: red;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt input.invalid {\n color: pink;\n }\n}\n\n.Markup-prompt-buttons {\n display: flex;\n vertical-align: middle;\n justify-content: space-between;\n justify-items: center;\n line-height: 28px;\n height: 28px;\n margin-top: 8px;\n margin-bottom: 8px;\n}\n\n.Markup-prompt-buttongroup {\n flex-shrink: 0;\n}\n\n.Markup-prompt-buttons img {\n aspect-ratio: auto;\n height: auto;\n object-fit: contain;\n}\n\n.Markup-prompt-buttons .Markup-menuitem {\n display: inline-flex;\n padding-right: 4px;\n padding-left: 4px;\n}\n\n/* The buttongroup contains OK and Cancel menuitems on the right */\n.Markup-prompt-buttongroup .Markup-menuitem {\n margin-right: 0;\n margin-left: 4px;\n}\n\n/* .Markup-menu-tablesizer is a specialized submenu */\n.Markup-menu-tablesizer {\n display: none;\n grid-template-columns: repeat(4, 1fr);\n grid-auto-rows: 18px;\n row-gap: 1px;\n column-gap: 1px;\n padding: 0;\n left: 100%;\n top: -5px;\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, white);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-tablesizer {\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, black);\n }\n}\n\n.Markup-menu-submenu-wrap:hover .Markup-menu-tablesizer, .Markup-menu-submenu-wrap-active .Markup-menu-tablesizer {\n display: grid;\n}\n\n.Markup-menu-dropdown-menu, .Markup-menu-tablesizer {\n position: absolute;\n background: inherit;\n padding: 2px;\n background: inherit;\n border: 1px solid var(--Markup-border-color, gray);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-menu, .Markup-menu-submenu {\n border: 1px solid var(--Markup-border-color, lightgray);\n }\n}\n\n.Markup-menu-tablesizer .Markup-menu-dropdown-item {\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n border: 1px solid var(--Markup-accent-color, blue);\n width: 18px;\n height: 18px;\n padding: 0;\n font-size: 13px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-tablesizer .Markup-menu-dropdown-item {\n border: 1px solid var(--Markup-accent-color, lightblue);\n }\n}\n\n.Markup-menu-tablesizer .Markup-menuitem-active {\n height: 13px;\n padding-top: 3px;\n fill: black;\n color: black;\n background: var(--Markup-accent-color, blue);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-tablesizer .Markup-menuitem-active {\n fill: black;\n color: black;\n background: var(--Markup-accent-color, lightblue);\n }\n}");
|
|
5
|
+
const sheet$2 = new CSSStyleSheet();sheet$2.replaceSync("/* Spacing at the top */\n/* Note that toolbar-overlay below is also set to these values */\n\n.Markup-searchbar-showing {\n height: 38px;\n top: 76px;\n}\n\n/* The wrapper lets us automatically embed a toolbar and scroll under it */\n.Markup-toolbar-wrapper {\n margin-right: -12px; /* Prevent side scroll even when menu fits */\n height: inherit;\n overflow-y: scroll;\n position: relative; \n}\n\n/* We add Markup-prompt-showing to the wrapper to prevent scroll, and remove it when done */\n.Markup-prompt-showing {\n overflow-y: hidden;\n}\n\n/* Z-indexes in one place */\n\n.body-content { \n z-index: 1; \n}\n\n.Markup-prompt-overlay { \n z-index: 2; \n}\n\n.Markup-prompt, .Markup-selection {\n z-index: 3;\n}\n\n.Markup-searchbar {\n z-index: 4;\n}\n\n.Markup-toolbar, .Markup-toolbar-more {\n z-index: 5;\n}\n\n.Markup-toolbar-overlay { \n z-index: 6; \n}\n\n.Markup-menu-dropdown-menu {\n z-index: 7;\n}\n\n/* Toolbar, menu item, and dropdown styling */\n\n.Markup-toolbar {\n display: inline-flex;\n position: sticky;\n overflow: visible;\n width: 100%;\n font-size: var(--Markup-button-font-size, 24px);\n vertical-align: middle;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n top: 0;\n max-height: calc(var(--Markup-button-size, 28px) + 10px);\n padding: 2px 8px;\n color: var(--Markup-accent-color, blue);\n background: var(--Markup-toolbar-bg, rgba(250, 249, 246, 0.95));\n border-bottom: 1px solid var(--Markup-border-color, lightgray);\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-toolbar {\n color: var(--Markup-accent-color, lightblue);\n background: var(--Markup-toolbar-bg, rgba(40, 40, 43, 0.9));\n border-bottom: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n.Markup-toolbar-hidden {\n display: none;\n}\n\n.Markup-menuitem {\n display: inline-block;\n flex-shrink: 0; /* Otherwise, the drop-downs with icons shrink */\n overflow-y: visible;\n vertical-align: middle;\n min-width: var(--Markup-button-size, 28px);\n height: var(--Markup-button-size, 28px);\n cursor: pointer;\n margin-right: 4px;\n border-radius: 4px;\n color: var(--Markup-accent-color, blue);\n border: 1px solid var(--Markup-accent-color, blue);\n background: var(--Markup-button-bg, white);\n fill: var(--Markup-accent-color, blue);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuitem {\n color: var(--Markup-accent-color, lightblue);\n border: 1px solid var(--Markup-accent-color, lightblue);\n /* border: 1px solid #4183c4; */\n background: var(--Markup-button-bg, black);\n fill: var(--Markup-accent-color, lightblue);\n }\n}\n\n.Markup-menuitem-active {\n fill: white;\n color: white;\n background: var(--Markup-accent-color, blue);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuitem-active {\n fill: black;\n color: black;\n background: var(--Markup-accent-color, lightblue);\n }\n}\n\n.Markup-menuitem-disabled {\n cursor: default;\n opacity: .3;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuitem-disabled {\n opacity: .6;\n }\n}\n\n.Markup-icon {\n display: inline-block;\n width: var(--Markup-button-size, 28px);\n height: var(--Markup-button-size, 28px);\n border: 0;\n}\n\n.Markup-icon span {\n vertical-align: middle;\n}\n\n.Markup-icon svg {\n width: var(--Markup-button-font-size, 24px);\n height: var(--Markup-button-font-size, 24px);\n padding: 2px;\n border: 0;\n fill: inherit;\n}\n\n.Markup-menuseparator {\n display: inline-block;\n vertical-align: middle;\n height: var(--Markup-button-size, 28px);\n border-right: 1px solid var(--Markup-border-color, lightgray);\n margin-right: 4px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menuseparator {\n border-right: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n.Markup-menu-disabled .Markup-icon {\n cursor: default;\n}\n\n.Markup-menu-dropdown, .Markup-menu-dropdown-menu {\n background: inherit;\n text-align: left;\n white-space: nowrap;\n}\n\n.Markup-menu-dropdown span {\n vertical-align: middle;\n}\n\n.Markup-menu-dropdown-icon span {\n vertical-align: middle;\n}\n\n.Markup-menu-dropdown-wrap {\n display: flex;\n justify-content: space-between;\n padding: 0 4px;\n height: inherit;\n border-radius: 4px;\n background: inherit;\n}\n\n.Markup-menu-dropdown-icon-wrap {\n display: flex;\n justify-content: space-between;\n padding-right: 4px;\n width: 1.8em;\n height: inherit;\n border-radius: 4px;\n background: inherit;\n}\n\n.Markup-menu-dropdown-icon-wrap-noindicator {\n display: inline-flex;\n padding-right: 4px;\n width: 1em;\n height: inherit;\n border-radius: 4px;\n background: inherit;\n}\n\n/* For the paragraph style dropdown with a label, make the font smaller */\n.Markup-menu-dropdown {\n display: flex;\n justify-content: space-between;\n align-items: center;\n box-sizing: border-box;\n font-size: 0.8em;\n width: inherit;\n height: inherit;\n background: inherit;\n position: absolute;\n}\n\n/* But for the indicator, bump size up to match the icon-style dropdown */\n.Markup-menu-dropdown .Markup-menu-dropdown-indicator {\n font-size: 1.25em;\n}\n\n.Markup-menu-dropdown-icon {\n display: inline-flex;\n justify-content: space-between;\n font-size: inherit;\n width: inherit;\n cursor: pointer;\n position: absolute;\n}\n\n.Markup-menu-dropdown-indicator {\n opacity: .6;\n}\n\n.Markup-tooltip .Markup-menu {\n width: -webkit-fit-content;\n width: fit-content;\n white-space: pre;\n}\n\n.Markup-menu-dropdown-menu, .Markup-menu-submenu {\n position: absolute;\n background: inherit;\n padding: 2px;\n background: inherit;\n border: 1px solid var(--Markup-border-color, gray);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-menu, .Markup-menu-submenu {\n border: 1px solid var(--Markup-border-color, lightgray);\n }\n}\n\n.Markup-menu-dropdown-menu {\n margin-top: calc(1em + 6px);\n min-width: 4em;\n}\n\n.Markup-menu-dropdown-item {\n cursor: pointer;\n padding: 2px 8px 2px 4px;\n}\n\n.Markup-menu-dropdown-separator {\n border-top: 1px solid var(--Markup-border-color, lightgray);\n margin: 4px 0;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-separator {\n border-top: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n/* Used to overlfow and ellipsis-truncate text in Dropdown menu items */\n.Markup-menuitem-clipped {\n white-space: nowrap; /* Required for text-overflow */\n overflow-x: hidden; /* Required for text-overflow */\n max-width: 30em;\n text-overflow: ellipsis;\n}\n\n.Markup-menu-dropdown-item:hover, .Markup-menu-submenu-wrap:hover {\n background: var(--Markup-hover-bg, #f2f2f2);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-item:hover, .Markup-menu-submenu-wrap:hover {\n background: var(--Markup-hover-bg, rgb(80, 80, 80));\n }\n}\n\n.Markup-menu-dropdown-item p, \n.Markup-menu-dropdown-item h1, \n.Markup-menu-dropdown-item h2, \n.Markup-menu-dropdown-item h3, \n.Markup-menu-dropdown-item h4, \n.Markup-menu-dropdown-item h5, \n.Markup-menu-dropdown-item h6, \n.Markup-menu-dropdown-item pre {\n padding: 0;\n margin: 0;\n min-height: 24px;\n}\n\n.Markup-stylelabel {\n display: flex;\n justify-content: space-between;\n align-items: center;\n white-space: pre;\n width: 100%;\n}\n\n.Markup-stylelabel-keymap {\n display: flex;\n justify-content: flex-end;\n font-size: 1.0rem;\n font-weight: normal;\n color: gray;\n}\n\n.Markup-menu-submenu-wrap:hover .Markup-menu-submenu, .Markup-menu-submenu-wrap-active .Markup-menu-submenu {\n display: block;\n}\n\n.Markup-menu-submenu-wrap {\n position: relative;\n margin-right: -4px;\n background: inherit;\n}\n\n.Markup-menu-submenu {\n display: none;\n min-width: 4em;\n left: 100%;\n top: -5px;\n max-height: 80vh;\n overflow-y: auto;\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, white);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-submenu {\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, black);\n }\n}\n\n.Markup-menu-submenu-label:after {\n content: \"\";\n border-top: 4px solid transparent;\n border-bottom: 4px solid transparent;\n border-left: 4px solid currentColor;\n opacity: .6;\n position: absolute;\n right: 4px;\n top: calc(50% - 4px);\n}\n\n.Markup-selection {\n position: absolute;\n border: 1px solid var(--Markup-accent-color, blue);\n background: transparent;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-selection {\n border: 1px solid var(--Markup-accent-color, lightblue);\n }\n}\n\n/* Toolbar-more styling */\n\n.Markup-toolbar-more {\n display: inline-flex;\n position: sticky;\n overflow: visible;\n width: 100%;\n font-size: var(--Markup-button-font-size, 24px);\n vertical-align: middle;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n top: calc(var(--Markup-button-size, 28px) + 7px);\n max-height: calc(var(--Markup-button-size, 28px) + 10px);\n padding: 2px 8px;\n color: var(--Markup-accent-color, blue);\n background: var(--Markup-toolbar-bg, rgba(250, 249, 246, 0.95));\n border-bottom: 1px solid var(--Markup-border-color, lightgray);\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-toolbar-more {\n color: var(--Markup-accent-color, lightblue);\n background: var(--Markup-toolbar-bg, rgba(40, 40, 43, 0.9));\n border-bottom: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n/* Searchbar styling */\n\n.Markup-searchbar {\n display: inline-block;\n font-size: var(--Markup-button-font-size, 24px);\n vertical-align: middle;\n position: sticky;\n top: calc(var(--Markup-button-size, 28px) + 7px);\n width: 100%;\n line-height: 30px;\n height: 37px;\n color: var(--Markup-accent-color, blue);\n background: var(--Markup-toolbar-bg, rgba(250, 249, 246, 0.95));\n border-bottom: 1px solid var(--Markup-border-color, lightgray);\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n overflow: hidden;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-searchbar {\n color: var(--Markup-accent-color, lightblue);\n background: var(--Markup-toolbar-bg, rgba(40, 40, 43, 0.9));\n border-bottom: 1px solid var(--Markup-border-color, gray);\n }\n}\n\n.Markup-searchbar input {\n appearance: none; /* Otherwise, in Safari/WebKit, the height is small and fixed */\n position: relative;\n font-size: 18px;\n line-height: 30px;\n height: 30px;\n width: calc(100% - 128px);\n margin: 0 8px;\n padding: 0 4px;\n outline: none;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n border: 1px solid lightgray;\n border-radius: 6px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-searchbar input {\n color: rgb(250, 249, 246);\n background: rgb(40, 40, 43);\n border: 1px solid gray;\n }\n}\n\n.Markup-searchbar .Markup-searchbar-status {\n position: absolute;\n display: flex;\n justify-content: flex-end;\n align-items: center;\n white-space: nowrap;\n font-size: 12px;\n overflow-x: visible;\n height: 28px;\n top: 5px;\n left: calc(100% - 13em);\n width: 1px;\n color: gray;\n user-select: none;\n}\n\n/* Dialog/prompt styling for insert/edit actions */\n\n.Markup-prompt-overlay {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground-color: rgba(0, 0, 0, 0.2);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt-overlay {\n background-color: rgba(255, 255, 255, 0.2);\n }\n}\n\n.Markup-toolbar-overlay {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tbackground-color: rgba(0, 0, 0, 0.1);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-toolbar-overlay {\n background-color: rgba(255, 255, 255, 0.1);\n }\n}\n\n.Markup-toolbar-overlay.Markup-searchbar-hidden {\n height: 38px;\n}\n\n.Markup-toolbar-overlay.Markup-searchbar-showing {\n height: 76px;\n}\n\n.Markup-prompt {\n margin: 0;\n font-size: 18px;\n background: white;\n padding: 8px;\n border: 1px solid silver;\n position: absolute;\n border-radius: 3px;\n box-shadow: -.5px 2px 5px rgba(0, 0, 0, 0.2);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt {\n background: black;\n box-shadow: -.5px 2px 5px rgba(255, 255, 255, 0.8);\n }\n}\n\n.Markup-prompt-link {\n height: calc(68px + var(--Markup-button-size, 28px)); /* 96 px by default */\n width: 300px;\n}\n\n.Markup-prompt-image {\n height: calc(102px + var(--Markup-button-size, 28px)); /* 130 px by default */\n width: 300px;\n}\n\n.Markup-prompt-language {\n height: calc(68px + var(--Markup-button-size, 28px)); /* 96 px by default */\n width: 300px;\n}\n\n.Markup-prompt img {\n display: inline-block;\n vertical-align: middle;\n min-width: var(--Markup-button-size, 28px);\n height: var(--Markup-button-size, 28px);\n margin-right: 4px;\n}\n\n.Markup-prompt p {\n margin: 0 0 4px 0;\n font-weight: normal;\n color: black;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt p {\n color: white;\n }\n}\n\n.Markup-prompt input[type=\"text\"] {\n font-size: 100%;\n line-height: 28px;\n margin-top: 2px;\n padding: 1px 4px;\n width: 100%;\n appearance: none;\n background: #eee;\n outline: none;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n border: 1px solid lightgray;\n border-radius: 6px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt input[type=\"text\"] {\n color: rgb(250, 249, 246);\n background: rgb(40, 40, 43);\n border: 1px solid gray;\n }\n}\n\n.Markup-prompt input.invalid {\n color: red;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-prompt input.invalid {\n color: pink;\n }\n}\n\n.Markup-prompt-buttons {\n display: flex;\n vertical-align: middle;\n justify-content: space-between;\n justify-items: center;\n line-height: var(--Markup-button-size, 28px);\n height: var(--Markup-button-size, 28px);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n\n.Markup-prompt-buttongroup {\n flex-shrink: 0;\n}\n\n.Markup-prompt-buttons img {\n aspect-ratio: auto;\n height: auto;\n object-fit: contain;\n}\n\n.Markup-prompt-buttons .Markup-menuitem {\n display: inline-flex;\n padding-right: 4px;\n padding-left: 4px;\n}\n\n/* The buttongroup contains OK and Cancel menuitems on the right */\n.Markup-prompt-buttongroup .Markup-menuitem {\n margin-right: 0;\n margin-left: 4px;\n}\n\n/* .Markup-menu-tablesizer is a specialized submenu */\n.Markup-menu-tablesizer {\n display: none;\n grid-template-columns: repeat(4, 1fr);\n grid-auto-rows: 18px;\n row-gap: 1px;\n column-gap: 1px;\n padding: 0;\n left: 100%;\n top: -5px;\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, white);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-tablesizer {\n /* background cannot be inherited because of hover highlighting in dropdown */\n background: var(--Markup-button-bg, black);\n }\n}\n\n.Markup-menu-submenu-wrap:hover .Markup-menu-tablesizer, .Markup-menu-submenu-wrap-active .Markup-menu-tablesizer {\n display: grid;\n}\n\n.Markup-menu-dropdown-menu, .Markup-menu-tablesizer {\n position: absolute;\n background: inherit;\n padding: 2px;\n background: inherit;\n border: 1px solid var(--Markup-border-color, gray);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-dropdown-menu, .Markup-menu-submenu {\n border: 1px solid var(--Markup-border-color, lightgray);\n }\n}\n\n.Markup-menu-tablesizer .Markup-menu-dropdown-item {\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n border: 1px solid var(--Markup-accent-color, blue);\n width: 18px;\n height: 18px;\n padding: 0;\n font-size: 13px;\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-tablesizer .Markup-menu-dropdown-item {\n border: 1px solid var(--Markup-accent-color, lightblue);\n }\n}\n\n.Markup-menu-tablesizer .Markup-menuitem-active {\n height: 13px;\n padding-top: 3px;\n fill: black;\n color: black;\n background: var(--Markup-accent-color, blue);\n}\n@media (prefers-color-scheme: dark) {\n .Markup-menu-tablesizer .Markup-menuitem-active {\n fill: black;\n color: black;\n background: var(--Markup-accent-color, lightblue);\n }\n}");
|
|
6
6
|
|
|
7
7
|
const sheet$1 = new CSSStyleSheet();sheet$1.replaceSync("pre code.hljs {\n display: block;\n overflow-x: auto;\n padding: 1em\n}\ncode.hljs {\n padding: 3px 5px\n}\n/*!\n Theme: GitHub\n Description: Light theme as seen on github.com\n Author: github.com\n Maintainer: @Hirse\n Updated: 2021-05-15\n\n Outdated base version: https://github.com/primer/github-syntax-light\n Current colors taken from GitHub's CSS\n*/\n.hljs {\n color: #24292e;\n background: #ffffff\n}\n.hljs-doctag,\n.hljs-keyword,\n.hljs-meta .hljs-keyword,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-type,\n.hljs-variable.language_ {\n /* prettylights-syntax-keyword */\n color: #d73a49\n}\n.hljs-title,\n.hljs-title.class_,\n.hljs-title.class_.inherited__,\n.hljs-title.function_ {\n /* prettylights-syntax-entity */\n color: #6f42c1\n}\n.hljs-attr,\n.hljs-attribute,\n.hljs-literal,\n.hljs-meta,\n.hljs-number,\n.hljs-operator,\n.hljs-variable,\n.hljs-selector-attr,\n.hljs-selector-class,\n.hljs-selector-id {\n /* prettylights-syntax-constant */\n color: #005cc5\n}\n.hljs-regexp,\n.hljs-string,\n.hljs-meta .hljs-string {\n /* prettylights-syntax-string */\n color: #032f62\n}\n.hljs-built_in,\n.hljs-symbol {\n /* prettylights-syntax-variable */\n color: #e36209\n}\n.hljs-comment,\n.hljs-code,\n.hljs-formula {\n /* prettylights-syntax-comment */\n color: #6a737d\n}\n.hljs-name,\n.hljs-quote,\n.hljs-selector-tag,\n.hljs-selector-pseudo {\n /* prettylights-syntax-entity-tag */\n color: #22863a\n}\n.hljs-subst {\n /* prettylights-syntax-storage-modifier-import */\n color: #24292e\n}\n.hljs-section {\n /* prettylights-syntax-markup-heading */\n color: #005cc5;\n font-weight: bold\n}\n.hljs-bullet {\n /* prettylights-syntax-markup-list */\n color: #735c0f\n}\n.hljs-emphasis {\n /* prettylights-syntax-markup-italic */\n color: #24292e;\n font-style: italic\n}\n.hljs-strong {\n /* prettylights-syntax-markup-bold */\n color: #24292e;\n font-weight: bold\n}\n.hljs-addition {\n /* prettylights-syntax-markup-inserted */\n color: #22863a;\n background-color: #f0fff4\n}\n.hljs-deletion {\n /* prettylights-syntax-markup-deleted */\n color: #b31d28;\n background-color: #ffeef0\n}\n.hljs-char.escape_,\n.hljs-link,\n.hljs-params,\n.hljs-property,\n.hljs-punctuation,\n.hljs-tag {\n /* purposely ignored */\n \n}");
|
|
8
8
|
|
|
@@ -236,7 +236,7 @@ class Registry {
|
|
|
236
236
|
/**
|
|
237
237
|
* Add `plugin` to the registry, keyed by `name`.
|
|
238
238
|
*
|
|
239
|
-
* @param {object} plugin Plugin object with { name,
|
|
239
|
+
* @param {object} plugin Plugin object with string values for { name, type, filename }.
|
|
240
240
|
* @param {string} name The key used to retrieve and invoke the plugin.
|
|
241
241
|
*/
|
|
242
242
|
registerPlugin(plugin, name) {
|
|
@@ -263,33 +263,19 @@ class Registry {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
/**
|
|
266
|
-
* Return
|
|
267
|
-
* Each entry contains
|
|
266
|
+
* Return an array of registered plugins that match type, all if not specified.
|
|
267
|
+
* Each entry contains {name, type, filename}
|
|
268
268
|
*
|
|
269
|
-
* @returns {Array<{
|
|
269
|
+
* @returns {Array<{name: string, type: string, filename: string}>}
|
|
270
270
|
*/
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
getPlugins(type) {
|
|
272
|
+
if (type) {
|
|
273
|
+
return Array.from(this._plugins.values()).filter(plugin => plugin.type === type)
|
|
274
|
+
} else {
|
|
275
|
+
return Array.from(this._plugins.values())
|
|
275
276
|
}
|
|
276
|
-
return manifest
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
/**
|
|
280
|
-
* Invoke `action` on the named plugin, passing `...args`.
|
|
281
|
-
* Returns null if the plugin is not found or does not define the action.
|
|
282
|
-
*
|
|
283
|
-
* @param {string} name The key used to identify the plugin.
|
|
284
|
-
* @param {string} action The action to invoke (e.g. 'export', 'import').
|
|
285
|
-
* @param {...*} args Arguments forwarded to the plugin action.
|
|
286
|
-
* @returns {*|null}
|
|
287
|
-
*/
|
|
288
|
-
invokePlugin(name, action, ...args) {
|
|
289
|
-
const plugin = this._plugins.get(name);
|
|
290
|
-
if (!plugin || typeof plugin[action] !== 'function') return null
|
|
291
|
-
return plugin[action](...args)
|
|
292
|
-
}
|
|
293
279
|
}
|
|
294
280
|
|
|
295
281
|
/**
|
|
@@ -369,29 +355,174 @@ function registerDelegate(delegate, name) {_registry.registerDelegate.bind(_regi
|
|
|
369
355
|
*/
|
|
370
356
|
function registerMessageHandler(handler, name) {_registry.registerMessageHandler.bind(_registry)(handler, name);}
|
|
371
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Add the `editor` to the registry.
|
|
360
|
+
*
|
|
361
|
+
* When we register an editor, it becomes the active editor.
|
|
362
|
+
*
|
|
363
|
+
* @param {MarkupEditor} editor The MarkupEditor to be added
|
|
364
|
+
*/
|
|
372
365
|
const registerEditor = _registry.registerEditor.bind(_registry);
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Remove the `editor` from the registry.
|
|
369
|
+
*
|
|
370
|
+
* @param {MarkupEditor} editor The MarkupEditor to be removed
|
|
371
|
+
*/
|
|
373
372
|
const unregisterEditor = _registry.unregisterEditor.bind(_registry);
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Remove the `delegate` from the registry.
|
|
376
|
+
*
|
|
377
|
+
* @param {MarkupDelegate | object} delegate A MarkupDelegate or appropriate object.
|
|
378
|
+
* @param {string} name A name used to retrieve the `delegate`.
|
|
379
|
+
*/
|
|
374
380
|
_registry.unregisterDelegate.bind(_registry);
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Return the `delegate` with `name`.
|
|
384
|
+
*
|
|
385
|
+
* @param {string} name A name used to retrieve the `delegate`.
|
|
386
|
+
* @returns {MarkupDelegate | object | undefined}
|
|
387
|
+
*/
|
|
375
388
|
const getDelegate = _registry.getDelegate.bind(_registry);
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Remove the `config` from the registry.
|
|
392
|
+
*
|
|
393
|
+
* @param {ToolbarConfig | KeymapConfig | BehaviorConfig | object} config One of the "configs" from the MarkupEditor API or appropriate object.
|
|
394
|
+
* @param {string} name A name used to retrieve the `config`.
|
|
395
|
+
*/
|
|
376
396
|
_registry.unregisterConfig.bind(_registry);
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Return the `config` with `name`.
|
|
400
|
+
*
|
|
401
|
+
* @param {string} name A name used to retrieve the `config`.
|
|
402
|
+
* @returns {ToolbarConfig | KeymapConfig | BehaviorConfig | object | undefined}
|
|
403
|
+
*/
|
|
377
404
|
const getConfig = _registry.getConfig.bind(_registry);
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Remove the `handler` from the registry.
|
|
408
|
+
*
|
|
409
|
+
* @param {MessageHandler | object} handler An instance of MessageHandler or appropriate object.
|
|
410
|
+
* @param {string} name A name used to retrieve the `handler`.
|
|
411
|
+
*/
|
|
378
412
|
_registry.unregisterMessageHandler.bind(_registry);
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Return the `handler` with `name`.
|
|
416
|
+
*
|
|
417
|
+
* @param {string} name A name used to retrieve the `handler`.
|
|
418
|
+
* @returns {MessageHandler | object | undefined}
|
|
419
|
+
*/
|
|
379
420
|
const getMessageHandler = _registry.getMessageHandler.bind(_registry);
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Remove the `toolbar` augmentation from the registry.
|
|
424
|
+
*
|
|
425
|
+
* @param {object} toolbar A toolbar that holds `cmdItems`.
|
|
426
|
+
* @param {string} name A name used to retrieve the `toolbar`.
|
|
427
|
+
*/
|
|
380
428
|
_registry.unregisterAugmentation.bind(_registry);
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Return the `toolbar` whose `menuItems` will be
|
|
432
|
+
* either prepended or appended to the normal MarkupEditor toolbar.
|
|
433
|
+
*
|
|
434
|
+
* @param {string} name A name used to retrieve the `toolbar`.
|
|
435
|
+
* @returns {object | undefined}
|
|
436
|
+
*/
|
|
381
437
|
const getAugmentation = _registry.getAugmentation.bind(_registry);
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Return the active editor with `muId` of the registry's `activeMuId`.
|
|
441
|
+
*
|
|
442
|
+
* @returns {MarkupEditor | undefined}
|
|
443
|
+
*/
|
|
382
444
|
_registry.activeEditor.bind(_registry);
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Return the active editor's `document` (could be the shadow root).
|
|
448
|
+
*
|
|
449
|
+
* @returns {Document | ShadowRoot | undefined}
|
|
450
|
+
*/
|
|
383
451
|
const activeDocument = _registry.activeDocument.bind(_registry);
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Set `activeMuId` based on `document` (could be a shadow root).
|
|
455
|
+
*
|
|
456
|
+
* @param {Document | ShadowRoot} document
|
|
457
|
+
*/
|
|
384
458
|
const setActiveDocument = _registry.setActiveDocument.bind(_registry);
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Return the active editor's element (typically with focus).
|
|
462
|
+
*
|
|
463
|
+
* @returns {Element | undefined}
|
|
464
|
+
*/
|
|
385
465
|
const activeEditorElement = _registry.activeEditorElement.bind(_registry);
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Return the active editor's `messageHandler`.
|
|
469
|
+
*
|
|
470
|
+
* @returns {MessageHandler | object | undefined}
|
|
471
|
+
*/
|
|
386
472
|
_registry.activeMessageHandler.bind(_registry);
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Return the active editor's instance of Searcher, `searcher`.
|
|
476
|
+
*
|
|
477
|
+
* @returns {object | undefined}
|
|
478
|
+
*/
|
|
387
479
|
const activeSearcher = _registry.activeSearcher.bind(_registry);
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Return the cached ID of the selected contentEditable element.
|
|
483
|
+
*
|
|
484
|
+
* @returns {string | undefined}
|
|
485
|
+
*/
|
|
388
486
|
const selectedID = _registry.selectedID.bind(_registry);
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Set/cache the ID of the selected contentEditable element to `string`.
|
|
490
|
+
*
|
|
491
|
+
* @param {string} string
|
|
492
|
+
*/
|
|
389
493
|
const setSelectedID = _registry.setSelectedID.bind(_registry);
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Add `plugin` to the registry, keyed by `name`.
|
|
497
|
+
*
|
|
498
|
+
* @param {object} plugin Plugin object with string values for { name, type, filename }.
|
|
499
|
+
* @param {string} name The key used to retrieve and invoke the plugin.
|
|
500
|
+
*/
|
|
390
501
|
const registerPlugin = _registry.registerPlugin.bind(_registry);
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Remove the plugin with `name` from the registry.
|
|
505
|
+
*
|
|
506
|
+
* @param {string} name The key used to identify the plugin.
|
|
507
|
+
*/
|
|
508
|
+
const unregisterPlugin = _registry.unregisterPlugin.bind(_registry);
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Return the plugin object with `name`, or undefined if not found.
|
|
512
|
+
*
|
|
513
|
+
* @param {string} name The key used to identify the plugin.
|
|
514
|
+
* @returns {object|undefined}
|
|
515
|
+
*/
|
|
516
|
+
const getPlugin = _registry.getPlugin.bind(_registry);
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Return an array of registered plugins that match `type`, all if not specified.
|
|
520
|
+
* Each entry contains {name, type, filename}
|
|
521
|
+
*
|
|
522
|
+
* @param {string} [type] The plugin type to filter by; all plugins are returned if omitted.
|
|
523
|
+
* @returns {Array<{name: string, type: string, filename: string}>}
|
|
524
|
+
*/
|
|
525
|
+
const getPlugins = _registry.getPlugins.bind(_registry);
|
|
395
526
|
|
|
396
527
|
/**
|
|
397
528
|
* MUError captures internal errors and makes it easy to communicate them externally.
|
|
@@ -12417,6 +12548,15 @@ function isSurrogatePair(str) {
|
|
|
12417
12548
|
let a = str.charCodeAt(0), b = str.charCodeAt(1);
|
|
12418
12549
|
return a >= 0xDC00 && a <= 0xDFFF && b >= 0xD800 && b <= 0xDBFF;
|
|
12419
12550
|
}
|
|
12551
|
+
|
|
12552
|
+
/**
|
|
12553
|
+
@internal
|
|
12554
|
+
*/
|
|
12555
|
+
const __parseFromClipboard = parseFromClipboard;
|
|
12556
|
+
/**
|
|
12557
|
+
@internal
|
|
12558
|
+
*/
|
|
12559
|
+
const __endComposition = endComposition;
|
|
12420
12560
|
/**
|
|
12421
12561
|
An editor view manages the DOM structure that represents an
|
|
12422
12562
|
editable document. Its state and behavior are determined by its
|
|
@@ -32597,11 +32737,18 @@ var HighlightJS = /*@__PURE__*/getDefaultExportFromCjs(commonExports);
|
|
|
32597
32737
|
* Delegates to hljs.getLanguage, which lowercases internally and checks
|
|
32598
32738
|
* both registered names and aliases, so this is case-insensitive and
|
|
32599
32739
|
* alias-aware.
|
|
32740
|
+
*
|
|
32741
|
+
* Plugins of type 'codeview' are also recognized languages in the sense
|
|
32742
|
+
* that UI that depends on the return value here needs to know they will
|
|
32743
|
+
* be rendered by the plugin.
|
|
32600
32744
|
*
|
|
32601
32745
|
* @param {string} name
|
|
32602
32746
|
* @returns {boolean}
|
|
32603
32747
|
*/
|
|
32604
32748
|
function isRecognizedLanguage(name) {
|
|
32749
|
+
let codeviews = getPlugins('codeview');
|
|
32750
|
+
let isCodeViewLanguage = codeviews.filter(plugin => plugin.name === name).length > 0;
|
|
32751
|
+
if (isCodeViewLanguage) { return true }
|
|
32605
32752
|
return !!HighlightJS.getLanguage((name ?? '').trim())
|
|
32606
32753
|
}
|
|
32607
32754
|
|
|
@@ -32629,6 +32776,61 @@ function presentCodeLanguages(doc) {
|
|
|
32629
32776
|
return Array.from(languages).sort()
|
|
32630
32777
|
}
|
|
32631
32778
|
|
|
32779
|
+
// hljs never has classPrefix reconfigured elsewhere in this codebase, so this
|
|
32780
|
+
// matches its own default. No public getter exists to read it back instead.
|
|
32781
|
+
const HLJS_CLASS_PREFIX = 'hljs-';
|
|
32782
|
+
|
|
32783
|
+
// Mirrors hljs's internal (unexported) scopeToCSSClass so class strings here
|
|
32784
|
+
// match what hljs's own HTML renderer would produce for the same scope name.
|
|
32785
|
+
function scopeToClass(name, prefix) {
|
|
32786
|
+
if (name.startsWith('language:')) return name.replace('language:', 'language-')
|
|
32787
|
+
if (name.includes('.')) {
|
|
32788
|
+
const pieces = name.split('.');
|
|
32789
|
+
return [`${prefix}${pieces.shift()}`, ...pieces.map((piece, i) => `${piece}${'_'.repeat(i + 1)}`)].join(' ')
|
|
32790
|
+
}
|
|
32791
|
+
return `${prefix}${name}`
|
|
32792
|
+
}
|
|
32793
|
+
|
|
32794
|
+
// Implements hljs's documented Renderer contract (addText/openNode/closeNode)
|
|
32795
|
+
// for TokenTree.walk, tracking span positions instead of building HTML.
|
|
32796
|
+
class SpanWalker {
|
|
32797
|
+
constructor(prefix) {
|
|
32798
|
+
this.prefix = prefix;
|
|
32799
|
+
this.position = 0;
|
|
32800
|
+
this.stack = [];
|
|
32801
|
+
this.spans = [];
|
|
32802
|
+
}
|
|
32803
|
+
|
|
32804
|
+
addText(text) {
|
|
32805
|
+
this.position += text.length;
|
|
32806
|
+
}
|
|
32807
|
+
|
|
32808
|
+
openNode(node) {
|
|
32809
|
+
if (node.scope) this.stack.push({ scope: node.scope, from: this.position });
|
|
32810
|
+
}
|
|
32811
|
+
|
|
32812
|
+
closeNode(node) {
|
|
32813
|
+
if (!node.scope) return
|
|
32814
|
+
const { scope, from } = this.stack.pop();
|
|
32815
|
+
this.spans.push({ from, to: this.position, class: scopeToClass(scope, this.prefix) });
|
|
32816
|
+
}
|
|
32817
|
+
}
|
|
32818
|
+
|
|
32819
|
+
/**
|
|
32820
|
+
* {from, to, class} spans for `code` highlighted as `language`, via hljs's
|
|
32821
|
+
* token tree (result._emitter.walk).
|
|
32822
|
+
*/
|
|
32823
|
+
function highlightSpans(code, language) {
|
|
32824
|
+
try {
|
|
32825
|
+
const result = HighlightJS.highlight(code, { language, ignoreIllegals: true });
|
|
32826
|
+
const walker = new SpanWalker(HLJS_CLASS_PREFIX);
|
|
32827
|
+
result._emitter.walk(walker);
|
|
32828
|
+
return walker.spans
|
|
32829
|
+
} catch {
|
|
32830
|
+
return []
|
|
32831
|
+
}
|
|
32832
|
+
}
|
|
32833
|
+
|
|
32632
32834
|
/**
|
|
32633
32835
|
* Define various arrays of tags used to represent MarkupEditor-specific concepts.
|
|
32634
32836
|
*
|
|
@@ -32962,21 +33164,61 @@ function pasteCode(text) {
|
|
|
32962
33164
|
|
|
32963
33165
|
/**
|
|
32964
33166
|
* Do a custom paste operation of "text only", which we will extract from the html
|
|
32965
|
-
* ourselves. First we get a node that conforms to the schema, which by definition
|
|
33167
|
+
* ourselves. First we get a node that conforms to the schema, which by definition
|
|
32966
33168
|
* only includes elements in a form we recognize, no spans, styles, etc.
|
|
32967
33169
|
* The trick here is that we want to use the same code to paste text as we do for
|
|
32968
33170
|
* HTML, but we want to paste something that is the MarkupEditor-equivalent of
|
|
32969
33171
|
* unformatted text.
|
|
32970
|
-
*
|
|
33172
|
+
*
|
|
32971
33173
|
* @param {string} html The HTML to be pasted
|
|
32972
33174
|
* @param {ClipboardEvent | null} event A mocked ClipboardEvent for testing
|
|
32973
33175
|
*/
|
|
32974
33176
|
function pasteText(html, event) {
|
|
32975
|
-
const node = _nodeFromHTML(html);
|
|
33177
|
+
const node = _nodeFromHTML(_preprocessPasteText(html));
|
|
32976
33178
|
const htmlFragment = fragmentFromNode(node);
|
|
32977
33179
|
const minimalHTML = _minimalHTML(htmlFragment); // Reduce to MarkupEditor-equivalent of "plain" text
|
|
32978
33180
|
pasteHTML(minimalHTML, event);
|
|
32979
33181
|
}
|
|
33182
|
+
/**
|
|
33183
|
+
* Preprocess raw text before it's parsed as HTML by _nodeFromHTML, converting
|
|
33184
|
+
* meaningful line structure into real markup so it survives.
|
|
33185
|
+
*
|
|
33186
|
+
* Only applied when there's an actual newline AND no real markup at all: that
|
|
33187
|
+
* combination means genuinely plain text (e.g., from a clipboard with no text/html
|
|
33188
|
+
* flavor available, or a plain-text-only source app) whose line structure is
|
|
33189
|
+
* meaningful — not HTML, where a run of whitespace (including newlines) collapses to
|
|
33190
|
+
* nothing meaningful once parsed. Gating on '\n' presence too, not just the absence
|
|
33191
|
+
* of '<', matters: some callers intentionally pass single-line text containing
|
|
33192
|
+
* literal HTML entities (e.g. "Hello <b>bold</b> world", meant to render
|
|
33193
|
+
* as that literal text, not a tag) with no '<' character anywhere in it either —
|
|
33194
|
+
* without the '\n' check, that would be misidentified as bare plain text needing
|
|
33195
|
+
* escaping and get double-escaped (< -> &lt;). No newline means there's
|
|
33196
|
+
* nothing this preprocessing could improve regardless, so it only ever applies to
|
|
33197
|
+
* input _nodeFromHTML couldn't already have handled correctly as HTML on its own.
|
|
33198
|
+
* @ignore
|
|
33199
|
+
*/
|
|
33200
|
+
function _preprocessPasteText(html) {
|
|
33201
|
+
return (html.includes('\n') && !html.includes('<')) ? _linebreaksToHTML(html) : html;
|
|
33202
|
+
}
|
|
33203
|
+
/**
|
|
33204
|
+
* Convert bare plain text (no HTML markup at all) into minimal paragraph/br-structured
|
|
33205
|
+
* HTML: a blank line (a run of two or more newlines) starts a new paragraph; a single
|
|
33206
|
+
* newline within a paragraph becomes a <br>. Text is HTML-escaped first via a detached
|
|
33207
|
+
* element's textContent/innerHTML round-trip, the standard safe way to escape arbitrary
|
|
33208
|
+
* text for insertion into an HTML string, so literal &, <, > in the source can't be
|
|
33209
|
+
* misinterpreted once this result is parsed as HTML by the caller.
|
|
33210
|
+
* @ignore
|
|
33211
|
+
*/
|
|
33212
|
+
function _linebreaksToHTML(text) {
|
|
33213
|
+
return text
|
|
33214
|
+
.split(/\n[ \t]*\n+/)
|
|
33215
|
+
.map(paragraph => {
|
|
33216
|
+
const div = document.createElement('div');
|
|
33217
|
+
div.textContent = paragraph;
|
|
33218
|
+
return `<p>${div.innerHTML.split('\n').join('<br>')}</p>`;
|
|
33219
|
+
})
|
|
33220
|
+
.join('');
|
|
33221
|
+
}
|
|
32980
33222
|
/**
|
|
32981
33223
|
* Return a minimal "unformatted equivalent" version of the HTML that is in fragment.
|
|
32982
33224
|
*
|
|
@@ -33792,10 +34034,9 @@ function codeBlockAtSelection(state) {
|
|
|
33792
34034
|
}
|
|
33793
34035
|
|
|
33794
34036
|
/**
|
|
33795
|
-
* Return `{pos, label}`
|
|
33796
|
-
*
|
|
33797
|
-
*
|
|
33798
|
-
* Decoration for the overlay should be anchored. `label` is "Language:
|
|
34037
|
+
* Return `{pos, label}` for the language tab of the code_block at `state`'s
|
|
34038
|
+
* selection, or null if the selection isn't in a code_block. `pos` is the
|
|
34039
|
+
* position just inside the code_block's content. `label` is "Language:
|
|
33799
34040
|
* <lowercase name>" or "Language: none" — display-only, the underlying
|
|
33800
34041
|
* `language` attribute value is untouched.
|
|
33801
34042
|
*
|
|
@@ -33803,7 +34044,7 @@ function codeBlockAtSelection(state) {
|
|
|
33803
34044
|
* @param {EditorState} state
|
|
33804
34045
|
* @returns {{pos: number, label: string} | null}
|
|
33805
34046
|
*/
|
|
33806
|
-
function
|
|
34047
|
+
function codeLanguageTabInfo(state) {
|
|
33807
34048
|
const found = codeBlockAtSelection(state);
|
|
33808
34049
|
if (!found) return null
|
|
33809
34050
|
const language = found.node.attrs.language;
|
|
@@ -34833,7 +35074,7 @@ function _loadedUserFiles(target) {
|
|
|
34833
35074
|
* @param {MUError} error
|
|
34834
35075
|
*/
|
|
34835
35076
|
function _callbackError(error) {
|
|
34836
|
-
_callback(error.messageDict());
|
|
35077
|
+
_callback(JSON.stringify(error.messageDict()));
|
|
34837
35078
|
}
|
|
34838
35079
|
|
|
34839
35080
|
/**
|
|
@@ -35112,7 +35353,7 @@ function testPasteHTMLPreprocessing(html) {
|
|
|
35112
35353
|
* @param {string} html The HTML to paste
|
|
35113
35354
|
*/
|
|
35114
35355
|
function testPasteTextPreprocessing(html) {
|
|
35115
|
-
const node = _nodeFromHTML(html);
|
|
35356
|
+
const node = _nodeFromHTML(_preprocessPasteText(html));
|
|
35116
35357
|
const fragment = fragmentFromNode(node);
|
|
35117
35358
|
const minimalHTML = _minimalHTML(fragment);
|
|
35118
35359
|
return minimalHTML;
|
|
@@ -35133,12 +35374,12 @@ function testPresentCodeLanguages() {
|
|
|
35133
35374
|
return presentCodeLanguages(view.state.doc);
|
|
35134
35375
|
}
|
|
35135
35376
|
/**
|
|
35136
|
-
* For testing purposes, invoke
|
|
35377
|
+
* For testing purposes, invoke codeLanguageTabInfo on the active document's
|
|
35137
35378
|
* current selection.
|
|
35138
35379
|
*/
|
|
35139
|
-
function
|
|
35380
|
+
function testCodeLanguageTabInfo() {
|
|
35140
35381
|
const view = activeView();
|
|
35141
|
-
return
|
|
35382
|
+
return codeLanguageTabInfo(view.state);
|
|
35142
35383
|
}
|
|
35143
35384
|
/********************************************************************************
|
|
35144
35385
|
* Links
|
|
@@ -36085,6 +36326,20 @@ function consoleLog(string) {
|
|
|
36085
36326
|
};
|
|
36086
36327
|
_callback(JSON.stringify(messageDict));
|
|
36087
36328
|
}
|
|
36329
|
+
/**
|
|
36330
|
+
* Report an error to the delegate's markupError method, the same path internal
|
|
36331
|
+
* MUErrors use. For external plugins that have their own error conditions
|
|
36332
|
+
* (e.g., a failed render) but no access to the internal MUError/_callbackError
|
|
36333
|
+
* machinery directly.
|
|
36334
|
+
*
|
|
36335
|
+
* @param {string} code A short identifier for the error.
|
|
36336
|
+
* @param {string} message The error message.
|
|
36337
|
+
* @param {string} [info] Optional additional detail.
|
|
36338
|
+
* @param {boolean} [alert] Whether the host app should treat this as alert-worthy. Defaults to true.
|
|
36339
|
+
*/
|
|
36340
|
+
function reportError(code, message, info, alert=true) {
|
|
36341
|
+
_callbackError(new MUError(code, message, info, alert));
|
|
36342
|
+
}
|
|
36088
36343
|
|
|
36089
36344
|
var visibility = {
|
|
36090
36345
|
toolbar: true,
|
|
@@ -38491,15 +38746,11 @@ class LanguageDialogItem extends DialogItem {
|
|
|
38491
38746
|
this.languageArea.addEventListener('keydown', e => { // Use keydown because 'input' isn't triggered for Enter
|
|
38492
38747
|
if (e.key === 'Enter') {
|
|
38493
38748
|
e.preventDefault();
|
|
38494
|
-
//
|
|
38495
|
-
//
|
|
38496
|
-
//
|
|
38497
|
-
//
|
|
38498
|
-
|
|
38499
|
-
this.submit();
|
|
38500
|
-
} else {
|
|
38501
|
-
this.closeDialog();
|
|
38502
|
-
}
|
|
38749
|
+
// OK is always the default action, even for an empty or unrecognized
|
|
38750
|
+
// language — entering something not yet in the recognized set (e.g. a
|
|
38751
|
+
// new fenced-code language) must work on Enter alone, without first
|
|
38752
|
+
// having to click OK to override Cancel as the default.
|
|
38753
|
+
this.submit();
|
|
38503
38754
|
} else if (e.key === 'Tab') {
|
|
38504
38755
|
e.preventDefault();
|
|
38505
38756
|
} else if (e.key === 'Escape') {
|
|
@@ -38511,25 +38762,12 @@ class LanguageDialogItem extends DialogItem {
|
|
|
38511
38762
|
|
|
38512
38763
|
/**
|
|
38513
38764
|
* Whether the input currently has any language name entered, recognized or
|
|
38514
|
-
* not. An empty field means "no language" — never colored invalid
|
|
38515
|
-
* also not something recognized, so it alone doesn't make OK the default
|
|
38516
|
-
* button; see hasRecognizedLanguage().
|
|
38765
|
+
* not. An empty field means "no language" — never colored invalid.
|
|
38517
38766
|
*/
|
|
38518
38767
|
hasContent() {
|
|
38519
38768
|
return this.languageArea.value.trim().length > 0
|
|
38520
38769
|
}
|
|
38521
38770
|
|
|
38522
|
-
/**
|
|
38523
|
-
* Whether the input currently holds a recognized language name. Drives which
|
|
38524
|
-
* of OK/Cancel looks like the default button — Cancel is default when the
|
|
38525
|
-
* field is empty OR holds an unsupported name, OK only once a supported
|
|
38526
|
-
* language is entered. Submission itself is never blocked either way (OK
|
|
38527
|
-
* stays enabled always); this only changes which button LOOKS default.
|
|
38528
|
-
*/
|
|
38529
|
-
hasRecognizedLanguage() {
|
|
38530
|
-
return this.hasContent() && isRecognizedLanguage(this.languageArea.value)
|
|
38531
|
-
}
|
|
38532
|
-
|
|
38533
38771
|
/**
|
|
38534
38772
|
* Color the input text red (the same .invalid convention ImageItem's srcArea
|
|
38535
38773
|
* uses) when it has an unsupported language entered. Called on every keystroke;
|
|
@@ -38544,10 +38782,11 @@ class LanguageDialogItem extends DialogItem {
|
|
|
38544
38782
|
/**
|
|
38545
38783
|
* Create and append the OK/Cancel buttons, positioned and styled like LinkItem's:
|
|
38546
38784
|
* a left-side spacer so buttonsDiv's space-between pushes the OK/Cancel group to
|
|
38547
|
-
* the right, and
|
|
38548
|
-
*
|
|
38549
|
-
*
|
|
38550
|
-
* error to block on
|
|
38785
|
+
* the right, and OK always the default (active-styled) button, regardless of
|
|
38786
|
+
* whether the field is empty or holds an unrecognized language — an unrecognized
|
|
38787
|
+
* language is a valid, deliberate choice (e.g. a new fenced-code language), not
|
|
38788
|
+
* an error to block submission on. Both buttons stay enabled always; only OK's
|
|
38789
|
+
* active styling is a fixed constant, not state-dependent.
|
|
38551
38790
|
*
|
|
38552
38791
|
* @param {EditorView} view
|
|
38553
38792
|
*/
|
|
@@ -38562,7 +38801,7 @@ class LanguageDialogItem extends DialogItem {
|
|
|
38562
38801
|
let okItem = cmdItem(() => this.submit(), {
|
|
38563
38802
|
class: prefix + '-menuitem',
|
|
38564
38803
|
title: 'OK',
|
|
38565
|
-
active: () => { return
|
|
38804
|
+
active: () => { return true },
|
|
38566
38805
|
enable: () => { return true }
|
|
38567
38806
|
});
|
|
38568
38807
|
let {dom: okDom, update: okUpdate} = okItem.render(view);
|
|
@@ -38573,7 +38812,7 @@ class LanguageDialogItem extends DialogItem {
|
|
|
38573
38812
|
let cancelItem = cmdItem(() => this.closeDialog(), {
|
|
38574
38813
|
class: prefix + '-menuitem',
|
|
38575
38814
|
title: 'Cancel',
|
|
38576
|
-
active: () => { return
|
|
38815
|
+
active: () => { return false },
|
|
38577
38816
|
enable: () => { return true }
|
|
38578
38817
|
});
|
|
38579
38818
|
let {dom: cancelDom, update: cancelUpdate} = cancelItem.render(view);
|
|
@@ -40579,78 +40818,37 @@ const tablePlugin = new Plugin({
|
|
|
40579
40818
|
}
|
|
40580
40819
|
});
|
|
40581
40820
|
|
|
40582
|
-
|
|
40821
|
+
function decorationsForSpans(pos, spans) {
|
|
40822
|
+
return spans.map(({from, to, class: cls}) => Decoration.inline(pos + 1 + from, pos + 1 + to, {class: cls}))
|
|
40823
|
+
}
|
|
40583
40824
|
|
|
40584
|
-
|
|
40585
|
-
|
|
40586
|
-
|
|
40587
|
-
|
|
40588
|
-
|
|
40589
|
-
|
|
40590
|
-
*
|
|
40591
|
-
* @ignore
|
|
40592
|
-
*/
|
|
40593
|
-
function highlightSpecs(code, language) {
|
|
40594
|
-
let html;
|
|
40595
|
-
try {
|
|
40596
|
-
html = HighlightJS.highlight(code, {language, ignoreIllegals: true}).value;
|
|
40597
|
-
} catch {
|
|
40598
|
-
return []
|
|
40599
|
-
}
|
|
40600
|
-
const container = document.createElement('div');
|
|
40601
|
-
container.innerHTML = html;
|
|
40602
|
-
const specs = [];
|
|
40603
|
-
let offset = 0;
|
|
40604
|
-
function walk(parent) {
|
|
40605
|
-
parent.childNodes.forEach((child) => {
|
|
40606
|
-
if (child.nodeType === Node.TEXT_NODE) {
|
|
40607
|
-
offset += child.textContent.length;
|
|
40608
|
-
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
40609
|
-
const start = offset;
|
|
40610
|
-
walk(child);
|
|
40611
|
-
const cls = child.getAttribute('class');
|
|
40612
|
-
if (cls) specs.push({from: start, to: offset, class: cls});
|
|
40613
|
-
}
|
|
40614
|
-
});
|
|
40615
|
-
}
|
|
40616
|
-
walk(container);
|
|
40617
|
-
return specs
|
|
40825
|
+
// null for anything that isn't a highlightable code_block, so callers can
|
|
40826
|
+
// skip it (no cache entry, no decorations) with a single check.
|
|
40827
|
+
function highlightEntryFor(node) {
|
|
40828
|
+
const language = node.attrs.language;
|
|
40829
|
+
if (!language || !isRecognizedLanguage(language)) return null
|
|
40830
|
+
return {node, spans: highlightSpans(node.textContent, language)}
|
|
40618
40831
|
}
|
|
40619
40832
|
|
|
40620
|
-
|
|
40621
|
-
|
|
40622
|
-
* DecorationSet highlighting each one, using a WeakMap cache keyed by node
|
|
40623
|
-
* identity so unchanged blocks (same node reference across transactions,
|
|
40624
|
-
* per ProseMirror's persistent-tree structural sharing) are never re-run
|
|
40625
|
-
* through hljs.highlight().
|
|
40626
|
-
*
|
|
40627
|
-
* @ignore
|
|
40628
|
-
*/
|
|
40629
|
-
function computeCodeHighlightDecorations(doc) {
|
|
40833
|
+
function computeAllHighlights(doc) {
|
|
40834
|
+
const cache = new Map();
|
|
40630
40835
|
const decorations = [];
|
|
40631
40836
|
doc.descendants((node, pos) => {
|
|
40632
40837
|
if (node.type.name !== 'code_block') return
|
|
40633
|
-
const
|
|
40634
|
-
if (
|
|
40635
|
-
|
|
40636
|
-
|
|
40637
|
-
|
|
40638
|
-
codeHighlightCache.set(node, specs);
|
|
40639
|
-
}
|
|
40640
|
-
specs.forEach(({from, to, class: cls}) => {
|
|
40641
|
-
decorations.push(Decoration.inline(pos + 1 + from, pos + 1 + to, {class: cls}));
|
|
40642
|
-
});
|
|
40838
|
+
const entry = highlightEntryFor(node);
|
|
40839
|
+
if (entry) {
|
|
40840
|
+
cache.set(pos, entry);
|
|
40841
|
+
decorations.push(...decorationsForSpans(pos, entry.spans));
|
|
40842
|
+
}
|
|
40643
40843
|
return false
|
|
40644
40844
|
});
|
|
40645
|
-
return DecorationSet.create(doc, decorations)
|
|
40845
|
+
return {cache, decorations: DecorationSet.create(doc, decorations)}
|
|
40646
40846
|
}
|
|
40647
40847
|
|
|
40648
40848
|
/**
|
|
40649
40849
|
* Walk cur's children, comparing against old's, skipping any subtree that's
|
|
40650
|
-
* the same node object as before
|
|
40651
|
-
*
|
|
40652
|
-
* nodes in the changed region, so cost is bounded by how much of the doc
|
|
40653
|
-
* actually changed rather than the whole document.
|
|
40850
|
+
* the same node object as before. Bounds cost to the changed region rather
|
|
40851
|
+
* than the whole document.
|
|
40654
40852
|
*
|
|
40655
40853
|
* @ignore
|
|
40656
40854
|
*/
|
|
@@ -40670,149 +40868,73 @@ function changedDescendants(old, cur, offset, f) {
|
|
|
40670
40868
|
}
|
|
40671
40869
|
}
|
|
40672
40870
|
|
|
40673
|
-
|
|
40674
|
-
|
|
40675
|
-
|
|
40676
|
-
|
|
40677
|
-
|
|
40678
|
-
|
|
40679
|
-
|
|
40680
|
-
|
|
40871
|
+
// Carries cache entries forward by position + Node.eq, not object identity;
|
|
40872
|
+
// changedDescendants then fills in anything new or actually changed.
|
|
40873
|
+
function updateHighlights(tr, {cache}) {
|
|
40874
|
+
const nextCache = new Map();
|
|
40875
|
+
const decorations = [];
|
|
40876
|
+
const carryForward = (pos, entry) => {
|
|
40877
|
+
nextCache.set(pos, entry);
|
|
40878
|
+
decorations.push(...decorationsForSpans(pos, entry.spans));
|
|
40879
|
+
};
|
|
40880
|
+
|
|
40881
|
+
cache.forEach(({node, spans}, pos) => {
|
|
40882
|
+
const mapped = tr.mapping.mapResult(pos);
|
|
40883
|
+
if (mapped.deleted) return
|
|
40884
|
+
const newNode = tr.doc.nodeAt(mapped.pos);
|
|
40885
|
+
if (newNode && newNode.eq(node)) carryForward(mapped.pos, {node: newNode, spans});
|
|
40886
|
+
});
|
|
40887
|
+
|
|
40888
|
+
changedDescendants(tr.before, tr.doc, 0, (node, pos) => {
|
|
40889
|
+
if (node.type.name !== 'code_block' || nextCache.has(pos)) return
|
|
40890
|
+
const entry = highlightEntryFor(node);
|
|
40891
|
+
if (entry) carryForward(pos, entry);
|
|
40892
|
+
});
|
|
40893
|
+
|
|
40894
|
+
return {cache: nextCache, decorations: DecorationSet.create(tr.doc, decorations)}
|
|
40895
|
+
}
|
|
40896
|
+
|
|
40897
|
+
// Syntax-highlighting decorations for code_block nodes with a registered
|
|
40898
|
+
// language. Only registered via markupSetup() when highlightCode is on.
|
|
40681
40899
|
const codeHighlightPlugin = new Plugin({
|
|
40682
40900
|
state: {
|
|
40683
40901
|
init(_, {doc}) {
|
|
40684
|
-
return
|
|
40902
|
+
return computeAllHighlights(doc)
|
|
40685
40903
|
},
|
|
40686
|
-
apply(tr,
|
|
40687
|
-
|
|
40688
|
-
let touchedCodeBlock = false;
|
|
40689
|
-
const checkCodeBlock = (node) => {
|
|
40690
|
-
if (node.type.name === 'code_block') touchedCodeBlock = true;
|
|
40691
|
-
};
|
|
40692
|
-
// Check both directions: a code_block added/changed in the new doc, and one
|
|
40693
|
-
// removed (e.g. by undoing a paragraph->code_block conversion) from the old
|
|
40694
|
-
// doc. changedDescendants(old, cur, ...) only ever visits cur's children, so
|
|
40695
|
-
// catching removal requires calling it again with old/new swapped.
|
|
40696
|
-
changedDescendants(tr.before, tr.doc, 0, checkCodeBlock);
|
|
40697
|
-
if (!touchedCodeBlock) changedDescendants(tr.doc, tr.before, 0, checkCodeBlock);
|
|
40698
|
-
if (!touchedCodeBlock) return set.map(tr.mapping, tr.doc)
|
|
40699
|
-
return computeCodeHighlightDecorations(tr.doc)
|
|
40904
|
+
apply(tr, value) {
|
|
40905
|
+
return tr.docChanged ? updateHighlights(tr, value) : value
|
|
40700
40906
|
}
|
|
40701
40907
|
},
|
|
40702
40908
|
props: {
|
|
40703
|
-
decorations(state) { return codeHighlightPlugin.getState(state) }
|
|
40909
|
+
decorations(state) { return codeHighlightPlugin.getState(state).decorations }
|
|
40704
40910
|
}
|
|
40705
40911
|
});
|
|
40706
40912
|
|
|
40707
40913
|
/**
|
|
40708
|
-
*
|
|
40709
|
-
*
|
|
40710
|
-
* doesn't need to be pixel-exact, just enough to decide which side to attach to.
|
|
40711
|
-
*
|
|
40712
|
-
* @ignore
|
|
40713
|
-
*/
|
|
40714
|
-
const CODE_LANGUAGE_OVERLAY_HEIGHT = 24;
|
|
40715
|
-
|
|
40716
|
-
/**
|
|
40717
|
-
* Whether there's room above `preDOM` (the code_block's own <pre> element) to show
|
|
40718
|
-
* the language overlay label there without it being pushed above the toolbar or
|
|
40719
|
-
* off-screen — if not, it should attach below instead. `view.nodeDOM` is used
|
|
40720
|
-
* read-only here (getBoundingClientRect only); mutating its result is what caused
|
|
40721
|
-
* the CPU-loop regression fixed earlier, so this must never write to preDOM.
|
|
40722
|
-
*
|
|
40723
|
-
* @ignore
|
|
40724
|
-
*/
|
|
40725
|
-
function hasRoomAboveOverlay(view, preDOM) {
|
|
40726
|
-
if (!preDOM) return true
|
|
40727
|
-
const preRect = preDOM.getBoundingClientRect();
|
|
40728
|
-
const toolbarRect = getToolbar(view)?.getBoundingClientRect();
|
|
40729
|
-
const minTop = (toolbarRect?.bottom ?? 0) + CODE_LANGUAGE_OVERLAY_HEIGHT;
|
|
40730
|
-
return preRect.top >= minTop
|
|
40731
|
-
}
|
|
40732
|
-
|
|
40733
|
-
/**
|
|
40734
|
-
* Compute the semi-transparent "Language: <name>" widget Decoration for the
|
|
40735
|
-
* selected code_block, if any. Recomputed on every transaction — this is only
|
|
40736
|
-
* a selection lookup plus a string, not a doc walk, so unlike
|
|
40737
|
-
* computeCodeHighlightDecorations there's no need to cache or gate on
|
|
40738
|
-
* tr.docChanged.
|
|
40739
|
-
*
|
|
40740
|
-
* @ignore
|
|
40741
|
-
*/
|
|
40742
|
-
function computeCodeLanguageOverlayDecorations(state, languageDialog) {
|
|
40743
|
-
const info = codeLanguageOverlayInfo(state);
|
|
40744
|
-
if (!info) return DecorationSet.empty
|
|
40745
|
-
// An empty code_block's only content would become this widget's contentEditable=false
|
|
40746
|
-
// button — the exact "non-editable content alone in a textblock" case prosemirror-view
|
|
40747
|
-
// itself flags as fragile in Safari/Chrome (addTextblockHacks, working around Safari
|
|
40748
|
-
// bug #1165 and Chrome bug #1152). Skip the overlay until there's actual code; there's
|
|
40749
|
-
// nothing useful to show a language badge over yet anyway.
|
|
40750
|
-
const found = codeBlockAtSelection(state);
|
|
40751
|
-
if (!found || found.node.content.size === 0) return DecorationSet.empty
|
|
40752
|
-
const widget = Decoration.widget(info.pos, (view) => {
|
|
40753
|
-
const button = document.createElement('button');
|
|
40754
|
-
button.type = 'button';
|
|
40755
|
-
button.className = prefix + '-code-language-overlay';
|
|
40756
|
-
if (!hasRoomAboveOverlay(view, view.nodeDOM(found.pos))) {
|
|
40757
|
-
button.classList.add(prefix + '-code-language-overlay-below');
|
|
40758
|
-
}
|
|
40759
|
-
button.textContent = info.label;
|
|
40760
|
-
// Without this, the button is ambiguous to the browser's native cursor placement
|
|
40761
|
-
// as part of the code_block's editable text flow.
|
|
40762
|
-
button.contentEditable = 'false';
|
|
40763
|
-
button.addEventListener('mousedown', (e) => {
|
|
40764
|
-
e.preventDefault();
|
|
40765
|
-
const found = codeBlockAtSelection(view.state);
|
|
40766
|
-
languageDialog.open(view, found?.node.attrs.language ?? '', (entered) => {
|
|
40767
|
-
setCodeLanguageCommand(entered ? entered : null)(view.state, view.dispatch, view);
|
|
40768
|
-
});
|
|
40769
|
-
});
|
|
40770
|
-
return button
|
|
40771
|
-
}, {
|
|
40772
|
-
side: 1,
|
|
40773
|
-
// By default the cursor at the widget's position is strictly kept on the
|
|
40774
|
-
// `side` indicated above, and per prosemirror-view's own docs "keyboard
|
|
40775
|
-
// cursor motion will not, without further custom handling, visit both
|
|
40776
|
-
// sides of the widget" — which is what broke placing/moving the cursor to
|
|
40777
|
-
// a code_block's start. relaxedSide lets the DOM selection land on either
|
|
40778
|
-
// side instead of being force-pinned to one.
|
|
40779
|
-
relaxedSide: true,
|
|
40780
|
-
// Keyed so ProseMirror reuses the existing button DOM node (and its click listener)
|
|
40781
|
-
// across transactions unrelated to this block, instead of destroying and rebuilding it
|
|
40782
|
-
// on every single transaction while a code block is selected (WidgetType.eq() only
|
|
40783
|
-
// short-circuits reuse on a spec.key match). The key includes pos and label — not just
|
|
40784
|
-
// a static string — so a genuinely different block or language change still gets a
|
|
40785
|
-
// fresh toDOM call rather than silently reusing stale button text.
|
|
40786
|
-
key: `code-language-overlay-${info.pos}-${info.label}`
|
|
40787
|
-
});
|
|
40788
|
-
return DecorationSet.create(state.doc, [widget])
|
|
40789
|
-
}
|
|
40790
|
-
|
|
40791
|
-
/**
|
|
40792
|
-
* Build the plugin that shows the selected code_block's language overlay.
|
|
40793
|
-
* A factory (not a module-level singleton like codeHighlightPlugin) because it
|
|
40794
|
-
* owns a LanguageDialogItem bound to this editor instance's `config` — sharing
|
|
40795
|
-
* one across multiple `<markup-editor>` instances on the same page would let
|
|
40796
|
-
* one instance's dialog state stomp on another's.
|
|
40914
|
+
* Return the plugin that shows the selected code_block's language tab (owned
|
|
40915
|
+
* by its CodeView NodeView, ../nodeview/codeview.js).
|
|
40797
40916
|
*
|
|
40798
40917
|
* @ignore
|
|
40799
40918
|
*/
|
|
40800
|
-
function
|
|
40801
|
-
|
|
40802
|
-
|
|
40803
|
-
|
|
40804
|
-
|
|
40805
|
-
|
|
40806
|
-
|
|
40807
|
-
|
|
40808
|
-
|
|
40809
|
-
|
|
40810
|
-
|
|
40811
|
-
|
|
40812
|
-
|
|
40919
|
+
function codeLanguageTabPlugin() {
|
|
40920
|
+
return new Plugin({
|
|
40921
|
+
view(editorView) {
|
|
40922
|
+
let activeCodeView = null;
|
|
40923
|
+
// A pure selection-only transaction never calls a NodeView's own
|
|
40924
|
+
// update(), so this reaches the CodeView directly via view.nodeDOM(pos)
|
|
40925
|
+
// instead.
|
|
40926
|
+
const sync = (view) => {
|
|
40927
|
+
const found = codeBlockAtSelection(view.state);
|
|
40928
|
+
const nextCodeView = found ? view.nodeDOM(found.pos)?.codeView : null;
|
|
40929
|
+
if (nextCodeView === activeCodeView) return
|
|
40930
|
+
activeCodeView?.setActive(false);
|
|
40931
|
+
nextCodeView?.setActive(true);
|
|
40932
|
+
activeCodeView = nextCodeView;
|
|
40933
|
+
};
|
|
40934
|
+
sync(editorView);
|
|
40935
|
+
return { update: sync }
|
|
40813
40936
|
}
|
|
40814
|
-
})
|
|
40815
|
-
return thePlugin
|
|
40937
|
+
})
|
|
40816
40938
|
}
|
|
40817
40939
|
|
|
40818
40940
|
const searchModePlugin = new Plugin({
|
|
@@ -40961,10 +41083,10 @@ function markupSetup(config, schema) {
|
|
|
40961
41083
|
plugins.push(tablePlugin);
|
|
40962
41084
|
|
|
40963
41085
|
// Add the plugins that highlight code blocks and show the selected block's
|
|
40964
|
-
// language
|
|
41086
|
+
// language tab, if enabled in behavior config
|
|
40965
41087
|
if (config.behavior.highlightCode) {
|
|
40966
41088
|
plugins.push(codeHighlightPlugin);
|
|
40967
|
-
plugins.push(
|
|
41089
|
+
plugins.push(codeLanguageTabPlugin());
|
|
40968
41090
|
}
|
|
40969
41091
|
|
|
40970
41092
|
// Add the plugin that handles placeholder display for an empty document, as passed in config
|
|
@@ -41599,6 +41721,102 @@ class DivView {
|
|
|
41599
41721
|
|
|
41600
41722
|
}
|
|
41601
41723
|
|
|
41724
|
+
// Approximate rendered height of the language tab (font-size 0.75rem +
|
|
41725
|
+
// padding 2px 6px, styles/markup.css) — only used for the room-above check below,
|
|
41726
|
+
// doesn't need to be pixel-exact.
|
|
41727
|
+
const CODE_LANGUAGE_TAB_HEIGHT = 24;
|
|
41728
|
+
|
|
41729
|
+
/**
|
|
41730
|
+
* NodeView for code_block. The language tab is a DOM sibling of contentDOM,
|
|
41731
|
+
* appended/removed by setActive. No selectNode/deselectNode — code_block
|
|
41732
|
+
* selection is a TextSelection inside its content, never a NodeSelection.
|
|
41733
|
+
*
|
|
41734
|
+
* Stores `view` directly rather than this codebase's activeView() lookup
|
|
41735
|
+
* (imageview.js): the tab's mousedown only ever fires from this view's own
|
|
41736
|
+
* DOM, so there's no cross-instance ambiguity to resolve.
|
|
41737
|
+
*
|
|
41738
|
+
* node.attrs.language only ever affects the tab's label and contentDOM's
|
|
41739
|
+
* class — never which code_block this applies to or how it's structured.
|
|
41740
|
+
*/
|
|
41741
|
+
class CodeView {
|
|
41742
|
+
constructor(node, view, getPos, languageDialog) {
|
|
41743
|
+
this.view = view;
|
|
41744
|
+
this.languageDialog = languageDialog;
|
|
41745
|
+
this.dom = document.createElement('pre');
|
|
41746
|
+
this.contentDOM = document.createElement('code');
|
|
41747
|
+
this.dom.appendChild(this.contentDOM);
|
|
41748
|
+
// codeLanguageTabPlugin (setup/index.js) reads this via
|
|
41749
|
+
// view.nodeDOM(pos) to call setActive on the right instance.
|
|
41750
|
+
this.dom.codeView = this;
|
|
41751
|
+
this.syncLanguageClass(node);
|
|
41752
|
+
this.tab = this.buildTab();
|
|
41753
|
+
this.setTabLabel(node);
|
|
41754
|
+
}
|
|
41755
|
+
|
|
41756
|
+
update(node) {
|
|
41757
|
+
if (node.type.name !== 'code_block') return false
|
|
41758
|
+
this.syncLanguageClass(node);
|
|
41759
|
+
this.setTabLabel(node);
|
|
41760
|
+
return true
|
|
41761
|
+
}
|
|
41762
|
+
|
|
41763
|
+
// ProseMirror's default ignoreMutation is `!contentDOM && mutation.type !=
|
|
41764
|
+
// "selection"`. Override here to avoid losing tab during mutation.
|
|
41765
|
+
ignoreMutation(mutation) {
|
|
41766
|
+
return mutation.type !== 'selection' && !this.contentDOM.contains(mutation.target)
|
|
41767
|
+
}
|
|
41768
|
+
|
|
41769
|
+
// Whether there's room above this.dom to show the language tab
|
|
41770
|
+
// without it being pushed above the toolbar or off-screen.
|
|
41771
|
+
hasRoomAbove() {
|
|
41772
|
+
if (!this.dom) return true
|
|
41773
|
+
const preRect = this.dom.getBoundingClientRect();
|
|
41774
|
+
const toolbarRect = getToolbar(this.view)?.getBoundingClientRect();
|
|
41775
|
+
const minTop = (toolbarRect?.bottom ?? 0) + CODE_LANGUAGE_TAB_HEIGHT;
|
|
41776
|
+
return preRect.top >= minTop
|
|
41777
|
+
}
|
|
41778
|
+
|
|
41779
|
+
// The tab sits outside contentDOM, similar to the way imageView works
|
|
41780
|
+
// for handles.
|
|
41781
|
+
setActive(isActive) {
|
|
41782
|
+
if (isActive && !this.tab.isConnected) {
|
|
41783
|
+
this.tab.classList.toggle(prefix + '-code-language-tab-below', !this.hasRoomAbove());
|
|
41784
|
+
this.dom.appendChild(this.tab);
|
|
41785
|
+
} else if (!isActive && this.tab.isConnected) {
|
|
41786
|
+
this.dom.removeChild(this.tab);
|
|
41787
|
+
}
|
|
41788
|
+
}
|
|
41789
|
+
|
|
41790
|
+
destroy() {
|
|
41791
|
+
this.dom.codeView = null;
|
|
41792
|
+
}
|
|
41793
|
+
|
|
41794
|
+
syncLanguageClass(node) {
|
|
41795
|
+
const language = node.attrs.language;
|
|
41796
|
+
this.contentDOM.className = language ? `language-${language}` : '';
|
|
41797
|
+
}
|
|
41798
|
+
|
|
41799
|
+
setTabLabel(node) {
|
|
41800
|
+
const language = node.attrs.language;
|
|
41801
|
+
this.tab.textContent = language ? `Language: ${language.toLowerCase()}` : 'Language: none';
|
|
41802
|
+
}
|
|
41803
|
+
|
|
41804
|
+
buildTab() {
|
|
41805
|
+
const button = document.createElement('button');
|
|
41806
|
+
button.type = 'button';
|
|
41807
|
+
button.className = prefix + '-code-language-tab';
|
|
41808
|
+
button.contentEditable = 'false';
|
|
41809
|
+
button.addEventListener('mousedown', (e) => {
|
|
41810
|
+
e.preventDefault();
|
|
41811
|
+
const found = codeBlockAtSelection(this.view.state);
|
|
41812
|
+
this.languageDialog.open(this.view, found?.node.attrs.language ?? '', (entered) => {
|
|
41813
|
+
setCodeLanguageCommand(entered ? entered : null)(this.view.state, this.view.dispatch, this.view);
|
|
41814
|
+
});
|
|
41815
|
+
});
|
|
41816
|
+
return button
|
|
41817
|
+
}
|
|
41818
|
+
}
|
|
41819
|
+
|
|
41602
41820
|
/**
|
|
41603
41821
|
* The MessageHandler receives `postMessage` from the MarkupEditor as the document state changes.
|
|
41604
41822
|
*
|
|
@@ -42041,10 +42259,19 @@ class MarkupEditor {
|
|
|
42041
42259
|
this.config.delegate = getDelegate(delegate);
|
|
42042
42260
|
}
|
|
42043
42261
|
|
|
42262
|
+
// One dialog per editor instance, not per code_block — sharing one across
|
|
42263
|
+
// multiple <markup-editor> instances on the same page would let one
|
|
42264
|
+
// instance's dialog state stomp on another's. In contrast to the other
|
|
42265
|
+
// dialogs, like LinkDialog, the languageDialog can be initiated from
|
|
42266
|
+
// the tab that shows when it is selected, not just the menu item. This
|
|
42267
|
+
// necessitates creating it here so we can pass it to the CodeView.
|
|
42268
|
+
const languageDialog = new LanguageDialogItem(this.config);
|
|
42269
|
+
MU.languageDialog = languageDialog;
|
|
42270
|
+
|
|
42044
42271
|
// Create the EditorView for this MarkupEditor
|
|
42045
42272
|
this.view = new EditorView(this.element, {
|
|
42046
42273
|
state: EditorState.create({
|
|
42047
|
-
// For the MarkupEditor, we can just use the editor element.
|
|
42274
|
+
// For the MarkupEditor, we can just use the editor element.
|
|
42048
42275
|
// There is no need to use a separate content element.
|
|
42049
42276
|
doc: DOMParser.fromSchema(schema).parse(this.element),
|
|
42050
42277
|
plugins: markupSetup(this.config, schema)
|
|
@@ -42053,6 +42280,7 @@ class MarkupEditor {
|
|
|
42053
42280
|
link(node, view, getPos) { return new LinkView(node, view, getPos) },
|
|
42054
42281
|
image(node, view, getPos) { return new ImageView(node, view, getPos) },
|
|
42055
42282
|
div(node, view, getPos) { return new DivView(node, view, getPos) },
|
|
42283
|
+
code_block(node, view, getPos) { return new CodeView(node, view, getPos, languageDialog) },
|
|
42056
42284
|
},
|
|
42057
42285
|
// All text input makes callbacks to indicate the document state has changed.
|
|
42058
42286
|
// For history, used handleTextInput, but that fires *before* input happens.
|
|
@@ -42194,6 +42422,7 @@ const MU = {
|
|
|
42194
42422
|
cancelSearch,
|
|
42195
42423
|
canUndo,
|
|
42196
42424
|
canRedo,
|
|
42425
|
+
CodeView,
|
|
42197
42426
|
consoleLog,
|
|
42198
42427
|
cutImage,
|
|
42199
42428
|
deactivateSearch,
|
|
@@ -42230,6 +42459,7 @@ const MU = {
|
|
|
42230
42459
|
removeAllDivs,
|
|
42231
42460
|
removeButton,
|
|
42232
42461
|
removeDiv,
|
|
42462
|
+
reportError,
|
|
42233
42463
|
resetSelection,
|
|
42234
42464
|
savedDataImage,
|
|
42235
42465
|
searchFor,
|
|
@@ -42240,7 +42470,7 @@ const MU = {
|
|
|
42240
42470
|
setToolbarVisible,
|
|
42241
42471
|
setTopLevelAttributes,
|
|
42242
42472
|
testBlockquoteEnter,
|
|
42243
|
-
|
|
42473
|
+
testCodeLanguageTabInfo,
|
|
42244
42474
|
testExtractContents,
|
|
42245
42475
|
testIsRecognizedLanguage,
|
|
42246
42476
|
testListEnter,
|
|
@@ -42273,8 +42503,9 @@ const MU = {
|
|
|
42273
42503
|
registerDelegate,
|
|
42274
42504
|
registerMessageHandler,
|
|
42275
42505
|
registerPlugin,
|
|
42276
|
-
|
|
42277
|
-
|
|
42506
|
+
unregisterPlugin,
|
|
42507
|
+
getPlugin,
|
|
42508
|
+
getPlugins,
|
|
42278
42509
|
};
|
|
42279
42510
|
|
|
42280
42511
|
sheet.media.mediaText = '(prefers-color-scheme: dark)';
|
|
@@ -42291,22 +42522,20 @@ sheet.media.mediaText = '(prefers-color-scheme: dark)';
|
|
|
42291
42522
|
*
|
|
42292
42523
|
* @param {string[]} pluginPaths Resolved paths to plugin modules.
|
|
42293
42524
|
* @param {object|null} delegate A MarkupDelegate instance (may be null/undefined).
|
|
42294
|
-
* @param {function} [importFn] Optional import function; defaults to the native dynamic
|
|
42295
|
-
* import. Provided for testing.
|
|
42296
42525
|
* @returns {Promise<void>}
|
|
42297
42526
|
*/
|
|
42298
|
-
async function loadPlugins(pluginPaths, delegate
|
|
42527
|
+
async function loadPlugins(pluginPaths, delegate) {
|
|
42299
42528
|
if (!pluginPaths || pluginPaths.length === 0) return
|
|
42300
|
-
const before = new Set(MU.
|
|
42529
|
+
const before = new Set(MU.getPlugins().map(m => m.name));
|
|
42301
42530
|
await Promise.all(
|
|
42302
42531
|
pluginPaths.map(path =>
|
|
42303
|
-
|
|
42532
|
+
import(path).catch(err => {
|
|
42304
42533
|
console.error('Plugin load failed:', path, err);
|
|
42305
42534
|
return null
|
|
42306
42535
|
})
|
|
42307
42536
|
)
|
|
42308
42537
|
);
|
|
42309
|
-
const after = MU.
|
|
42538
|
+
const after = MU.getPlugins();
|
|
42310
42539
|
const newManifests = after.filter(m => !before.has(m.name));
|
|
42311
42540
|
delegate?.markupPluginsDidLoad && delegate.markupPluginsDidLoad(newManifests);
|
|
42312
42541
|
}
|
|
@@ -42367,7 +42596,7 @@ class MarkupEditorElement extends HTMLElement {
|
|
|
42367
42596
|
const pluginPaths = pluginsAttr ? JSON.parse(pluginsAttr) : [];
|
|
42368
42597
|
const delegate = this.editor.config?.delegate;
|
|
42369
42598
|
await loadPlugins(pluginPaths, delegate);
|
|
42370
|
-
const manifests = MU.
|
|
42599
|
+
const manifests = MU.getPlugins();
|
|
42371
42600
|
if (manifests.length > 0) {
|
|
42372
42601
|
this.editor.messageHandler.postMessage(
|
|
42373
42602
|
JSON.stringify({ messageType: 'markupPluginsDidLoad', plugins: manifests })
|
|
@@ -42544,4 +42773,4 @@ class MarkupEditorElement extends HTMLElement {
|
|
|
42544
42773
|
// Let the browser know about the custom element
|
|
42545
42774
|
customElements.define('markup-editor', MarkupEditorElement);
|
|
42546
42775
|
|
|
42547
|
-
export { ContentMatch, DOMParser, DOMSerializer, Fragment, MU, Mark, MarkType, Node$1 as Node, NodeRange, NodeType$1 as NodeType, ReplaceError, ResolvedPos, Schema, Slice, loadPlugins };
|
|
42776
|
+
export { AllSelection, ContentMatch, DOMParser, DOMSerializer, Decoration, DecorationSet, EditorState, EditorView, Fragment, MU, Mark, MarkType, Node$1 as Node, NodeRange, NodeSelection, NodeType$1 as NodeType, Plugin, PluginKey, ReplaceError, ResolvedPos, Schema, Selection, SelectionRange, Slice, TextSelection, Transaction, __endComposition, __parseFromClipboard, loadPlugins, schema };
|
package/package.json
CHANGED
package/styles/markup.css
CHANGED
|
@@ -267,12 +267,12 @@ img {
|
|
|
267
267
|
|
|
268
268
|
/* Scoped to :has() rather than styling pre unconditionally, since a code_block's
|
|
269
269
|
<pre> should only become a positioning context when it's actually carrying the
|
|
270
|
-
language
|
|
271
|
-
pre:has(.Markup-code-language-
|
|
270
|
+
language tab (highlightCode on, block selected) — not for every code block. */
|
|
271
|
+
pre:has(.Markup-code-language-tab) {
|
|
272
272
|
position: relative;
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
.Markup-code-language-
|
|
275
|
+
.Markup-code-language-tab {
|
|
276
276
|
position: absolute;
|
|
277
277
|
bottom: 100%;
|
|
278
278
|
right: 0;
|
|
@@ -286,20 +286,21 @@ pre:has(.Markup-code-language-overlay) {
|
|
|
286
286
|
background: var(--Markup-accent-color, blue);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
.Markup-code-language-
|
|
289
|
+
.Markup-code-language-tab:hover {
|
|
290
290
|
opacity: 0.9;
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
/* Applied (setup/index.js,
|
|
294
|
-
the top of the view for the
|
|
295
|
-
.Markup-code-language-
|
|
293
|
+
/* Applied (setup/index.js, CodeView.hasRoomAbove) when the code_block is too close to
|
|
294
|
+
the top of the view for the tab to fit above it — attach to the bottom instead. */
|
|
295
|
+
.Markup-code-language-tab-below {
|
|
296
296
|
bottom: auto;
|
|
297
297
|
top: 100%;
|
|
298
298
|
border-radius: 0 0 4px 4px;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
/* Matches .Markup-menuitem-active's selected-button color scheme. */
|
|
301
302
|
@media (prefers-color-scheme: dark) {
|
|
302
|
-
.Markup-code-language-
|
|
303
|
+
.Markup-code-language-tab {
|
|
303
304
|
background: var(--Markup-accent-color, lightblue);
|
|
304
305
|
color: black;
|
|
305
306
|
}
|
package/styles/toolbar.css
CHANGED
|
@@ -520,25 +520,25 @@
|
|
|
520
520
|
}
|
|
521
521
|
|
|
522
522
|
.Markup-prompt-link {
|
|
523
|
-
height:
|
|
523
|
+
height: calc(68px + var(--Markup-button-size, 28px)); /* 96 px by default */
|
|
524
524
|
width: 300px;
|
|
525
525
|
}
|
|
526
526
|
|
|
527
527
|
.Markup-prompt-image {
|
|
528
|
-
height:
|
|
528
|
+
height: calc(102px + var(--Markup-button-size, 28px)); /* 130 px by default */
|
|
529
529
|
width: 300px;
|
|
530
530
|
}
|
|
531
531
|
|
|
532
532
|
.Markup-prompt-language {
|
|
533
|
-
height:
|
|
533
|
+
height: calc(68px + var(--Markup-button-size, 28px)); /* 96 px by default */
|
|
534
534
|
width: 300px;
|
|
535
535
|
}
|
|
536
536
|
|
|
537
537
|
.Markup-prompt img {
|
|
538
538
|
display: inline-block;
|
|
539
539
|
vertical-align: middle;
|
|
540
|
-
min-width: 28px;
|
|
541
|
-
height: 28px;
|
|
540
|
+
min-width: var(--Markup-button-size, 28px);
|
|
541
|
+
height: var(--Markup-button-size, 28px);
|
|
542
542
|
margin-right: 4px;
|
|
543
543
|
}
|
|
544
544
|
|
|
@@ -589,8 +589,8 @@
|
|
|
589
589
|
vertical-align: middle;
|
|
590
590
|
justify-content: space-between;
|
|
591
591
|
justify-items: center;
|
|
592
|
-
line-height: 28px;
|
|
593
|
-
height: 28px;
|
|
592
|
+
line-height: var(--Markup-button-size, 28px);
|
|
593
|
+
height: var(--Markup-button-size, 28px);
|
|
594
594
|
margin-top: 8px;
|
|
595
595
|
margin-bottom: 8px;
|
|
596
596
|
}
|