(_hyperscript)
| 16 | import { Tokenizer } from '../core/tokenizer.js'; |
| 17 | |
| 18 | export default function componentPlugin(_hyperscript) { |
| 19 | const { runtime, createParser, reactivity } = _hyperscript.internals; |
| 20 | const tokenizer = new Tokenizer(); |
| 21 | |
| 22 | // Hide undefined custom elements to avoid a flash of unstyled content |
| 23 | // while bundle fetches or the after-process walk register them. The rule |
| 24 | // only matches custom elements (built-in tags are always :defined), so |
| 25 | // it's safe to apply globally. Injected lazily on the first before-process |
| 26 | // hook (rather than at module load) so that we know <head> exists and that |
| 27 | // the extension is running in a real document. |
| 28 | function ensureFouceGuard() { |
| 29 | if (typeof document === 'undefined' || !document.head) return; |
| 30 | if (document.head.querySelector('style[data-hyperscript-component="fouce-guard"]')) return; |
| 31 | var styleEl = document.createElement('style'); |
| 32 | styleEl.setAttribute('data-hyperscript-component', 'fouce-guard'); |
| 33 | styleEl.textContent = ':not(:defined) { visibility: hidden; }'; |
| 34 | document.head.appendChild(styleEl); |
| 35 | } |
| 36 | |
| 37 | function substituteSlots(templateSource, slotContent, scopeSel) { |
| 38 | if (!slotContent) return templateSource; |
| 39 | |
| 40 | // Parse slot content to separate named slots from default |
| 41 | var tmp = document.createElement('div'); |
| 42 | tmp.innerHTML = slotContent; |
| 43 | var named = {}; |
| 44 | var defaultParts = []; |
| 45 | |
| 46 | // Annotate slotted elements with dom-scope to resolve ^var from outer context |
| 47 | for (var child of Array.from(tmp.childNodes)) { |
| 48 | if (child.nodeType === 1 && scopeSel && !child.hasAttribute('dom-scope')) { |
| 49 | child.setAttribute('dom-scope', 'parent of ' + scopeSel); |
| 50 | } |
| 51 | var slotName = child.nodeType === 1 && child.getAttribute('slot'); |
| 52 | if (slotName) { |
| 53 | child.removeAttribute('slot'); |
| 54 | if (!named[slotName]) named[slotName] = ''; |
| 55 | named[slotName] += child.outerHTML; |
| 56 | } else { |
| 57 | defaultParts.push(child.nodeType === 1 ? child.outerHTML : |
| 58 | child.nodeType === 3 ? child.textContent : ''); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | var defaultContent = defaultParts.join(''); |
| 63 | |
| 64 | // Replace named slots: <slot name="X"/> or <slot name="X"></slot> |
| 65 | var source = templateSource.replace( |
| 66 | /<slot\s+name\s*=\s*["']([^"']+)["']\s*\/?\s*>(\s*<\/slot>)?/g, |
| 67 | function(_, name) { return named[name] || ''; } |
| 68 | ); |
| 69 | |
| 70 | // Replace default slots: <slot/> or <slot></slot> |
| 71 | source = source.replace(/<slot\s*\/?\s*>(\s*<\/slot>)?/g, defaultContent); |
| 72 | |
| 73 | return source; |
| 74 | } |
| 75 |
nothing calls this directly
no test coverage detected