pome-ui 2.0.0-preview61 → 2.0.0-preview64

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/pome-ui.dev.js CHANGED
@@ -18109,2483 +18109,2490 @@ ${codeFrame}` : message);
18109
18109
  })({});
18110
18110
 
18111
18111
  // PomeUI
18112
- // Copyright (c) Yuko(Yisheng) Zheng. All rights reserved.
18113
- // Licensed under the GPL v3. See LICENSE in the project root for license information.
18114
-
18115
- window.Vue = Vue;
18116
-
18117
- function build(options, exports) {
18118
- if (typeof exports == 'undefined') {
18119
- exports = {};
18120
- }
18121
-
18122
- // Options
18123
- var _options = {
18124
- resolveModulesParallelly: true,
18125
- removeStyleWhenUnmount: false,
18126
- preloadCss: true,
18127
- mobile: function () {
18128
- return false;
18129
- },
18130
- httpGet: function (url) {
18131
- return fetch(url);
18132
- },
18133
- httpGetSync: function (url) {
18134
- if (useRelativePath) {
18135
- if (url.length && url[0] == '/') {
18136
- url = url.substr(1);
18137
- }
18138
- }
18139
- var xhr = new XMLHttpRequest();
18140
- xhr.open('get', url, false);
18141
- xhr.send();
18142
- return xhr.responseText;
18143
- },
18144
- onNotFound: function (url, options) {
18145
- if (url.indexOf('/404') == 0) {
18146
- throw 'No not-found template found';
18147
- }
18148
- if (options) {
18149
- return Redirect('/404?' + _serializeOptionsToUrl(options));
18150
- } else {
18151
- return Redirect('/404');
18152
- }
18153
- },
18154
- reuseContainerActiveView(viewName) {
18155
- return true;
18156
- },
18157
- callCreatedWhenReuseContainerActiveView(viewName) {
18158
- return true;
18159
- },
18160
- callMountedWhenReuseContainerActiveView(viewName) {
18161
- return true;
18162
- },
18163
- callUnmountedWhenReuseContainerActiveView(viewName) {
18164
- return true;
18165
- },
18166
- resetDataWhenReuseContainerActiveView(viewName) {
18167
- return true;
18168
- },
18169
- generateTitle(titles) {
18170
- return titles.join(' - ');
18171
- }
18172
- };
18173
-
18174
- _combineObject(options, _options);
18175
-
18176
- // Common
18177
- var _cache = {};
18178
-
18179
- var _css = {};
18180
-
18181
- var _cssCloakInjected = false;
18182
- function _ensureCssCloakStyle() {
18183
- if (_cssCloakInjected) return;
18184
- _cssCloakInjected = true;
18185
- var style = document.createElement('style');
18186
- style.textContent = '._pome-css-cloak{visibility:hidden!important}';
18187
- document.head.appendChild(style);
18188
- }
18189
-
18190
- var _vueCloakInjected = false;
18191
- function _ensureVueCloakStyle() {
18192
- if (_vueCloakInjected) return;
18193
- _vueCloakInjected = true;
18194
- var style = document.createElement('style');
18195
- style.textContent = '._pome-vue-cloak{display:none!important}';
18196
- document.head.appendChild(style);
18197
- }
18198
-
18199
- function _ensureSkeletonStyle() {
18200
- // pome-skeleton.css must be referenced by the host page manually.
18201
- // This function is kept as a hook point for future use.
18202
- }
18203
-
18204
- // Registry: kebab-name �?pre-rendered skeleton HTML string
18205
- var _componentSkeletonRegistry = {};
18206
-
18207
- function _toKebabCase(name) {
18208
- // ScalableSidebar �?scalable-sidebar, menuBar �?menu-bar
18209
- return name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
18210
- }
18211
-
18212
- function _registerComponentSkeleton(name, opt, rawHtml, skeletonFileHtml) {
18213
- // skeletonFileHtml: content of <component>.skeleton.html (takes top priority)
18214
- // opt.skeleton === string: inline HTML declared in the JS
18215
- // opt.skeleton === true: auto-generate from rawHtml
18216
- var hasFile = !!skeletonFileHtml;
18217
- var hasInline = opt && typeof opt.skeleton === 'string';
18218
- var hasAuto = opt && opt.skeleton === true;
18219
- if (!hasFile && !hasInline && !hasAuto) return;
18220
- var kebab = _toKebabCase(name);
18221
- var skHtml = hasFile ? skeletonFileHtml
18222
- : hasInline ? opt.skeleton
18223
- : _generateSkeletonHtml(rawHtml || (opt && opt.template) || '');
18224
- _componentSkeletonRegistry[kebab] = skHtml;
18225
- }
18226
-
18227
- // --- Extract a plain numeric value from a bound attribute like :default-width="230" ---
18228
- function _extractBoundNumber(el, attr) {
18229
- var val = el.getAttribute(':' + attr);
18230
- if (!val) return null;
18231
- var m = val.match(/^(\d+(?:\.\d+)?)/);
18232
- return m ? m[1] : null;
18233
- }
18234
-
18235
- // --- Known HTML tags for skeleton (custom components will be unwrapped) ---
18236
- var _knownHtmlTags = null;
18237
- function _isKnownHtmlTag(tag) {
18238
- if (!_knownHtmlTags) {
18239
- _knownHtmlTags = {};
18240
- 'div,span,p,a,h1,h2,h3,h4,h5,h6,ul,ol,li,table,thead,tbody,tfoot,tr,td,th,colgroup,col,img,video,canvas,iframe,svg,form,input,textarea,select,option,button,label,section,article,aside,header,footer,nav,main,figure,figcaption,blockquote,pre,code,em,strong,i,b,u,small,sub,sup,br,hr,dl,dt,dd,details,summary,fieldset,legend,caption,abbr,cite,mark,time,address'.split(',').forEach(function(t) { _knownHtmlTags[t] = true; });
18241
- }
18242
- return !!_knownHtmlTags[tag];
18243
- }
18244
-
18245
- function _generateSkeletonHtml(templateHtml) {
18246
- if (!templateHtml) return '';
18247
- var html = templateHtml;
18248
- // Remove Vue mustache expressions �?replace with non-breaking space
18249
- html = html.replace(/\{\{[\s\S]*?\}\}/g, '\u00A0');
18250
- // Parse as DOM
18251
- var doc = new DOMParser().parseFromString(
18252
- '<div id="_pome-sk-wrap">' + html + '</div>', 'text/html'
18253
- );
18254
- var root = doc.getElementById('_pome-sk-wrap');
18255
- if (!root) return '';
18256
- // Pass 1 �?structural: unwrap <template> slots, replace custom elements,
18257
- // clone v-for rows, remove v-else branches
18258
- _skeletonStructurePass(root, doc);
18259
- // Pass 2 �?cleanup: strip Vue directives, replace text with skeleton blocks
18260
- _skeletonCleanupPass(root);
18261
- return root.innerHTML;
18262
- }
18263
-
18264
- function _wrapTemplateWithSkeleton(opt) {
18265
- if (!opt.skeleton || !opt.template) return;
18266
- _ensureSkeletonStyle();
18267
- var skeletonHtml = typeof opt.skeleton === 'string'
18268
- ? opt.skeleton
18269
- : _generateSkeletonHtml(opt.template);
18270
-
18271
- var inner = '<template v-if="!pomeSkeletonLoading && !pomeSkeletonCloaked">' + opt.template
18272
- + '</template><div v-if="pomeSkeletonLoading" class="_pome-skeleton">'
18273
- + skeletonHtml + '</div>';
18274
-
18275
- if (opt.delayOpen) {
18276
- // Wrap everything in a single div with reactive delayOpen classes
18277
- // so the delayOpen animation applies to both skeleton and real content.
18278
- opt.template = '<div :class="{\'_pome-ui-opened\': pomeDelayOpened, \'_pome-ui-opening\': pomeDelayOpening}">' + inner + '</div>';
18279
- } else {
18280
- opt.template = inner;
18281
- }
18282
- }
18283
-
18284
- // --- Pass 1: structural transformations ---
18285
- function _skeletonStructurePass(node, doc) {
18286
- if (!node || node.nodeType !== 1) return;
18287
- var i = 0;
18288
- while (i < node.childNodes.length) {
18289
- var child = node.childNodes[i];
18290
- if (child.nodeType !== 1) { i++; continue; }
18291
- var tag = child.tagName.toLowerCase();
18292
-
18293
- // 1. Handle <template> tags (Vue slots)
18294
- if (tag === 'template') {
18295
- // Determine slot name from #xxx or v-slot:xxx
18296
- var slotName = null;
18297
- for (var a = 0; a < child.attributes.length; a++) {
18298
- var attr = child.attributes[a].name;
18299
- if (attr[0] === '#') { slotName = attr.substring(1); break; }
18300
- if (attr.indexOf('v-slot:') === 0) { slotName = attr.substring(7); break; }
18301
- }
18302
- // Only keep the default slot (or unnamed templates); discard others
18303
- if (slotName && slotName !== 'default') {
18304
- node.removeChild(child);
18305
- continue;
18306
- }
18307
- // Unwrap template content into parent
18308
- if (child.content) {
18309
- var tplNodes = Array.from(child.content.childNodes);
18310
- for (var j = 0; j < tplNodes.length; j++) {
18311
- node.insertBefore(doc.importNode(tplNodes[j], true), child);
18312
- }
18313
- }
18314
- node.removeChild(child);
18315
- continue; // re-examine index (new children inserted)
18316
- }
18317
-
18318
- // 2. Remove v-else / v-else-if branches entirely
18319
- if (child.getAttribute('v-else') !== null || child.getAttribute('v-else-if') !== null) {
18320
- node.removeChild(child);
18321
- continue;
18322
- }
18323
-
18324
- // 3. Handle v-for �?clone element to simulate repeated rows
18325
- if (child.getAttribute('v-for')) {
18326
- child.removeAttribute('v-for');
18327
- var cloneCount = (tag === 'tr') ? 4 : (tag === 'li') ? 3 : 2;
18328
- var refNode = child.nextSibling;
18329
- for (var j = 0; j < cloneCount; j++) {
18330
- var clone = child.cloneNode(true);
18331
- node.insertBefore(clone, refNode);
18332
- }
18333
- // fall through to continue processing this element
18334
- }
18335
-
18336
- // 4. Replace custom/unknown elements with <div>, keep children
18337
- if (!_isKnownHtmlTag(tag)) {
18338
- // Check if this component has declared its own skeleton
18339
- var registeredSkeleton = _componentSkeletonRegistry[tag];
18340
- if (registeredSkeleton) {
18341
- // Parse the registered skeleton HTML and replace the element with it
18342
- var skWrap = doc.createElement('div');
18343
- skWrap.innerHTML = registeredSkeleton;
18344
- if (child.getAttribute('class')) skWrap.setAttribute('class', child.getAttribute('class'));
18345
- var existingStyleReg = child.getAttribute('style') || '';
18346
- var styleExtraReg = '';
18347
- var defWReg = _extractBoundNumber(child, 'default-width') || child.getAttribute('default-width');
18348
- var minWReg = _extractBoundNumber(child, 'min-width') || child.getAttribute('min-width');
18349
- if (defWReg) styleExtraReg += ';width:' + defWReg + 'px;flex-shrink:0';
18350
- if (minWReg) styleExtraReg += ';min-width:' + minWReg + 'px';
18351
- var combinedStyleReg = (existingStyleReg + styleExtraReg).replace(/^;+/, '');
18352
- if (combinedStyleReg) skWrap.setAttribute('style', combinedStyleReg);
18353
- // Replace the custom element with a wrapper containing the skeleton.
18354
- // Use a fragment-like approach: move skWrap's children directly
18355
- // so we don't add an extra div when the registered HTML already has one.
18356
- var skNodes = Array.from(skWrap.childNodes);
18357
- if (skNodes.length === 1 && skNodes[0].nodeType === 1) {
18358
- var skRoot = skNodes[0];
18359
- // Merge class / style from host element onto the single root node
18360
- if (child.getAttribute('class')) skRoot.classList && skRoot.setAttribute('class', (skRoot.getAttribute('class') || '') + ' ' + child.getAttribute('class'));
18361
- if (combinedStyleReg) skRoot.setAttribute('style', (skRoot.getAttribute('style') ? skRoot.getAttribute('style') + ';' : '') + combinedStyleReg);
18362
- node.replaceChild(skRoot, child);
18363
- i++;
18364
- } else {
18365
- while (skWrap.firstChild) node.insertBefore(skWrap.firstChild, child);
18366
- node.removeChild(child);
18367
- // i stays the same since we removed child and inserted nodes before it
18368
- }
18369
- continue;
18370
- }
18371
-
18372
- var div = doc.createElement('div');
18373
- if (child.getAttribute('class')) div.setAttribute('class', child.getAttribute('class'));
18374
-
18375
- // Reconstruct inline style, preserving explicit style + any bound sizing attrs
18376
- var existingStyle = child.getAttribute('style') || '';
18377
- var styleExtra = '';
18378
- // :default-width / default-width �?width + flex-shrink:0 so sidebar-like
18379
- // components keep their width in the skeleton
18380
- var defW = _extractBoundNumber(child, 'default-width') || child.getAttribute('default-width');
18381
- var minW = _extractBoundNumber(child, 'min-width') || child.getAttribute('min-width');
18382
- var maxW = _extractBoundNumber(child, 'max-width') || child.getAttribute('max-width');
18383
- if (defW) styleExtra += ';width:' + defW + 'px;flex-shrink:0';
18384
- if (minW) styleExtra += ';min-width:' + minW + 'px';
18385
- if (maxW) styleExtra += ';max-width:' + maxW + 'px';
18386
- var combinedStyle = (existingStyle + styleExtra).replace(/^;+/, '');
18387
- if (combinedStyle) div.setAttribute('style', combinedStyle);
18388
-
18389
- while (child.firstChild) div.appendChild(child.firstChild);
18390
- node.replaceChild(div, child);
18391
- _skeletonStructurePass(div, doc); // recurse into replacement
18392
- i++;
18393
- continue;
18394
- }
18395
-
18396
- // 5. Recurse into known elements
18397
- _skeletonStructurePass(child, doc);
18398
- i++;
18399
- }
18400
- }
18401
-
18402
- // --- Pass 2: cleanup directives, replace text, handle media ---
18403
- function _skeletonCleanupPass(node) {
18404
- if (!node) return;
18405
- if (node.nodeType === 1) {
18406
- // Strip Vue directives / bindings / event listeners.
18407
- // Preserve v-show so CSS-driven responsive visibility still works
18408
- // (the skeleton lives inside a Vue-processed template).
18409
- var attrsToRemove = [];
18410
- for (var i = 0; i < node.attributes.length; i++) {
18411
- var attrName = node.attributes[i].name;
18412
- if (attrName === 'v-show') continue; // keep v-show for responsive toggling
18413
- if (attrName.indexOf('v-') === 0 || attrName[0] === '@' || attrName[0] === ':' || attrName[0] === '#') {
18414
- attrsToRemove.push(attrName);
18415
- }
18416
- }
18417
- for (var i = 0; i < attrsToRemove.length; i++) {
18418
- node.removeAttribute(attrsToRemove[i]);
18419
- }
18420
- // Remove delayOpen classes
18421
- node.classList.remove('_pome-ui-opened');
18422
- node.classList.remove('_pome-ui-opening');
18423
- // Add shimmer class to leaf-level text containers
18424
- var tag = node.tagName.toLowerCase();
18425
- var shimmerTags = {span:1,a:1,p:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,li:1,label:1,button:1,input:1,textarea:1,select:1,dt:1,dd:1,figcaption:1,blockquote:1};
18426
- if (shimmerTags[tag]) {
18427
- node.classList.add('_pome-sk-shimmer');
18428
- }
18429
- if (tag === 'img') {
18430
- // Replace img with a shimmer skeleton block that preserves dimensions
18431
- var imgBlock = node.ownerDocument.createElement('span');
18432
- imgBlock.className = '_pome-sk-img';
18433
- // Preserve sizing from class or explicit attributes
18434
- if (node.getAttribute('class')) imgBlock.className += ' ' + node.getAttribute('class');
18435
- if (node.getAttribute('width')) imgBlock.style.width = node.getAttribute('width') + (/\d$/.test(node.getAttribute('width')) ? 'px' : '');
18436
- else imgBlock.style.width = '24px';
18437
- if (node.getAttribute('height')) imgBlock.style.height = node.getAttribute('height') + (/\d$/.test(node.getAttribute('height')) ? 'px' : '');
18438
- else imgBlock.style.height = '24px';
18439
- node.parentNode.replaceChild(imgBlock, node);
18440
- return; // node replaced, skip children
18441
- }
18442
- if (tag === 'video' || tag === 'canvas' || tag === 'iframe') {
18443
- node.removeAttribute('src');
18444
- node.removeAttribute('srcset');
18445
- node.style.backgroundColor = '#e8e8e8';
18446
- node.style.borderRadius = '4px';
18447
- }
18448
- }
18449
- var children = Array.from(node.childNodes);
18450
- for (var i = 0; i < children.length; i++) {
18451
- var child = children[i];
18452
- if (child.nodeType === 3) { // text node
18453
- // \u00A0 comes from mustache replacement �?treat it as content
18454
- var text = child.textContent.replace(/[\s\u00A0]+/g, '');
18455
- var hasNbsp = child.textContent.indexOf('\u00A0') >= 0;
18456
- if (text || hasNbsp) {
18457
- var parentTag = child.parentNode && child.parentNode.tagName
18458
- ? child.parentNode.tagName.toLowerCase() : '';
18459
- var block = child.ownerDocument.createElement('span');
18460
- block.className = '_pome-sk-block';
18461
- block.innerHTML = '\u00A0';
18462
- child.parentNode.replaceChild(block, child);
18463
- }
18464
- } else if (child.nodeType === 1) {
18465
- _skeletonCleanupPass(child);
18466
- }
18467
- }
18468
- }
18469
-
18470
- function _httpCached(url) {
18471
- return !!_cache[url];
18472
- }
18473
-
18474
- function _httpGet(url) {
18475
- if (_cache[url]) {
18476
- return Promise.resolve(_cache[url]);
18477
- }
18478
-
18479
- var _url = url;
18480
- if (_options.version) {
18481
- if (url.indexOf('?') > 0) {
18482
- _url += "&";
18483
- } else {
18484
- _url += "?"
18485
- }
18486
- _url += "v=" + _options.version;
18487
- }
18488
-
18489
- return _options.httpGet(_url).then(function (result) {
18490
- if (result.status > 300 || result.status < 200) {
18491
- return Promise.reject(result);
18492
- }
18493
-
18494
- var txt = result.text();
18495
- _cache[url] = txt;
18496
- return Promise.resolve(txt);
18497
- }).catch(function (err) {
18498
- Promise.reject(err);
18499
- });
18500
- };
18501
-
18502
- function _httpExist(url) {
18503
- return _httpGet(url)
18504
- .then(function () {
18505
- return Promise.resolve(true);
18506
- })
18507
- .catch(function () {
18508
- return Promise.resolve(false);
18509
- });
18510
- };
18511
-
18512
- // Fetch a .skeleton.html file, returning null when the file does not
18513
- // physically exist. Unlike _httpGet, this guards against SPA catch-all
18514
- // routes that return the app entry page (status 200) for any URL:
18515
- // if the response body starts with "<!DOCTYPE" or "<html" it is treated
18516
- // as a missing file and null is returned.
18517
- // Caches "not found" results so that repeated requests for the same
18518
- // missing skeleton file do not produce additional network round-trips.
18519
- var _skeletonNotFoundCache = {};
18520
- function _httpGetSkeletonFile(url) {
18521
- if (_skeletonNotFoundCache[url]) {
18522
- return Promise.resolve(null);
18523
- }
18524
- return _httpGet(url).then(function (text) {
18525
- if (!text) {
18526
- _skeletonNotFoundCache[url] = true;
18527
- return null;
18528
- }
18529
- var trimmed = text.replace(/^[\s\uFEFF]+/, ''); // strip BOM / whitespace
18530
- if (/^<!DOCTYPE/i.test(trimmed) || /^<html/i.test(trimmed)) {
18531
- _skeletonNotFoundCache[url] = true;
18532
- return null; // SPA fallback page, not a real skeleton file
18533
- }
18534
- return text;
18535
- }).catch(function () {
18536
- _skeletonNotFoundCache[url] = true;
18537
- return null;
18538
- });
18539
- };
18540
-
18541
- function _serializeOptionsToUrl(options) {
18542
- var fields = Object.getOwnPropertyNames(options);
18543
- var str = '';
18544
- for (var i = 0; i < fields.length; ++i) {
18545
- str += encodeURIComponent(fields[i]) + '=' + encodeURIComponent(options[fields[i]]) + '&';
18546
- }
18547
-
18548
- if (str[str.length - 1] === '&') {
18549
- str = str.substr(0, str.length - 1);
18550
- }
18551
-
18552
- return str;
18553
- }
18554
- function _addHyphenBeforeUppercase(str) {
18555
- var ret = str.replace(/([A-Z])/g, '-$1').toLowerCase();
18556
- while (ret.length && ret[0] == '-') {
18557
- ret = ret.substr(1);
18558
- }
18559
- return ret;
18560
- }
18561
-
18562
- // Resolve the template option:
18563
- // - If it ends with '.html', treat it as a path and fetch the HTML content
18564
- // - Otherwise, treat it as inline HTML code and return it directly
18565
- function _resolveTemplateOption(template) {
18566
- if (!template || typeof template !== 'string') {
18567
- return Promise.resolve(null);
18568
- }
18569
- if (template.toLowerCase().endsWith('.html')) {
18570
- return _httpGet(template).then(function (html) {
18571
- return _sanitizeTemplate(html);
18572
- });
18573
- }
18574
- return Promise.resolve(template);
18575
- }
18576
-
18577
- function _sanitizeTemplate(template) {
18578
- if (!template instanceof String) {
18579
- return template;
18580
- }
18581
-
18582
- var result = [...template.matchAll(/(?<=:)[a-zA-Z0-9-_]{1,}(?=\=")/g)];
18583
- for (var i = 0; i < result.length; ++i) {
18584
- var propertyName = result[i].toString();
18585
- var sanitizedPropertyName = _addHyphenBeforeUppercase(propertyName);
18586
- template = template.replaceAll(':' + propertyName + '=', ':' + sanitizedPropertyName + '=');
18587
- }
18588
-
18589
- result = [...template.matchAll(/(?<=@)[a-zA-Z0-9-_]{1,}(?=\=")/g)];
18590
- for (var i = 0; i < result.length; ++i) {
18591
- var propertyName = result[i].toString();
18592
- var sanitizedPropertyName = _addHyphenBeforeUppercase(propertyName);
18593
- template = template.replaceAll('@' + propertyName + '=', '@' + sanitizedPropertyName + '=');
18594
- }
18595
-
18596
- return template;
18597
- }
18598
-
18599
- var _root = null;
18600
- function root() {
18601
- return _root;
18602
- };
18603
-
18604
- function _findRoot(instance) {
18605
- var globalRoot = exports.root();
18606
- if (globalRoot) return globalRoot;
18607
- if (!instance) return null;
18608
- var current = instance;
18609
- while (current.parent) {
18610
- current = current.parent;
18611
- }
18612
- return current.proxy || current;
18613
- }
18614
-
18615
- exports._rules = [];
18616
-
18617
- function useRoutes(url) {
18618
- var rules = _options.httpGetSync(url);
18619
- rules = JSON.parse(rules);
18620
- if (!exports._rules) {
18621
- exports._rules = {};
18622
- }
18623
- _combineObject(rules, exports._rules);
18624
- }
18625
-
18626
- // Internal
18627
- function _combineObject(src, dest) {
18628
- if (!src) {
18629
- return;
18630
- }
18631
-
18632
- var fields = Object.getOwnPropertyNames(src);
18633
- for (var i = 0; i < fields.length; ++i) {
18634
- dest[fields[i]] = src[fields[i]];
18635
- }
18636
- };
18637
-
18638
- // Helper: Chain an async lifecycle hook onto an existing one
18639
- function _chainHook(obj, hookName, fn) {
18640
- var original = obj[hookName] || function () {};
18641
- obj[hookName] = function () {
18642
- var self = this;
18643
- var result = original.call(self);
18644
- var p = (result && result instanceof Promise) ? result : Promise.resolve();
18645
- return p.then(function () {
18646
- var p2;
18647
- try {
18648
- p2 = fn.call(self);
18649
- } catch (ex) {
18650
- console.error(ex);
18651
- }
18652
- return (p2 && p2 instanceof Promise) ? p2 : Promise.resolve();
18653
- });
18654
- };
18655
- }
18656
-
18657
- // Helper: Hook setup() to inject $app and optional extras
18658
- function _hookSetup(opt, extraFn) {
18659
- var originalSetup = opt.setup || function () {};
18660
- opt.setup = function (props, context) {
18661
- originalSetup(props, context);
18662
- var instance = Vue.getCurrentInstance();
18663
- instance.$app = exports;
18664
- if (extraFn) {
18665
- extraFn.call(this, instance, opt);
18666
- }
18667
- if (!instance.$root) {
18668
- instance.$root = _findRoot(instance);
18669
- }
18670
- if (!instance.$parent) {
18671
- instance.$parent = (instance.parent && instance.parent.proxy) || instance.$root;
18672
- }
18673
- };
18674
- }
18675
-
18676
- // Helper: Hook data() to pass exports and optionally merge params/query
18677
- function _hookData(opt, params) {
18678
- var originalData = opt.data || function () { return {}; };
18679
- opt.data = function () {
18680
- var data = originalData.call(this, exports);
18681
- if (params) {
18682
- _combineObject(params, data);
18683
- _parseQueryString(data);
18684
- }
18685
- return data;
18686
- };
18687
- }
18688
-
18689
- // Helper: Create PomeloModule require function
18690
- function _createRequire(path) {
18691
- if (!PomeloModule) return undefined;
18692
- return function (script, workingDirectory, mode) {
18693
- workingDirectory = workingDirectory || PomeloModule.getContainingFolder(path);
18694
- return PomeloModule.require(script, workingDirectory, mode);
18695
- };
18696
- }
18697
-
18698
- function _getQueryString() {
18699
- var ret = window.location.search;
18700
-
18701
- if (window.location.hash.indexOf('?') > 0) {
18702
- var hashSearch = window.location.hash.substr(window.location.hash.indexOf('?'));
18703
- if (ret) {
18704
- ret += '&' + hashSearch.substr(1);
18705
- } else {
18706
- ret = hashSearch;
18707
- }
18708
- }
18709
-
18710
- return ret;
18711
- }
18712
-
18713
- function _parseQueryString(dest) {
18714
- var qs = _getQueryString();
18715
- if (!qs) {
18716
- return;
18717
- }
18718
-
18719
- var str = qs;
18720
- if (str[0] == '?') {
18721
- str = str.substr(1);
18722
- }
18723
-
18724
- var splited = str.split('&');
18725
- for (var i = 0; i < splited.length; ++i) {
18726
- var splited2 = splited[i].split('=');
18727
- var key = decodeURIComponent(splited2[0]);
18728
- var val = decodeURIComponent(splited2[1]);
18729
- _fillObjectField(key, val, dest);
18730
- }
18731
- }
18732
-
18733
- function _resolveModules(modules, viewName) { // viewName is only for parse macro
18734
- if (!modules) {
18735
- return Promise.resolve();
18736
- }
18737
-
18738
- if (_options.resolveModulesParallelly) {
18739
- var promises = [];
18740
- for (var i = 0; i < modules.length; ++i) {
18741
- promises.push(LoadScript(parseMacroPath(viewName, modules[i])));
18742
- }
18743
-
18744
- return Promise.all(promises);
18745
- } else {
18746
- var promise = Promise.resolve(null);
18747
- var makeFunc = function (module) {
18748
- return function (result) {
18749
- return LoadScript(parseMacroPath(viewName, module));
18750
- };
18751
- };
18752
- for (var i = 0; i < modules.length; ++i) {
18753
- var m = modules[i];
18754
- promise = promise.then(makeFunc(m));
18755
- }
18756
- return promise;
18757
- }
18758
- }
18759
-
18760
- function _buildApp(url, params, mobile, parent) {
18761
- var componentObject = {};
18762
- return _httpGet(url + '.js')
18763
- .then(function (js) {
18764
- var Page = function (options) {
18765
- componentObject = options;
18766
- };
18767
-
18768
- var require = _createRequire(url);
18769
- try {
18770
- eval(js + '\r\n//# sourceURL=' + url + '.js');
18771
- } catch (evalError) {
18772
- console.error('[PomeUI] Failed to eval component JS. URL: ' + url + '.js', evalError);
18773
- throw new Error('Failed to eval component JS (' + url + '.js): ' + (evalError.message || evalError));
18774
- }
18775
- if (!componentObject || (typeof componentObject !== 'object')) {
18776
- console.error('[PomeUI] Component JS did not produce a valid component object. URL: ' + url + '.js', 'Got:', componentObject);
18777
- throw new Error('Component JS (' + url + '.js) did not produce a valid component object. Got: ' + String(componentObject));
18778
- }
18779
- hookMountedAndUnmounted(componentObject, url + (mobile ? '.m' : ''));
18780
- return _resolveModules(componentObject.modules || [], url).then(function () {
18781
- return Promise.resolve(componentObject)
18782
- });
18783
- })
18784
- .then(function (component) {
18785
- var htmlPromise;
18786
- if (mobile) {
18787
- htmlPromise = _httpExist(url + '.m.html').then(function (res) {
18788
- return _httpGet(url + (res ? '.m.html' : '.html'));
18789
- });
18790
- } else {
18791
- htmlPromise = _httpGet(url + '.html');
18792
- }
18793
- // Load .skeleton.html in parallel; null if not found
18794
- var skeletonFilePromise = _httpGetSkeletonFile(url + '.skeleton.html');
18795
-
18796
- // If component.template is specified, resolve it (could be .html path or inline HTML)
18797
- var templateOptionPromise = component.template
18798
- ? _resolveTemplateOption(component.template)
18799
- : Promise.resolve(null);
18800
-
18801
- return Promise.all([htmlPromise, skeletonFilePromise, templateOptionPromise]).then(function (results) {
18802
- var template = results[0];
18803
- var skeletonFileHtml = results[1];
18804
- var resolvedTemplate = results[2];
18805
- if (resolvedTemplate) {
18806
- component.template = resolvedTemplate;
18807
- } else if (!component.template) {
18808
- component.template = _sanitizeTemplate(template);
18809
- }
18810
- // .skeleton.html file takes top priority over skeleton: true / inline string
18811
- if (skeletonFileHtml && component.skeleton) {
18812
- component.skeleton = skeletonFileHtml;
18813
- }
18814
- if (component.delayOpen) {
18815
- var dom = new DOMParser().parseFromString(component.template, 'text/html');
18816
- var children = dom.querySelector('body').children;
18817
- for (var i = 0; i < children.length; ++i) {
18818
- if (children[i].tagName.toUpperCase() != 'DIV') {
18819
- continue;
18820
- }
18821
- if (children[i].getAttribute('v-if') != null || children[i].getAttribute('v-else-if') || children[i].getAttribute('v-else')) {
18822
- continue;
18823
- }
18824
- if (component.skeleton) {
18825
- // Skeleton mode: delayOpen classes will be added by
18826
- // _wrapTemplateWithSkeleton on an outer wrapper div.
18827
- // No need to add them to individual children here.
18828
- } else {
18829
- children[i].classList.add('_pome-ui-opened');
18830
- children[i].classList.add('_pome-ui-opening');
18831
- }
18832
- }
18833
-
18834
- var tpl = template || component.template;
18835
- var ret = tpl.indexOf('<html') >= 0 ? new XMLSerializer().serializeToString(dom) : dom.querySelector('body').innerHTML;
18836
- component.template = ret;
18837
- }
18838
- _patchComponent(url, component, true);
18839
- // _wrapTemplateWithSkeleton is deferred to after _loadComponents
18840
- // so the component skeleton registry is fully populated.
18841
- return Promise.resolve(component);
18842
- });
18843
- })
18844
- .then(function (component) {
18845
- _hookSetup(component, function (instance, comp) {
18846
- instance.$parent = parent || _findRoot(instance);
18847
- instance.$root = _findRoot(instance) || parent;
18848
- instance.$view = url;
18849
- instance.$data = comp.data || function () { return {}; };
18850
- instance.$created = comp.created || function () { };
18851
- instance.$mounted = comp.mounted || function () { };
18852
- instance.$unmounted = comp.unmounted || function () { };
18853
- instance.$delayClose = comp.delayClose || 0;
18854
- _attachContainer(instance);
18855
- });
18856
-
18857
- _hookData(component, params);
18858
-
18859
- // Create instance
18860
- return _resolveModules(component.modules, url).then(function () {
18861
- var components = component.components || [];
18862
- var directives = component.directives || [];
18863
- var _ret;
18864
-
18865
- // Preload page's own CSS before mount
18866
- var pageCssPromise = Promise.resolve();
18867
- var viewName = url + (mobile ? '.m' : '');
18868
- if (_options.preloadCss && component.style) {
18869
- pageCssPromise = appendCssReferenceAsync(viewName, component.style);
18870
- }
18871
-
18872
- return Promise.all([pageCssPromise, _loadComponents(components, url)]).then(function (results) {
18873
- var components = results[1];
18874
- // Wrap skeleton template now that component registry is fully populated.
18875
- _wrapTemplateWithSkeleton(component);
18876
- var ret;
18877
- try {
18878
- ret = Vue.createApp(component);
18879
- } catch (createAppError) {
18880
- console.error('[PomeUI] Vue.createApp failed. URL: ' + url, createAppError);
18881
- console.error('[PomeUI] Component object:', { template: component.template ? component.template.substring(0, 200) + '...' : '(none)', data: typeof component.data, methods: component.methods ? Object.keys(component.methods) : '(none)' });
18882
- throw new Error('Vue.createApp failed for URL ' + url + ': ' + (createAppError.message || createAppError));
18883
- }
18884
-
18885
- for (var i = 0; i < components.length; ++i) {
18886
- var com = components[i];
18887
- ret.component(com.name, com.options);
18888
- }
18889
-
18890
- var originalMountFunc = ret.mount || function () { };
18891
- ret.mount = function (el) {
18892
- ret.proxy = originalMountFunc(el);
18893
- return ret.proxy;
18894
- }
18895
-
18896
- _ret = ret;
18897
- return _loadDirectives(directives, url);
18898
- }).then(function (directives) {
18899
- for (var i = 0; i < directives.length; ++i) {
18900
- var dir = directives[i];
18901
- _ret.directive(dir.name, dir.options);
18902
- }
18903
- return Promise.resolve(_ret);
18904
- });
18905
- });
18906
- });
18907
- };
18908
-
18909
- function _replace(source, find, replace) {
18910
- var idx = source.indexOf(find);
18911
- if (idx < 0) {
18912
- return source;
18913
- }
18914
-
18915
- var ret = source.substr(0, idx) + replace + source.substr(idx + find.length);
18916
- return ret;
18917
- }
18918
-
18919
- function sleep(ms) {
18920
- return new Promise(function (res) {
18921
- setTimeout(function () { res(); }, ms);
18922
- });
18923
- };
18924
-
18925
- function yield() {
18926
- return sleep(0);
18927
- }
18928
-
18929
- function _attachContainer(instance) {
18930
- if (!instance) {
18931
- console.warn('Invalid view model');
18932
- }
18933
-
18934
- if (!instance.$containers) {
18935
- instance.$containers = [];
18936
- }
18937
-
18938
- if (!instance.$containers) {
18939
- instance.$containers = [];
18940
- }
18941
-
18942
- var containers = instance.$containers;
18943
- instance.$container = function (el) {
18944
- var container = containers.filter(x => x.selector == el)[0];
18945
- if (!container) {
18946
- container = {
18947
- element: document.querySelector(el),
18948
- selector: el,
18949
- open: function (url, params) {
18950
- var mobile = _options.mobile();
18951
- var currentProxy = null;
18952
- if (instance.proxy) {
18953
- currentProxy = instance.proxy;
18954
- }
18955
- if (instance.$ && instance.$.proxy) {
18956
- currentProxy = instance.$.proxy;
18957
- }
18958
-
18959
- var p = Promise.resolve();
18960
- if (!this.active || this.active.$view != url || !_options.reuseContainerActiveView()) {
18961
- p = this.close();
18962
- }
18963
-
18964
- var self = this;
18965
-
18966
- return p.then(function () {
18967
- var p = Promise.resolve();
18968
- params = generateParametersFromRoute(params);
18969
- _parseQueryString(params);
18970
- if (_options.reuseContainerActiveView() && self.active?.$view == url) {
18971
- var reuseComponentFunc = function (container) {
18972
- if (!container || !container.active) {
18973
- return p;
18974
- }
18975
-
18976
- if (_options.callUnmountedWhenReuseContainerActiveView(container.active.$view)) {
18977
- p = p.then(function () {
18978
- if (!container.active || !container.active.$unmounted) return Promise.resolve();
18979
- var val = container.active.$unmounted();
18980
- if (val instanceof Promise) {
18981
- return val;
18982
- } else {
18983
- return Promise.resolve();
18984
- }
18985
- });
18986
- }
18987
- p = p.then(function () {
18988
- if (!container.active || !container.active.$data) return Promise.resolve();
18989
- var initData = container.active.$data();
18990
- if (_options.resetDataWhenReuseContainerActiveView()) {
18991
- _combineObject(initData, container.active);
18992
- }
18993
- _combineObject(params, container.active);
18994
- return Promise.resolve();
18995
- });
18996
- if (_options.callCreatedWhenReuseContainerActiveView(container.active.$view)) {
18997
- p = p.then(function () {
18998
- if (!container.active || !container.active.$created) return Promise.resolve();
18999
- var val = container.active.$created();
19000
- if (val instanceof Promise) {
19001
- return val;
19002
- } else {
19003
- return Promise.resolve();
19004
- }
19005
- });
19006
- }
19007
- if (_options.callMountedWhenReuseContainerActiveView(container.active.$view)) {
19008
- p = p.then(function () {
19009
- if (!container.active || !container.active.$mounted) return Promise.resolve();
19010
- var val = container.active.$mounted();
19011
- if (val instanceof Promise) {
19012
- return val;
19013
- } else {
19014
- return Promise.resolve();
19015
- }
19016
- });
19017
- }
19018
-
19019
- if (container.active.$containers && container.active.$containers.length) {
19020
- for (var i = 0; i < container.active.$containers.length; ++i) {
19021
- reuseComponentFunc(container.active.$containers[i]);
19022
- }
19023
- }
19024
-
19025
- return p.then(function () { if (!container.active) return Promise.resolve(null); container.active.$forceUpdate(); return Promise.resolve(container.active) });
19026
-
19027
- }
19028
- return Promise.resolve(reuseComponentFunc(self));
19029
- }
19030
-
19031
- var _result;
19032
- var retryLeft = 20;
19033
- var _lastMountError = null;
19034
- var buildRetryPromise = function () {
19035
- return new Promise(function (res, rej) {
19036
- var containerEl = document.querySelector(self.selector);
19037
- if (!containerEl) {
19038
- if (--retryLeft > 0) {
19039
- return res(sleep(50).then(function () {
19040
- return buildRetryPromise();
19041
- }));
19042
- } else {
19043
- var msg = 'Mount component to ' + self.selector + ' failed: container element not found in DOM after retries. URL: ' + url;
19044
- console.error('[PomeUI]', msg);
19045
- return rej(new Error(msg));
19046
- }
19047
- }
19048
-
19049
- var active;
19050
- try {
19051
- active = _result.mount(self.selector);
19052
- } catch (mountError) {
19053
- _lastMountError = mountError;
19054
- console.error('[PomeUI] Mount component to ' + self.selector + ' threw an error. URL: ' + url, mountError);
19055
- return rej(new Error('Mount component to ' + self.selector + ' failed: ' + (mountError.message || mountError) + '. URL: ' + url));
19056
- }
19057
-
19058
- if (active) {
19059
- self.active = active;
19060
- return res(active);
19061
- }
19062
-
19063
- if (--retryLeft > 0) {
19064
- return res(sleep(50).then(function () {
19065
- return buildRetryPromise();
19066
- }));
19067
- } else {
19068
- var detail = 'mount() returned ' + (active === null ? 'null' : (active === undefined ? 'undefined' : String(active)));
19069
- if (_lastMountError) {
19070
- detail += '; last error: ' + (_lastMountError.message || _lastMountError);
19071
- }
19072
- var msg = 'Mount component to ' + self.selector + ' failed: ' + detail + '. URL: ' + url;
19073
- console.error('[PomeUI]', msg);
19074
- console.error('[PomeUI] Diagnostics:', {
19075
- selector: self.selector,
19076
- url: url,
19077
- containerElement: containerEl,
19078
- containerInnerHTML: containerEl ? containerEl.innerHTML.substring(0, 200) : '(N/A)',
19079
- appResult: _result,
19080
- mobile: mobile
19081
- });
19082
- return rej(new Error(msg));
19083
- }
19084
- });
19085
- };
19086
-
19087
- return _buildApp(url, params, mobile, currentProxy).then(function (result) {
19088
- _result = result;
19089
- return buildRetryPromise();
19090
- }).catch(function (err) {
19091
- console.error('[PomeUI] Failed to build or mount component. URL: ' + url + ', Selector: ' + self.selector, err);
19092
- return Promise.reject(err);
19093
- });
19094
- });
19095
- },
19096
- close: async function (recurse = true) {
19097
- async function liftClose(container) {
19098
- if (container.active && container.active.$) {
19099
- if (recurse) {
19100
- for (var i = 0; i < container.active.$containers.length; ++i) {
19101
- liftClose(container.active.$containers[i]);
19102
- }
19103
- }
19104
-
19105
- if (container.active.$delayClose) {
19106
- try {
19107
- if (container.active.$el) {
19108
- container.active.$el.classList?.add('_pome-ui-closing');
19109
- }
19110
- } catch (ex) {
19111
- console.warn(ex);
19112
- }
19113
- console.log(`sleeping ${container.active.$delayClose}ms...`);
19114
- await sleep(container.active.$delayClose);
19115
- }
19116
-
19117
- try {
19118
- container.active.$.appContext.app.unmount();
19119
- } catch (ex) {
19120
- console.warn(ex);
19121
- }
19122
- container.active = null;
19123
- }
19124
- }
19125
-
19126
- await liftClose(this);
19127
- },
19128
- active: null
19129
- };
19130
- containers.push(container);
19131
- }
19132
- return container;
19133
- };
19134
- };
19135
-
19136
- function Root(options, el, layout) {
19137
- options = options || {};
19138
- _hookSetup(options, function (instance) {
19139
- instance.$parent = parent || _findRoot(instance);
19140
- instance.$root = _findRoot(instance) || parent;
19141
- instance.$onUpdating = options.onUpdating;
19142
- if (layout) {
19143
- instance.$layout = layout;
19144
- instance.$view = layout;
19145
- }
19146
- _attachContainer(instance);
19147
- });
19148
-
19149
- return _resolveModules(options.modules, layout).then(function () {
19150
- var _app;
19151
-
19152
- return _loadComponents(options.components || [], layout)
19153
- .then(function (components) {
19154
- // Inject layout skeleton overlay now that component registry is populated.
19155
- if (options._pomeLayoutSkeleton) {
19156
- var ls = options._pomeLayoutSkeleton;
19157
- var skHtml = ls.skeletonOverride
19158
- ? ls.skeletonOverride
19159
- : (function () {
19160
- var html = _generateSkeletonHtml(ls.skeletonBody);
19161
- // Post-process: remove empty top-level nodes (modals etc.),
19162
- // set flex:1 on the main content area next to the sidebar.
19163
- var tmp = document.createElement('div');
19164
- tmp.innerHTML = html;
19165
- var topChildren = Array.from(tmp.children);
19166
- var sidebarIdx = -1;
19167
- for (var ci = 0; ci < topChildren.length; ci++) {
19168
- var ch = topChildren[ci];
19169
- if (!ch.innerHTML.trim()) {
19170
- tmp.removeChild(ch);
19171
- topChildren = Array.from(tmp.children);
19172
- ci--;
19173
- continue;
19174
- }
19175
- if (sidebarIdx < 0 && /\bwidth\s*:/.test(ch.getAttribute('style') || '')) {
19176
- sidebarIdx = ci;
19177
- } else if (sidebarIdx >= 0 && ci === sidebarIdx + 1) {
19178
- ch.style.flex = '1';
19179
- ch.style.minWidth = '0';
19180
- ch.style.overflow = 'hidden';
19181
- }
19182
- }
19183
- return tmp.innerHTML;
19184
- })();
19185
- var appEl = document.querySelector(ls.appId);
19186
- if (appEl) {
19187
- var skDiv = document.createElement('div');
19188
- skDiv.setAttribute('v-if', 'pomeSkeletonLoading || pomeSkeletonCloaked');
19189
- skDiv.className = '_pome-skeleton _pome-layout-skeleton ' + ls.bodyClass;
19190
- if (ls.overlayStyle) skDiv.setAttribute('style', ls.overlayStyle);
19191
- skDiv.innerHTML = skHtml;
19192
- appEl.insertBefore(skDiv, appEl.firstChild);
19193
- }
19194
- delete options._pomeLayoutSkeleton;
19195
- }
19196
- var app = Vue.createApp(options || {});
19197
- for (var i = 0; i < components.length; ++i) {
19198
- var com = components[i];
19199
- app.component(com.name, com.options);
19200
- }
19201
-
19202
- _app = app;
19203
- return _loadDirectives(options.directives || [], layout);
19204
- })
19205
- .then(function (directives) {
19206
- for (var i = 0; i < directives.length; ++i) {
19207
- var dir = directives[i];
19208
- app.directive(dir.name, dir.options);
19209
- }
19210
-
19211
- _root = _app.mount(el);
19212
- _root.$.proxy = _root;
19213
- var _mountEl = document.querySelector(el);
19214
- if (_mountEl) {
19215
- _mountEl.classList.remove('_pome-vue-cloak');
19216
- }
19217
- });
19218
- });
19219
- }
19220
-
19221
- function mount() {
19222
- function parseHref(el) {
19223
- if (!el) {
19224
- return null;
19225
- }
19226
-
19227
- if (!el.getAttribute) {
19228
- return null;
19229
- }
19230
-
19231
- var target = el.getAttribute('target') || '_self';
19232
- var staticAttribute = el.getAttribute('static-link') || el.getAttribute('v-static') || el.getAttribute('pomelo-static');
19233
-
19234
- if (staticAttribute == null
19235
- && target.toLowerCase() == '_self'
19236
- && el.tagName.toLowerCase() == "a") {
19237
- return el.getAttribute('href');
19238
- }
19239
-
19240
- return parseHref(el.parentNode);
19241
- }
19242
-
19243
- window.addEventListener('click', function (e) {
19244
- if (!e) return;
19245
- var href = parseHref(e.target);
19246
- if (href) {
19247
- if (e.ctrlKey || e.metaKey) {
19248
- return;
19249
- }
19250
- exports.redirect(href);
19251
- e.preventDefault();
19252
- return;
19253
- }
19254
- });
19255
-
19256
- window.onpopstate = function () {
19257
- UpdateLayout();
19258
- };
19259
-
19260
- return UpdateLayout();
19261
- }
19262
-
19263
- function UseConfig(options) {
19264
- _combineObject(options, _options);
19265
- }
19266
-
19267
- function MapRoute(rule, view) {
19268
- if (!exports._rules) {
19269
- exports._rules = {};
19270
- }
19271
-
19272
- exports._rules[rule] = view;
19273
- }
19274
-
19275
- function ForceUpdate(proxy = exports.root()) {
19276
- if (!proxy) return;
19277
- proxy.$forceUpdate();
19278
- if (proxy.$containers) {
19279
- for (var i = 0; i < proxy.$containers.length; ++i) {
19280
- if (proxy.$containers[i].active) {
19281
- ForceUpdate(proxy.$containers[i].active);
19282
- }
19283
- }
19284
- }
19285
- }
19286
-
19287
- function MatchRoute() {
19288
- function replaceAll(str, s1, s2) {
19289
- return str.replace(new RegExp(s1, "g"), s2);
19290
- };
19291
-
19292
- function matchAll(str) {
19293
- var ret = [];
19294
- if (!str) {
19295
- return ret;
19296
- }
19297
-
19298
- var currentBrace = -1;
19299
- var parenthesis = 0;
19300
- for (var i = 0; i < str.length; ++i) {
19301
- if (str[i] == '{' && !parenthesis) {
19302
- currentBrace = i;
19303
- parenthesis = 0;
19304
- } else if (str[i] == '(') {
19305
- ++parenthesis;
19306
- } else if (str[i] == ')') {
19307
- --parenthesis;
19308
- } else if (str[i] == '}' && !parenthesis) {
19309
- ret.push(str.substring(currentBrace, i + 1));
19310
- }
19311
- }
19312
-
19313
- return ret;
19314
- }
19315
-
19316
- function unwrapBrackets(src) {
19317
- if (src[0] === '{') {
19318
- return src.substr(1, src.length - 2);
19319
- } else {
19320
- return src;
19321
- }
19322
- }
19323
-
19324
- function regExpEscape(str) {
19325
- return str.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
19326
- }
19327
-
19328
- function getRegExpPatterns(str) {
19329
- var cnt = 0;
19330
- if (str) {
19331
- for (var i = 0; i < str.length; ++i) {
19332
- if (str[i] == '(') {
19333
- ++cnt;
19334
- }
19335
- if (str[i] == '?' && i > 0 && str[i - 1] == '(') {
19336
- --cnt;
19337
- }
19338
- }
19339
- }
19340
- return cnt;
19341
- }
19342
-
19343
- function getSanitizedHash() {
19344
- var hash = window.location.hash;
19345
- var idx = hash.indexOf('?');
19346
- if (idx == -1) {
19347
- return hash;
19348
- }
19349
- return hash.substr(0, idx);
19350
- }
19351
-
19352
- var keys = Object.getOwnPropertyNames(exports._rules);
19353
- for (var i = 0; i < keys.length; ++i) {
19354
- var rule = keys[i];
19355
- var isHash = rule[0] == '#';
19356
- var view = exports._rules[keys[i]];
19357
- var matches = matchAll(rule);
19358
- var params = [];
19359
- var patterns = [];
19360
- for (var j = 0; j < matches.length; ++j) {
19361
- var param = matches[j];
19362
- var k = unwrapBrackets(param);
19363
- regex = '([^/]+)';
19364
- if (k[0] == '*') {
19365
- regex = '(.*)';
19366
- k = k.substr(1);
19367
- }
19368
- if (k.indexOf('=') > 0) {
19369
- var value = k.substr(k.indexOf('=') + 1);
19370
- regex = `(${regExpEscape(value)})`;
19371
- params.push(k.substr(0, k.indexOf('=')));
19372
- } else if (param.indexOf(':') > 0) {
19373
- regex = param.substr(param.indexOf(':') + 1)
19374
- regex = regex.substr(0, regex.length - 1);
19375
- params.push(k.substr(0, k.indexOf(':')));
19376
- } else {
19377
- params.push(k);
19378
- }
19379
- patterns.push(getRegExpPatterns(regex));
19380
- rule = _replace(rule, param, regex);
19381
- }
19382
-
19383
- var parsedReg = new RegExp('^' + rule + '$');
19384
- var matches = parsedReg.exec(isHash ? getSanitizedHash() || '#' : window.location.pathname);
19385
- if (matches) {
19386
- var ret = {
19387
- view: view,
19388
- params: []
19389
- };
19390
- var _matches = matches;
19391
- matches = [];
19392
- var index = 0;
19393
- for (var j = 1; j < _matches.length; ++j) {
19394
- matches.push(_matches[j]);
19395
- for (var k = 0; k < patterns[index] - 1; ++k) {
19396
- ++j;
19397
- }
19398
- ++index;
19399
- }
19400
- var values = matches.map(function (x) { return decodeURIComponent(x); });
19401
- for (var j = 0; j < params.length; ++j) {
19402
- ret.params.push({ key: params[j], value: values[j] });
19403
- }
19404
- return ret;
19405
- }
19406
- }
19407
-
19408
- return null;
19409
- }
19410
-
19411
- function _fillObjectField(param, value, dest) {
19412
- if (!dest) {
19413
- return;
19414
- }
19415
-
19416
- var splited = param.split('.');
19417
- for (var i = 0; i < splited.length - 1; ++i) {
19418
- if (!dest[splited[i]]) {
19419
- dest[splited[i]] = {}
19420
- }
19421
- dest = dest[splited[i]];
19422
- }
19423
- dest[splited[splited.length - 1]] = value;
19424
- }
19425
- function _applyLayoutHtml(layout) {
19426
- return _httpGet(layout + (_options.mobile() ? '.m.html' : '.html')).then(function (layoutHtml) {
19427
- var htmlBeginTagIndex = layoutHtml.indexOf('<html');
19428
- var htmlBeginTagIndex2 = layoutHtml.indexOf('>', htmlBeginTagIndex);
19429
- layoutHtml = layoutHtml.substr(htmlBeginTagIndex2 + 1);
19430
- var htmlEndTagIndex = layoutHtml.lastIndexOf('</html>');
19431
- layoutHtml = layoutHtml.substr(0, htmlEndTagIndex);
19432
- layoutHtml = _patchTemplate(layout, layoutHtml);
19433
- document.querySelector('html').innerHTML = layoutHtml;
19434
-
19435
- var ticks = new Date().getTime();
19436
- var appId = 'pomelo-' + ticks;
19437
- _ensureVueCloakStyle();
19438
- document.querySelector('body').innerHTML = '<div id="' + appId + '" class="_pome-vue-cloak">' + document.querySelector('body').innerHTML + '</div>';
19439
-
19440
- return Promise.resolve(appId);
19441
- })
19442
- }
19443
-
19444
- function generateParametersFromRoute(params = {}) {
19445
- var route = null;
19446
- route = MatchRoute();
19447
- if (route == null) {
19448
- try {
19449
- _options.onNotFound(window.location.pathname + window.location.search);
19450
- return;
19451
- } catch (ex) {
19452
- throw "No available route found.";
19453
- }
19454
- }
19455
-
19456
- for (var i = 0; i < route.params.length; ++i) {
19457
- var param = route.params[i];
19458
- _fillObjectField(param.key, param.value, params);
19459
- }
19460
-
19461
- return params;
19462
- }
19463
-
19464
- function parseMacroPath(viewName, href) {
19465
- if (!href) {
19466
- href = '';
19467
- }
19468
-
19469
- if (href.indexOf('@') < 0) {
19470
- return href;
19471
- }
19472
-
19473
- var containingFolder = '/';
19474
- var folderIndex = viewName.lastIndexOf('/');
19475
- if (folderIndex >= 0) {
19476
- containingFolder = viewName.substr(0, folderIndex);
19477
- }
19478
-
19479
- href = href.replaceAll('@(view)', viewName)
19480
- .replaceAll('@(js)', viewName + '.js')
19481
- .replaceAll('@(html)', viewName + '.html')
19482
- .replaceAll('@(mobileHtml)', viewName + '.m.html')
19483
- .replaceAll('@(css)', viewName + '.css')
19484
- .replaceAll('@(mobileCss)', viewName + '.m.css')
19485
- .replaceAll('@(less)', viewName + '.less')
19486
- .replaceAll('@(mobileLess)', viewName + '.m.less')
19487
- .replaceAll('@(mobileSass)', viewName + '.m.sass')
19488
- .replaceAll('@(mobileScss)', viewName + '.m.scss')
19489
- .replaceAll('@(containingFolder)', containingFolder);
19490
-
19491
- if (href.length && href[0] != '/' && href.indexOf('http') == -1) {
19492
- href = getContainingFolder(viewName) + href;
19493
- }
19494
-
19495
- return href;
19496
- }
19497
-
19498
- function appendCssReference(view, style) {
19499
- if (typeof style == 'boolean') {
19500
- var href = view + '.css';
19501
- if (_options.version) {
19502
- href += '?v=' + _options.version;
19503
- }
19504
- internalAppendCssReference(view, href);
19505
- } else if (typeof style == 'string') {
19506
- var href = parseMacroPath(view, style);
19507
- href = resolveRelativePath(href, getContainingFolder(view));
19508
- if (_options.version) {
19509
- if (href.indexOf('>') < 0) {
19510
- href += '?v=' + _options.version;
19511
- } else {
19512
- href += '&v=' + _options.version;
19513
- }
19514
- }
19515
- internalAppendCssReference(view, href);
19516
- } else if (style instanceof Array) {
19517
- for (var i = 0; i < style.length; ++i) {
19518
- if (typeof style[i] != 'string') {
19519
- continue;
19520
- }
19521
- var href = parseMacroPath(view, style[i]);
19522
- href = resolveRelativePath(href, getContainingFolder(view));
19523
- if (_options.version) {
19524
- if (href.indexOf('>') < 0) {
19525
- href += '?v=' + _options.version;
19526
- } else {
19527
- href += '&v=' + _options.version;
19528
- }
19529
- }
19530
- internalAppendCssReference(view, href);
19531
- }
19532
- } else {
19533
- throw 'style type not supported'
19534
- }
19535
- }
19536
-
19537
- function getContainingFolder(absolutePath) {
19538
- if (!absolutePath) {
19539
- console.warn('getContainingFolder: absolutePath is invalid');
19540
- }
19541
-
19542
- var slashIndex = absolutePath.lastIndexOf('/');
19543
- if (slashIndex < 0) {
19544
- return '/';
19545
- }
19546
-
19547
- return absolutePath.substr(0, slashIndex) + '/';
19548
- }
19549
-
19550
- function internalAppendCssReference(viewName, href) {
19551
- if (document.querySelectorAll('link[data-style="' + viewName + '"][href="' + href + '"]').length) {
19552
- return;
19553
- }
19554
-
19555
- var link = document.createElement('link');
19556
- link.rel = 'stylesheet';
19557
- link.type = 'text/' + getStyleSheetType(href);
19558
- link.setAttribute('data-style', viewName)
19559
- link.href = href;
19560
- try {
19561
- document.querySelector('head').appendChild(link);
19562
- } catch (ex) { }
19563
- }
19564
-
19565
- function internalAppendCssReferenceAsync(viewName, href) {
19566
- if (document.querySelectorAll('link[data-style="' + viewName + '"][href="' + href + '"]').length) {
19567
- return Promise.resolve();
19568
- }
19569
-
19570
- return new Promise(function (resolve) {
19571
- var link = document.createElement('link');
19572
- link.rel = 'stylesheet';
19573
- link.type = 'text/' + getStyleSheetType(href);
19574
- link.setAttribute('data-style', viewName);
19575
- function onReady() {
19576
- requestAnimationFrame(function () {
19577
- resolve();
19578
- });
19579
- }
19580
- link.onload = onReady;
19581
- link.onerror = onReady;
19582
- link.href = href;
19583
- try {
19584
- document.querySelector('head').appendChild(link);
19585
- } catch (ex) {
19586
- resolve();
19587
- }
19588
- });
19589
- }
19590
-
19591
- function appendCssReferenceAsync(view, style) {
19592
- var promises = [];
19593
- if (typeof style == 'boolean') {
19594
- var href = view + '.css';
19595
- if (_options.version) {
19596
- href += '?v=' + _options.version;
19597
- }
19598
- promises.push(internalAppendCssReferenceAsync(view, href));
19599
- } else if (typeof style == 'string') {
19600
- var href = parseMacroPath(view, style);
19601
- href = resolveRelativePath(href, getContainingFolder(view));
19602
- if (_options.version) {
19603
- if (href.indexOf('>') < 0) {
19604
- href += '?v=' + _options.version;
19605
- } else {
19606
- href += '&v=' + _options.version;
19607
- }
19608
- }
19609
- promises.push(internalAppendCssReferenceAsync(view, href));
19610
- } else if (style instanceof Array) {
19611
- for (var i = 0; i < style.length; ++i) {
19612
- if (typeof style[i] != 'string') {
19613
- continue;
19614
- }
19615
- var href = parseMacroPath(view, style[i]);
19616
- href = resolveRelativePath(href, getContainingFolder(view));
19617
- if (_options.version) {
19618
- if (href.indexOf('>') < 0) {
19619
- href += '?v=' + _options.version;
19620
- } else {
19621
- href += '&v=' + _options.version;
19622
- }
19623
- }
19624
- promises.push(internalAppendCssReferenceAsync(view, href));
19625
- }
19626
- }
19627
- return Promise.all(promises);
19628
- }
19629
-
19630
- function getStyleSheetType(styleSheetUrl) {
19631
- var questionMarkIndex = styleSheetUrl.lastIndexOf('?');
19632
- if (questionMarkIndex >= 0) {
19633
- styleSheetUrl = styleSheetUrl.substr(0, questionMarkIndex);
19634
- }
19635
-
19636
- var dotIndex = styleSheetUrl.lastIndexOf('.');
19637
- if (dotIndex < 0) {
19638
- return null;
19639
- }
19640
-
19641
- return styleSheetUrl.substr(dotIndex + 1).toLowerCase();
19642
- }
19643
-
19644
- function removeCssReference(view) {
19645
- if (!_options.removeStyleWhenUnmount) {
19646
- return;
19647
- }
19648
-
19649
- var dom = document.querySelectorAll('link[data-style="' + view + '"]');
19650
- if (dom && dom.length) {
19651
- for (var i = 0; i < dom.length; ++i) {
19652
- dom[i].remove();
19653
- }
19654
- }
19655
- }
19656
-
19657
- function hookMountedAndUnmounted(options, view) {
19658
- if (!options) {
19659
- return;
19660
- }
19661
-
19662
- if (!options.mounted) {
19663
- options.mounted = function () { };
19664
- }
19665
-
19666
- if (!options.unmounted) {
19667
- options.unmounted = function () { };
19668
- }
19669
-
19670
- if (!options.created) {
19671
- options.created = function () { };
19672
- }
19673
-
19674
- if (options.style || options.skeleton) {
19675
- var originalCreated = options.created;
19676
- options.created = function () {
19677
- if (options.style) {
19678
- if (!_css[view]) {
19679
- _css[view] = 0;
19680
- }
19681
- if (_css[view] == 0) {
19682
- if (_options.preloadCss) {
19683
- this._cssLoadPromise = appendCssReferenceAsync(view, options.style);
19684
- } else {
19685
- appendCssReference(view, options.style);
19686
- }
19687
- }
19688
- ++_css[view];
19689
- }
19690
-
19691
- this.createdPromise = Promise.resolve();
19692
- var ret = originalCreated.call(this);
19693
- if (ret instanceof Promise) {
19694
- this.createdPromise = ret;
19695
- if (options.skeleton) {
19696
- var self = this;
19697
- var skeletonShowing = false;
19698
- var resolved = false;
19699
- // Only activate the skeleton if the promise is still pending
19700
- // after skeletonDelay ms. If it resolves faster, skip the
19701
- // skeleton entirely to avoid a flash.
19702
- var skeletonDelay = typeof options.skeletonDelay === 'number'
19703
- ? options.skeletonDelay : 1000;
19704
- var skeletonTimer = setTimeout(function () {
19705
- if (resolved) return;
19706
- skeletonShowing = true;
19707
- self.pomeSkeletonCloaked = false;
19708
- self.pomeSkeletonLoading = true;
19709
- // Skeleton is now visible. If delayOpen is also set, kick
19710
- // off its animation so it's primed when skeleton disappears.
19711
- if (options.delayOpen) {
19712
- self.$nextTick(function () {
19713
- requestAnimationFrame(function () {
19714
- requestAnimationFrame(function () {
19715
- self.pomeDelayOpening = false;
19716
- });
19717
- });
19718
- setTimeout(function () {
19719
- self.pomeDelayOpened = false;
19720
- }, options.delayOpen);
19721
- });
19722
- }
19723
- }, skeletonDelay);
19724
- ret.then(function () {
19725
- resolved = true;
19726
- clearTimeout(skeletonTimer);
19727
- self.pomeSkeletonCloaked = false;
19728
- self.pomeSkeletonLoading = false;
19729
- // Fast path: resolved before skeleton appeared �?still need
19730
- // to run the delayOpen animation now.
19731
- if (!skeletonShowing && options.delayOpen) {
19732
- self.$nextTick(function () {
19733
- requestAnimationFrame(function () {
19734
- requestAnimationFrame(function () {
19735
- self.pomeDelayOpening = false;
19736
- });
19737
- });
19738
- setTimeout(function () {
19739
- self.pomeDelayOpened = false;
19740
- }, options.delayOpen);
19741
- });
19742
- }
19743
- }).catch(function (err) {
19744
- resolved = true;
19745
- clearTimeout(skeletonTimer);
19746
- self.pomeSkeletonCloaked = false;
19747
- self.pomeSkeletonLoading = false;
19748
- console.error('[SKELETON] created Promise REJECTED:', err);
19749
- });
19750
- }
19751
- } else if (options.skeleton) {
19752
- // Sync created �?nothing to wait for, ensure skeleton is off.
19753
- this.pomeSkeletonCloaked = false;
19754
- this.pomeSkeletonLoading = false;
19755
- // created() didn't return a Promise, so the skeleton
19756
- // timer / promise path above won't run. We still need
19757
- // to kick off the delayOpen animation that was deferred
19758
- // under the assumption that skeleton would manage it.
19759
- if (options.delayOpen) {
19760
- var self = this;
19761
- self.$nextTick(function () {
19762
- requestAnimationFrame(function () {
19763
- requestAnimationFrame(function () {
19764
- self.pomeDelayOpening = false;
19765
- });
19766
- });
19767
- setTimeout(function () {
19768
- self.pomeDelayOpened = false;
19769
- }, options.delayOpen);
19770
- });
19771
- }
19772
- }
19773
-
19774
- return ret;
19775
- };
19776
- }
19777
-
19778
- var originalMounted = options.mounted;
19779
- options.mounted = function () {
19780
- // CSS cloak: hide element until CSS is fully loaded
19781
- if (_options.preloadCss && this._cssLoadPromise) {
19782
- _ensureCssCloakStyle();
19783
- var el = this.$el;
19784
- if (el && el.nodeType === 1) {
19785
- el.classList.add('_pome-css-cloak');
19786
- this._cssLoadPromise.then(function () {
19787
- el.classList.remove('_pome-css-cloak');
19788
- });
19789
- }
19790
- }
19791
-
19792
- // Remove opening class if needed
19793
- if (options.delayOpen && !options.skeleton) {
19794
- var self = this;
19795
- var delayOpenFunc = function () {
19796
- requestAnimationFrame(function () {
19797
- requestAnimationFrame(function () {
19798
- if (!self.$el || !self.$el.parentNode) return;
19799
- var doms = self.$el.parentNode.querySelectorAll('._pome-ui-opening');
19800
- for (var i = 0; i < doms.length; ++i) {
19801
- doms[i].classList.remove('_pome-ui-opening');
19802
- }
19803
- });
19804
- });
19805
-
19806
- setTimeout(function () {
19807
- if (!self.$el || !self.$el.parentNode) return;
19808
- var doms = self.$el.parentNode.querySelectorAll('._pome-ui-opened');
19809
- for (var i = 0; i < doms.length; ++i) {
19810
- doms[i].classList.remove('_pome-ui-opened');
19811
- }
19812
- }, options.delayOpen);
19813
- };
19814
-
19815
- (self.createdPromise || Promise.resolve()).then(function () {
19816
- delayOpenFunc();
19817
- });
19818
- }
19819
-
19820
- return originalMounted.call(this);
19821
- };
19822
-
19823
- var originalUnmounted = options.unmounted;
19824
- options.unmounted = function () {
19825
- if (options.style) {
19826
- if (!_css[view]) {
19827
- return originalUnmounted.call(this);
19828
- }
19829
-
19830
- --_css[view];
19831
- if (_css[view] <= 0) {
19832
- removeCssReference(view);
19833
- delete _css[view];
19834
- }
19835
- }
19836
- return originalUnmounted.call(this);
19837
- };
19838
- }
19839
-
19840
- function pomeUiPassTitle(arr) {
19841
- if (arr) {
19842
- this.pomeUiSubTitles = arr;
19843
- }
19844
-
19845
- var parents = JSON.parse(JSON.stringify(this.pomeUiSubTitles));
19846
- if (this.title) {
19847
- parents.push(this.title);
19848
- }
19849
-
19850
- var p = this.$parent;
19851
- while (p && p != window && !p.pomeUiPassTitle) {
19852
- p = p.$parent;
19853
- }
19854
-
19855
- if (p && p != window && p.pomeUiPassTitle) {
19856
- p.pomeUiPassTitle(parents);
19857
- } else {
19858
- document.querySelector('title').innerHTML = _options.generateTitle(parents);
19859
- }
19860
- }
19861
-
19862
- function UpdateLayout() {
19863
- var mobile = _options.mobile();
19864
- var params = {};
19865
- var route = null;
19866
- var layout = _options.layout;
19867
-
19868
- route = MatchRoute();
19869
- params = generateParametersFromRoute();
19870
-
19871
- var _def;
19872
- var viewName = route.view + (_options.mobile() ? '.m' : '');
19873
- return _httpGet(route.view + '.js').then(function (def) {
19874
- _def = def;
19875
- var modules = null;
19876
- var _opt;
19877
- var Page = function (options) {
19878
- _opt = options;
19879
- layout = options.layout || layout;
19880
- modules = options.modules;
19881
- };
19882
-
19883
- var require = _createRequire(route.view);
19884
- def = eval(def + '\r\n//# sourceURL=' + route.view + '.js');
19885
- hookMountedAndUnmounted(_opt, viewName);
19886
- return _resolveModules(modules, viewName);
19887
- }).then(function () {
19888
- if (exports.root() && exports.root().$layout) {
19889
- if (exports.root().$layout === layout) {
19890
- _parseQueryString(params);
19891
- var fields = Object.getOwnPropertyNames(params);
19892
- for (var i = 0; i < fields.length; ++i) {
19893
- var val = params[fields[i]];
19894
- exports.root()[fields[i]] = val;
19895
- }
19896
-
19897
- return exports.root().$containers[0].open(route.view, params).then(function () {
19898
- var promise = Promise.resolve();
19899
- if (typeof exports.root().$.$onUpdating == 'function') {
19900
- var result = exports.root().$.$onUpdating.call(exports.root());
19901
- if (result instanceof Promise) {
19902
- promise = promise.then(() => result);
19903
- }
19904
- }
19905
- return promise;
19906
- });
19907
- }
19908
-
19909
- exports.root().$.appContext.app.unmount();
19910
- }
19911
-
19912
- if (layout) {
19913
- var layoutName = layout + (mobile ? '.m' : '');
19914
- var _layoutHtml;
19915
- var _layoutSkeletonFileHtml; // hoisted so LayoutNext closure can access it
19916
- // Load layout .html, .js and optional .skeleton.html all in parallel
19917
- return Promise.all([
19918
- _httpGet(layoutName + '.html'),
19919
- _httpGet(layout + '.js'),
19920
- _httpGetSkeletonFile(layoutName + '.skeleton.html')
19921
- ]).then(function (layoutResults) {
19922
- _layoutHtml = layoutResults[0];
19923
- var js = layoutResults[1];
19924
- _layoutSkeletonFileHtml = layoutResults[2]; // null when absent
19925
- return js;
19926
- }).then(function (js) {
19927
- var _opt = null;
19928
- var Layout = function (options) {
19929
- _opt = options;
19930
- };
19931
- var LayoutNext = function (options) {
19932
- _hookSetup(options);
19933
-
19934
- if (!_opt.template) {
19935
- _opt.template = _sanitizeTemplate(_layoutHtml);
19936
- }
19937
- _patchComponent(layout, _opt);
19938
- _layoutHtml = _opt.template;
19939
- var htmlBeginTagIndex = _layoutHtml.indexOf('<html');
19940
- var htmlBeginTagIndex2 = _layoutHtml.indexOf('>', htmlBeginTagIndex);
19941
- _layoutHtml = _layoutHtml.substr(htmlBeginTagIndex2 + 1);
19942
- var htmlEndTagIndex = _layoutHtml.lastIndexOf('</html>');
19943
- _layoutHtml = _layoutHtml.substr(0, htmlEndTagIndex);
19944
- document.querySelector('html').innerHTML = _layoutHtml;
19945
- _hookData(options, params);
19946
-
19947
- var ticks = new Date().getTime();
19948
- var appId = 'pomelo-' + ticks;
19949
- var containerId = 'container-' + ticks;
19950
- var bodyHtml = document.querySelector('body').innerHTML;
19951
- var renderBodyRegex = /<render-body\s*(?:\/\s*)?>(?:<\/render-body\s*>)?/i;
19952
- var body;
19953
- if (renderBodyRegex.test(bodyHtml)) {
19954
- body = bodyHtml.replace(renderBodyRegex, '<div id="' + containerId + '"></div>');
19955
- } else {
19956
- console.error('[PomeUI] <render-body> tag not found in layout body innerHTML. The container element will not be created.');
19957
- console.error('[PomeUI] Body innerHTML (first 500 chars):', bodyHtml.substring(0, 500));
19958
- body = bodyHtml;
19959
- }
19960
- // Layout skeleton: defer generation to Root→_loadComponents so the
19961
- // component skeleton registry is fully populated before we generate HTML.
19962
- if (options.skeleton) {
19963
- _ensureSkeletonStyle();
19964
- var bodyEl = document.querySelector('body');
19965
- var bodyClass = bodyEl.getAttribute('class') || '';
19966
- var bodyInlineStyle = bodyEl.getAttribute('style') || '';
19967
- var bodyComputed = window.getComputedStyle(bodyEl);
19968
- var overlayStyle = bodyInlineStyle;
19969
- if (bodyComputed.display && bodyComputed.display.indexOf('flex') >= 0) {
19970
- if (overlayStyle) overlayStyle += ';';
19971
- overlayStyle += 'display:' + bodyComputed.display
19972
- + ';flex-direction:' + bodyComputed.flexDirection
19973
- + ';align-items:' + bodyComputed.alignItems;
19974
- } else {
19975
- if (overlayStyle) overlayStyle += ';';
19976
- overlayStyle += 'display:flex;flex-direction:row;align-items:stretch';
19977
- }
19978
- var skeletonBody = body.replace('<div id="' + containerId + '"></div>', '<div style="flex:1;min-width:0"></div>');
19979
- // Store pending data; Root will inject the overlay div after
19980
- // _loadComponents so registered component skeletons are available.
19981
- options._pomeLayoutSkeleton = {
19982
- appId: '#' + appId,
19983
- bodyClass: bodyClass,
19984
- overlayStyle: overlayStyle,
19985
- skeletonBody: skeletonBody,
19986
- // Priority: .skeleton.html file > inline string in JS
19987
- skeletonOverride: _layoutSkeletonFileHtml
19988
- || (typeof options.skeleton === 'string' ? options.skeleton : null)
19989
- };
19990
- }
19991
- _ensureVueCloakStyle();
19992
- document.querySelector('body').innerHTML = '<div id="' + appId + '" class="_pome-vue-cloak">' + body + '</div>';
19993
- if (!document.getElementById(containerId)) {
19994
- console.error('[PomeUI] Container element #' + containerId + ' not found in DOM immediately after setting body innerHTML. The <render-body> replacement likely failed.');
19995
- }
19996
- options.template = null;
19997
- // Hook mounted
19998
- if (!options.mounted) {
19999
- options.mounted = function () { };
20000
- }
20001
-
20002
- mountedFunc = options.mounted;
20003
- options.mounted = function () {
20004
- var containerEl = document.getElementById(containerId);
20005
- if (!containerEl) {
20006
- console.error('[PomeUI] Container element #' + containerId + ' not found in DOM at mounted hook. Vue may have removed it during template compilation/render.');
20007
- console.error('[PomeUI] Mount element innerHTML (first 500 chars):', document.querySelector('#' + appId)?.innerHTML?.substring(0, 500));
20008
- }
20009
- var container = this.$container('#' + containerId);
20010
- container.open(route.view, params);
20011
- return mountedFunc.call(this);
20012
- };
20013
-
20014
- Root(options, '#' + appId, layout);
20015
- };
20016
-
20017
- var require = _createRequire(layout);
20018
- eval(js + '\r\n//# sourceURL=' + layout + ".js");
20019
- hookMountedAndUnmounted(_opt, layoutName);
20020
- // Resolve template option for Layout (could be .html path or inline HTML)
20021
- var layoutTemplatePromise = _opt.template
20022
- ? _resolveTemplateOption(_opt.template)
20023
- : Promise.resolve(null);
20024
- return Promise.all([_resolveModules(_opt.modules, layout), layoutTemplatePromise]).then(function (layoutResolveResults) {
20025
- var resolvedLayoutTemplate = layoutResolveResults[1];
20026
- if (resolvedLayoutTemplate) {
20027
- _opt.template = resolvedLayoutTemplate;
20028
- }
20029
- LayoutNext(_opt);
20030
- return Promise.resolve();
20031
- });
20032
- });
20033
- } else {
20034
- var viewName = route.view + (_options.mobile() ? '.m' : '');
20035
- return _applyLayoutHtml(route.view).then(function (appId) {
20036
- var _opt = null;
20037
- var components = null;
20038
- var Page = function (options) {
20039
- _opt = options;
20040
- };
20041
- var PageNext = function (options) {
20042
- modules = options.modules;
20043
- components = options.components || [];
20044
- Root(options, '#' + appId, route.view);
20045
- };
20046
-
20047
- var require = _createRequire(route.view);
20048
- eval(_def + '\r\n//# sourceURL=' + route.view + '.js');
20049
-
20050
- if (!_opt) {
20051
- _opt = {};
20052
- }
20053
-
20054
- _hookData(_opt, params);
20055
- hookMountedAndUnmounted(_opt, viewName);
20056
- _patchComponent(viewName, _opt);
20057
- return _resolveModules(_opt.modules, viewName).then(function () {
20058
- PageNext(_opt);
20059
- return Promise.resolve();
20060
- });
20061
- });
20062
- }
20063
- }).then(function () {
20064
- ForceUpdate();
20065
- }).catch(function (err) {
20066
- console.error(err);
20067
- })
20068
- };
20069
-
20070
- function Redirect(url) {
20071
- var title = null;
20072
- var titleTag = document.querySelector('title');
20073
- if (titleTag) {
20074
- title = titleTag.innerText;
20075
- }
20076
- window.history.pushState(null, title, url);
20077
- UpdateLayout();
20078
- }
20079
-
20080
- function Replace(url) {
20081
- var title = null;
20082
- var titleTag = document.querySelector('title');
20083
- if (titleTag) {
20084
- title = titleTag.innerText;
20085
- }
20086
- window.history.replaceState(null, title, url);
20087
- UpdateLayout();
20088
- }
20089
-
20090
-
20091
- function LoadScript(url) {
20092
- if (_httpCached(url)) {
20093
- with (window) {
20094
- if (PomeloModule) {
20095
- var require = function (script, workingDirectory, mode) {
20096
- workingDirectory = workingDirectory || PomeloModule.getContainingFolder(url);
20097
- return PomeloModule.require(script, workingDirectory, mode);
20098
- };
20099
- }
20100
-
20101
- eval(_cache[url] + '\r\n//# sourceURL=' + url);
20102
- }
20103
- return Promise.resolve();
20104
- }
20105
-
20106
- return _httpGet(url).then(function (js) {
20107
- with (window) {
20108
-
20109
- if (PomeloModule) {
20110
- var require = function (script, workingDirectory, mode) {
20111
- workingDirectory = workingDirectory || PomeloModule.getContainingFolder(url);
20112
- return PomeloModule.require(script, workingDirectory, mode);
20113
- };
20114
- }
20115
-
20116
- eval(js + '\r\n//# sourceURL=' + url);
20117
- }
20118
- _cache[url] = js;
20119
- return Promise.resolve();
20120
- }).catch(err => {
20121
- console.error('Load module ' + url + ' failed.');
20122
- console.error(err);
20123
- });
20124
- }
20125
-
20126
- function resolveRelativePathPlain(url) {
20127
- if (url.indexOf('./') == -1 && url.indexOf('../') == -1) {
20128
- return url;
20129
- }
20130
-
20131
- var index = url.lastIndexOf('../');
20132
- if (index == 0) {
20133
- return url;
20134
- }
20135
-
20136
- url = url.replaceAll('/./', '/');
20137
- if (url.indexOf('./') == 0) {
20138
- url = url.substr(2);
20139
- }
20140
-
20141
- if (index) {
20142
- var w = url.substr(0, index);
20143
- var f = url.substr(index);
20144
- return resolveRelativePath(f, w);
20145
- }
20146
- }
20147
-
20148
- function resolveRelativePath(file, workingDirectory) {
20149
- if (file.length && (file[0] == '/') || file.indexOf('http') == 0) {
20150
- return resolveRelativePathPlain(file);
20151
- }
20152
-
20153
- if (file.length && file[0] != '.') {
20154
- return resolveRelativePathPlain(workingDirectory + file);
20155
- }
20156
-
20157
- if (file.indexOf('./') == 0) {
20158
- return resolveRelativePath(file.substr(2), workingDirectory);
20159
- }
20160
-
20161
- if (file.indexOf('../') == 0) {
20162
- file = file.substr(3);
20163
- workingDirectory = getContainingFolder(workingDirectory.substr(0, workingDirectory.length - 1));
20164
- return resolveRelativePath(file, workingDirectory);
20165
- }
20166
- }
20167
-
20168
- function _loadComponents(components, viewName) {
20169
- var ret = [];
20170
- if (!components.length) {
20171
- return Promise.resolve(ret);
20172
- }
20173
- var workingDirectory = getContainingFolder(viewName || '/');
20174
- return Promise.all(components.map(function (c) {
20175
- c = resolveRelativePath(parseMacroPath(viewName, c), workingDirectory);
20176
- var componentPath = c;
20177
- var _html;
20178
- var _name;
20179
- var _opt;
20180
- // Load .html, .js and optional .skeleton.html in parallel
20181
- return Promise.all([
20182
- _httpGet(c + '.html'),
20183
- _httpGet(c + '.js'),
20184
- _httpGetSkeletonFile(c + '.skeleton.html')
20185
- ]).then(function (results) {
20186
- _html = results[0];
20187
- var comJs = results[1];
20188
- var skeletonFileHtml = results[2]; // null when file does not exist
20189
- var Component = function (name, options) {
20190
- _opt = options;
20191
- _name = name;
20192
- };
20193
-
20194
- var require = _createRequire(c);
20195
- eval(comJs + '\r\n//# sourceURL=' + c + ".js");
20196
- hookMountedAndUnmounted(_opt, c);
20197
- // Resolve template option for Component (could be .html path or inline HTML)
20198
- var compTemplatePromise = _opt.template
20199
- ? _resolveTemplateOption(_opt.template)
20200
- : Promise.resolve(null);
20201
- return compTemplatePromise.then(function (resolvedCompTemplate) {
20202
- if (resolvedCompTemplate) {
20203
- _opt.template = resolvedCompTemplate;
20204
- } else if (!_opt.template) {
20205
- _opt.template = _sanitizeTemplate(_html);
20206
- }
20207
- _hookSetup(_opt);
20208
- _patchComponent(c, _opt, true);
20209
- // Register the component's skeleton BEFORE wrapping the template,
20210
- // so _generateSkeletonHtml still sees the clean original template.
20211
- _registerComponentSkeleton(_name, _opt, _opt.template, skeletonFileHtml);
20212
- _wrapTemplateWithSkeleton(_opt);
20213
- _hookData(_opt);
20214
- var cssPreloadPromise = Promise.resolve();
20215
- if (_options.preloadCss && _opt.style) {
20216
- cssPreloadPromise = appendCssReferenceAsync(c, _opt.style);
20217
- }
20218
- return Promise.all([cssPreloadPromise, _resolveModules(_opt.modules, c)]);
20219
- }); // end of compTemplatePromise.then
20220
- }).then(function () {
20221
- // Recursively load sub-components for this component
20222
- var subComponentRefs = _opt.components || [];
20223
- return _loadComponents(subComponentRefs, componentPath);
20224
- }).then(function (subComponents) {
20225
- ret.push({ name: _name, options: _opt });
20226
- for (var i = 0; i < subComponents.length; ++i) {
20227
- if (!ret.some(function (x) { return x.name == subComponents[i].name; })) {
20228
- ret.push(subComponents[i]);
20229
- }
20230
- }
20231
- return Promise.resolve();
20232
- });
20233
- })).then(function () {
20234
- return Promise.resolve(ret);
20235
- });
20236
- }
20237
-
20238
- function _loadDirectives(directives, viewName) {
20239
- var ret = [];
20240
- if (!directives.length) {
20241
- return Promise.resolve(ret);
20242
- }
20243
- var workingDirectory = getContainingFolder(viewName || '/');
20244
- var viewName;
20245
- var subComponentRefs = [];
20246
- return Promise.all(directives.map(function (c) {
20247
- c = resolveRelativePath(parseMacroPath(viewName, c), workingDirectory);
20248
- viewName = c;
20249
- var _name;
20250
- var _opt;
20251
- return _httpGet(c + ".js").then(function (comJs) {
20252
- var Directive = function (name, options) {
20253
- _opt = options;
20254
- _name = name;
20255
- };
20256
-
20257
- var require = _createRequire(c);
20258
- eval(comJs + '\r\n//# sourceURL=' + c + ".js");
20259
- ret.push({ name: _name, options: _opt });
20260
- return Promise.resolve();
20261
- })
20262
- })).then(function () {
20263
- return Promise.resolve(ret);
20264
- });
20265
- }
20266
-
20267
- exports._addins = [];
20268
-
20269
- function _patchComponent(view, opt, isComponent) {
20270
- prepared = true;
20271
- if (!opt.data) {
20272
- opt.data = function () {
20273
- return {};
20274
- };
20275
- }
20276
-
20277
- if (!opt.style) {
20278
- opt.style = [];
20279
- }
20280
-
20281
- if (!opt.style instanceof Array) {
20282
- if (opt.style instanceof String) {
20283
- opt.style = [opt.style];
20284
- } else {
20285
- opt.style = ['@(css)'];
20286
- }
20287
- }
20288
-
20289
- if (!opt.components) {
20290
- opt.components = [];
20291
- }
20292
-
20293
- if (!opt.created) {
20294
- opt.created = function () { };
20295
- }
20296
-
20297
- if (!opt.mounted) {
20298
- opt.mounted = function () { };
20299
- }
20300
-
20301
- if (!opt.unmounted) {
20302
- opt.unmounted = function () { };
20303
- }
20304
-
20305
- if (!opt.destroyed) {
20306
- opt.destroyed = function () { };
20307
- }
20308
-
20309
- if (!opt.watch) {
20310
- opt.watch = {};
20311
- }
20312
-
20313
- if (!opt.computed) {
20314
- opt.computed = {};
20315
- }
20316
-
20317
- let func1 = opt.data;
20318
- opt.data = function (app) {
20319
- var data = func1.call(this, app);
20320
- var data2 = {};
20321
- if (!isComponent) {
20322
- data2.pomeUiSubTitles = [];
20323
- }
20324
- if (opt.skeleton) {
20325
- // Start hidden; skeleton is only shown after skeletonDelay ms
20326
- // to avoid a flash when loading completes quickly.
20327
- data2.pomeSkeletonLoading = false;
20328
- // Cloak: hide real content until skeleton appears or data loads,
20329
- // preventing a flash of uninitialized content during the delay.
20330
- data2.pomeSkeletonCloaked = true;
20331
- }
20332
- if (opt.skeleton && opt.delayOpen) {
20333
- data2.pomeDelayOpened = true;
20334
- data2.pomeDelayOpening = true;
20335
- }
20336
- _combineObject(data2, data);
20337
- return data;
20338
- }
20339
-
20340
- if (!opt.methods) {
20341
- opt.methods = {};
20342
- }
20343
-
20344
- if (!isComponent) {
20345
- opt.methods.pomeUiPassTitle = pomeUiPassTitle;
20346
-
20347
- if (!opt.watch) {
20348
- opt.watch = {};
20349
- }
20350
-
20351
- if (!opt.watch.title) {
20352
- opt.watch.title = function () { };
20353
- }
20354
-
20355
-
20356
- _chainHook(opt.watch, 'title', function () {
20357
- this.pomeUiPassTitle();
20358
- });
20359
- }
20360
-
20361
- for (let i = 0; i < exports._addins.length; ++i) {
20362
- let v = exports._addins[i].view;
20363
- let addin = exports._addins[i].opt;
20364
- if (v != '*' && view != v) {
20365
- continue;
20366
- }
20367
-
20368
- if (addin.data) {
20369
- let func2 = opt.data;
20370
- opt.data = function (app) {
20371
- var data = func2.call(this, app);
20372
- var data2 = {};
20373
- try {
20374
- data2 = addin.data.call(this, app);
20375
- } catch (ex) {
20376
- console.error(ex);
20377
- }
20378
- _combineObject(data2, data);
20379
- return data;
20380
- }
20381
- }
20382
-
20383
- if (addin.style) {
20384
- if (addin.style instanceof Boolean) {
20385
- addin.style = ['@(css)'];
20386
- }
20387
-
20388
- if (addin.style instanceof String) {
20389
- addin.style = [addin.style];
20390
- }
20391
-
20392
- addin.style.forEach(function (s) {
20393
- if (!opt.style) {
20394
- opt.style = [];
20395
- }
20396
- if (typeof opt.style == 'boolean') {
20397
- opt.style = ['@(css)'];
20398
- }
20399
- if (!opt.style.some(x => x == s)) {
20400
- opt.style.push(s);
20401
- }
20402
- });
20403
- }
20404
-
20405
- if (addin.components) {
20406
- addin.components.forEach(function (c) {
20407
- if (!opt.components.some(x => x == c)) {
20408
- opt.components.push(c);
20409
- }
20410
- });
20411
- }
20412
-
20413
- if (addin.layout) {
20414
- opt.layout = addin.layout;
20415
- }
20416
-
20417
- if (addin.props) {
20418
- if (!opt.props) {
20419
- opt.props = [];
20420
- }
20421
-
20422
- addin.props.forEach(function (p) {
20423
- if (!opt.props.some(x => x == p)) {
20424
- opt.props.push(p);
20425
- }
20426
- });
20427
- }
20428
-
20429
- if (addin.watch) {
20430
- var properties = Object.getOwnPropertyNames(addin.watch);
20431
- properties.forEach(function (key) {
20432
- var _originalWatch = opt.watch[key];
20433
- opt.watch[key] = function (a, b) {
20434
- _originalWatch.invoke(this, a, b);
20435
- try {
20436
- addin.watch[key].invoke(this, a, b);
20437
- } catch (ex) {
20438
- console.error(ex);
20439
- }
20440
- }
20441
- });
20442
- }
20443
-
20444
- if (addin.computed) {
20445
- var properties = Object.getOwnPropertyNames(addin.computed);
20446
- properties.forEach(function (key) {
20447
- opt.computed[key] = addin.computed[key];
20448
- });
20449
- }
20450
-
20451
- if (addin.methods) {
20452
- var setup = opt.setup || function (props, context) {
20453
- };
20454
-
20455
- opt.setup = function (props, context) {
20456
- setup(props, context);
20457
- var methods = {};
20458
- var originMethods = Object.getOwnPropertyNames(opt.methods);
20459
- originMethods.forEach(function (m) {
20460
- methods[m] = opt.methods[m];
20461
- });
20462
- var instance = Vue.getCurrentInstance();
20463
- instance.$baseMethods = methods;
20464
- };
20465
-
20466
- var addinMethods = Object.getOwnPropertyNames(addin.methods);
20467
- addinMethods.forEach(function (m) {
20468
- opt.methods[m] = addin.methods[m];
20469
- });
20470
- }
20471
-
20472
- if (addin.created) {
20473
- _chainHook(opt, 'created', addin.created);
20474
- }
20475
-
20476
- if (addin.mounted) {
20477
- _chainHook(opt, 'mounted', addin.mounted);
20478
- }
20479
-
20480
- if (addin.unmounted) {
20481
- _chainHook(opt, 'unmounted', addin.unmounted);
20482
- }
20483
-
20484
- if (addin.destroyed) {
20485
- _chainHook(opt, 'destroyed', addin.destroyed);
20486
- }
20487
-
20488
- if (addin.template) {
20489
- if (addin.template instanceof Function) {
20490
- if (opt.template) {
20491
- if (opt.template.indexOf('<html') >= 0) {
20492
- var template = new DOMParser().parseFromString(_sanitizeTemplate(opt.template), 'text/html');
20493
- addin.template(template);
20494
- opt.template = new XMLSerializer().serializeToString(template);
20495
- } else {
20496
- opt.template = `<pome-ui-template>${opt.template}</pome-ui-template>`
20497
- var template = new DOMParser().parseFromString(_sanitizeTemplate(opt.template), 'text/html');
20498
- addin.template(template);
20499
- opt.template = new XMLSerializer().serializeToString(template);
20500
- opt.template = opt.template.substr(opt.template.indexOf('<pome-ui-template>') + '<pome-ui-template>'.length);
20501
- opt.template = opt.template.substr(0, opt.template.indexOf('</pome-ui-template>'));
20502
- }
20503
- }
20504
- } else {
20505
- opt.template = addin.template;
20506
- }
20507
- }
20508
- }
20509
-
20510
- if (!isComponent) {
20511
- _chainHook(opt, 'created', function () {
20512
- this.pomeUiPassTitle();
20513
- });
20514
-
20515
- _chainHook(opt, 'unmounted', function () {
20516
- this.pomeUiPassTitle([]);
20517
- });
20518
- }
20519
- }
20520
-
20521
- function _patchTemplate(view, html) {
20522
- for (let i = 0; i < exports._addins.length; ++i) {
20523
- let v = exports._addins[i].view;
20524
- let addin = exports._addins[i].opt;
20525
- if (v != '*' && view != v) {
20526
- continue;
20527
- }
20528
-
20529
- if (addin.template) {
20530
- if (addin.template instanceof Function) {
20531
- if (html.indexOf('<html') >= 0) {
20532
- var template = new DOMParser().parseFromString(_sanitizeTemplate(html), 'text/html');
20533
- addin.template(template);
20534
- html = new XMLSerializer().serializeToString(template);
20535
- } else {
20536
- html = `<pome-ui-template>${html}</pome-ui-template>`
20537
- var template = new DOMParser().parseFromString(_sanitizeTemplate(html), 'text/html');
20538
- addin.template(template);
20539
- html = new XMLSerializer().serializeToString(template);
20540
- html = html.substr(html.indexOf('<pome-ui-template>') + '<pome-ui-template>'.length);
20541
- html = html.substr(0, html.indexOf('</pome-ui-template>'));
20542
- }
20543
- } else {
20544
- html = addin.template;
20545
- }
20546
- }
20547
- }
20548
- return html;
20549
- }
20550
-
20551
- function UseAddin(addinUrl) {
20552
- var Addin = function (view, opt) {
20553
- exports._addins.push({view, opt});
20554
- };
20555
-
20556
- var js = _options.httpGetSync(addinUrl);
20557
- eval(js);
20558
- }
20559
-
20560
-
20561
- function UseInlineAddin(script) {
20562
- var Addin = function (view, opt) {
20563
- exports._addins.push({ view, opt });
20564
- };
20565
-
20566
- eval(script);
20567
- }
20568
-
20569
- function Backward() {
20570
- window.history.back();
20571
- }
20572
-
20573
- exports.root = root;
20574
- exports.useConfig = UseConfig;
20575
- exports.mapRoute = MapRoute;
20576
- exports.matchRoute = MatchRoute;
20577
- exports.updateLayout = UpdateLayout;
20578
- exports.redirect = Redirect;
20579
- exports.replace = Replace;
20580
- exports.backward = Backward;
20581
- exports.loadScript = LoadScript;
20582
- exports.forceUpdate = ForceUpdate;
20583
- exports.mount = mount;
20584
- exports.useRoutes = useRoutes;
20585
- exports.useAddin = UseAddin;
20586
- exports.useInlineAddin = UseInlineAddin;
20587
-
20588
- return exports;
20589
- };
20590
-
18112
+ // Copyright (c) Yuko(Yisheng) Zheng. All rights reserved.
18113
+ // Licensed under the GPL v3. See LICENSE in the project root for license information.
18114
+
18115
+ window.Vue = Vue;
18116
+
18117
+ function build(options, exports) {
18118
+ if (typeof exports == 'undefined') {
18119
+ exports = {};
18120
+ }
18121
+
18122
+ // Options
18123
+ var _options = {
18124
+ resolveModulesParallelly: true,
18125
+ removeStyleWhenUnmount: false,
18126
+ preloadCss: true,
18127
+ mobile: function () {
18128
+ return false;
18129
+ },
18130
+ httpGet: function (url) {
18131
+ return fetch(url);
18132
+ },
18133
+ httpGetSync: function (url) {
18134
+ if (useRelativePath) {
18135
+ if (url.length && url[0] == '/') {
18136
+ url = url.substr(1);
18137
+ }
18138
+ }
18139
+ var xhr = new XMLHttpRequest();
18140
+ xhr.open('get', url, false);
18141
+ xhr.send();
18142
+ return xhr.responseText;
18143
+ },
18144
+ onNotFound: function (url, options) {
18145
+ if (url.indexOf('/404') == 0) {
18146
+ throw 'No not-found template found';
18147
+ }
18148
+ if (options) {
18149
+ return Redirect('/404?' + _serializeOptionsToUrl(options));
18150
+ } else {
18151
+ return Redirect('/404');
18152
+ }
18153
+ },
18154
+ reuseContainerActiveView(viewName) {
18155
+ return true;
18156
+ },
18157
+ callCreatedWhenReuseContainerActiveView(viewName) {
18158
+ return true;
18159
+ },
18160
+ callMountedWhenReuseContainerActiveView(viewName) {
18161
+ return true;
18162
+ },
18163
+ callUnmountedWhenReuseContainerActiveView(viewName) {
18164
+ return true;
18165
+ },
18166
+ resetDataWhenReuseContainerActiveView(viewName) {
18167
+ return true;
18168
+ },
18169
+ generateTitle(titles) {
18170
+ return titles.join(' - ');
18171
+ }
18172
+ };
18173
+
18174
+ _combineObject(options, _options);
18175
+
18176
+ // Common
18177
+ var _cache = {};
18178
+
18179
+ var _css = {};
18180
+
18181
+ var _cssCloakInjected = false;
18182
+ function _ensureCssCloakStyle() {
18183
+ if (_cssCloakInjected) return;
18184
+ _cssCloakInjected = true;
18185
+ var style = document.createElement('style');
18186
+ style.textContent = '._pome-css-cloak{visibility:hidden!important}';
18187
+ document.head.appendChild(style);
18188
+ }
18189
+
18190
+ var _vueCloakInjected = false;
18191
+ function _ensureVueCloakStyle() {
18192
+ if (_vueCloakInjected) return;
18193
+ _vueCloakInjected = true;
18194
+ var style = document.createElement('style');
18195
+ style.textContent = '._pome-vue-cloak{display:none!important}';
18196
+ document.head.appendChild(style);
18197
+ }
18198
+
18199
+ function _ensureSkeletonStyle() {
18200
+ // pome-skeleton.css must be referenced by the host page manually.
18201
+ // This function is kept as a hook point for future use.
18202
+ }
18203
+
18204
+ // Registry: kebab-name �?pre-rendered skeleton HTML string
18205
+ var _componentSkeletonRegistry = {};
18206
+
18207
+ function _toKebabCase(name) {
18208
+ // ScalableSidebar �?scalable-sidebar, menuBar �?menu-bar
18209
+ return name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
18210
+ }
18211
+
18212
+ function _registerComponentSkeleton(name, opt, rawHtml, skeletonFileHtml) {
18213
+ // skeletonFileHtml: content of <component>.skeleton.html (takes top priority)
18214
+ // opt.skeleton === string: inline HTML declared in the JS
18215
+ // opt.skeleton === true: auto-generate from rawHtml
18216
+ var hasFile = !!skeletonFileHtml;
18217
+ var hasInline = opt && typeof opt.skeleton === 'string';
18218
+ var hasAuto = opt && opt.skeleton === true;
18219
+ if (!hasFile && !hasInline && !hasAuto) return;
18220
+ var kebab = _toKebabCase(name);
18221
+ var skHtml = hasFile ? skeletonFileHtml
18222
+ : hasInline ? opt.skeleton
18223
+ : _generateSkeletonHtml(rawHtml || (opt && opt.template) || '');
18224
+ _componentSkeletonRegistry[kebab] = skHtml;
18225
+ }
18226
+
18227
+ // --- Extract a plain numeric value from a bound attribute like :default-width="230" ---
18228
+ function _extractBoundNumber(el, attr) {
18229
+ var val = el.getAttribute(':' + attr);
18230
+ if (!val) return null;
18231
+ var m = val.match(/^(\d+(?:\.\d+)?)/);
18232
+ return m ? m[1] : null;
18233
+ }
18234
+
18235
+ // --- Known HTML tags for skeleton (custom components will be unwrapped) ---
18236
+ var _knownHtmlTags = null;
18237
+ function _isKnownHtmlTag(tag) {
18238
+ if (!_knownHtmlTags) {
18239
+ _knownHtmlTags = {};
18240
+ 'div,span,p,a,h1,h2,h3,h4,h5,h6,ul,ol,li,table,thead,tbody,tfoot,tr,td,th,colgroup,col,img,video,canvas,iframe,svg,form,input,textarea,select,option,button,label,section,article,aside,header,footer,nav,main,figure,figcaption,blockquote,pre,code,em,strong,i,b,u,small,sub,sup,br,hr,dl,dt,dd,details,summary,fieldset,legend,caption,abbr,cite,mark,time,address'.split(',').forEach(function(t) { _knownHtmlTags[t] = true; });
18241
+ }
18242
+ return !!_knownHtmlTags[tag];
18243
+ }
18244
+
18245
+ function _generateSkeletonHtml(templateHtml) {
18246
+ if (!templateHtml) return '';
18247
+ var html = templateHtml;
18248
+ // Remove Vue mustache expressions �?replace with non-breaking space
18249
+ html = html.replace(/\{\{[\s\S]*?\}\}/g, '\u00A0');
18250
+ // Parse as DOM
18251
+ var doc = new DOMParser().parseFromString(
18252
+ '<div id="_pome-sk-wrap">' + html + '</div>', 'text/html'
18253
+ );
18254
+ var root = doc.getElementById('_pome-sk-wrap');
18255
+ if (!root) return '';
18256
+ // Pass 1 �?structural: unwrap <template> slots, replace custom elements,
18257
+ // clone v-for rows, remove v-else branches
18258
+ _skeletonStructurePass(root, doc);
18259
+ // Pass 2 �?cleanup: strip Vue directives, replace text with skeleton blocks
18260
+ _skeletonCleanupPass(root);
18261
+ return root.innerHTML;
18262
+ }
18263
+
18264
+ function _wrapTemplateWithSkeleton(opt) {
18265
+ if (!opt.skeleton || !opt.template) return;
18266
+ _ensureSkeletonStyle();
18267
+ var skeletonHtml = typeof opt.skeleton === 'string'
18268
+ ? opt.skeleton
18269
+ : _generateSkeletonHtml(opt.template);
18270
+
18271
+ var inner = '<template v-if="!pomeSkeletonLoading && !pomeSkeletonCloaked">' + opt.template
18272
+ + '</template><div v-if="pomeSkeletonLoading" class="_pome-skeleton">'
18273
+ + skeletonHtml + '</div>';
18274
+
18275
+ if (opt.delayOpen) {
18276
+ // Wrap everything in a single div with reactive delayOpen classes
18277
+ // so the delayOpen animation applies to both skeleton and real content.
18278
+ opt.template = '<div :class="{\'_pome-ui-opened\': pomeDelayOpened, \'_pome-ui-opening\': pomeDelayOpening}">' + inner + '</div>';
18279
+ } else {
18280
+ opt.template = inner;
18281
+ }
18282
+ }
18283
+
18284
+ // --- Pass 1: structural transformations ---
18285
+ function _skeletonStructurePass(node, doc) {
18286
+ if (!node || node.nodeType !== 1) return;
18287
+ var i = 0;
18288
+ while (i < node.childNodes.length) {
18289
+ var child = node.childNodes[i];
18290
+ if (child.nodeType !== 1) { i++; continue; }
18291
+ var tag = child.tagName.toLowerCase();
18292
+
18293
+ // 1. Handle <template> tags (Vue slots)
18294
+ if (tag === 'template') {
18295
+ // Determine slot name from #xxx or v-slot:xxx
18296
+ var slotName = null;
18297
+ for (var a = 0; a < child.attributes.length; a++) {
18298
+ var attr = child.attributes[a].name;
18299
+ if (attr[0] === '#') { slotName = attr.substring(1); break; }
18300
+ if (attr.indexOf('v-slot:') === 0) { slotName = attr.substring(7); break; }
18301
+ }
18302
+ // Only keep the default slot (or unnamed templates); discard others
18303
+ if (slotName && slotName !== 'default') {
18304
+ node.removeChild(child);
18305
+ continue;
18306
+ }
18307
+ // Unwrap template content into parent
18308
+ if (child.content) {
18309
+ var tplNodes = Array.from(child.content.childNodes);
18310
+ for (var j = 0; j < tplNodes.length; j++) {
18311
+ node.insertBefore(doc.importNode(tplNodes[j], true), child);
18312
+ }
18313
+ }
18314
+ node.removeChild(child);
18315
+ continue; // re-examine index (new children inserted)
18316
+ }
18317
+
18318
+ // 2. Remove v-else / v-else-if branches entirely
18319
+ if (child.getAttribute('v-else') !== null || child.getAttribute('v-else-if') !== null) {
18320
+ node.removeChild(child);
18321
+ continue;
18322
+ }
18323
+
18324
+ // 3. Handle v-for �?clone element to simulate repeated rows
18325
+ if (child.getAttribute('v-for')) {
18326
+ child.removeAttribute('v-for');
18327
+ var cloneCount = (tag === 'tr') ? 4 : (tag === 'li') ? 3 : 2;
18328
+ var refNode = child.nextSibling;
18329
+ for (var j = 0; j < cloneCount; j++) {
18330
+ var clone = child.cloneNode(true);
18331
+ node.insertBefore(clone, refNode);
18332
+ }
18333
+ // fall through to continue processing this element
18334
+ }
18335
+
18336
+ // 4. Replace custom/unknown elements with <div>, keep children
18337
+ if (!_isKnownHtmlTag(tag)) {
18338
+ // Check if this component has declared its own skeleton
18339
+ var registeredSkeleton = _componentSkeletonRegistry[tag];
18340
+ if (registeredSkeleton) {
18341
+ // Parse the registered skeleton HTML and replace the element with it
18342
+ var skWrap = doc.createElement('div');
18343
+ skWrap.innerHTML = registeredSkeleton;
18344
+ if (child.getAttribute('class')) skWrap.setAttribute('class', child.getAttribute('class'));
18345
+ var existingStyleReg = child.getAttribute('style') || '';
18346
+ var styleExtraReg = '';
18347
+ var defWReg = _extractBoundNumber(child, 'default-width') || child.getAttribute('default-width');
18348
+ var minWReg = _extractBoundNumber(child, 'min-width') || child.getAttribute('min-width');
18349
+ if (defWReg) styleExtraReg += ';width:' + defWReg + 'px;flex-shrink:0';
18350
+ if (minWReg) styleExtraReg += ';min-width:' + minWReg + 'px';
18351
+ var combinedStyleReg = (existingStyleReg + styleExtraReg).replace(/^;+/, '');
18352
+ if (combinedStyleReg) skWrap.setAttribute('style', combinedStyleReg);
18353
+ // Replace the custom element with a wrapper containing the skeleton.
18354
+ // Use a fragment-like approach: move skWrap's children directly
18355
+ // so we don't add an extra div when the registered HTML already has one.
18356
+ var skNodes = Array.from(skWrap.childNodes);
18357
+ if (skNodes.length === 1 && skNodes[0].nodeType === 1) {
18358
+ var skRoot = skNodes[0];
18359
+ // Merge class / style from host element onto the single root node
18360
+ if (child.getAttribute('class')) skRoot.classList && skRoot.setAttribute('class', (skRoot.getAttribute('class') || '') + ' ' + child.getAttribute('class'));
18361
+ if (combinedStyleReg) skRoot.setAttribute('style', (skRoot.getAttribute('style') ? skRoot.getAttribute('style') + ';' : '') + combinedStyleReg);
18362
+ node.replaceChild(skRoot, child);
18363
+ i++;
18364
+ } else {
18365
+ while (skWrap.firstChild) node.insertBefore(skWrap.firstChild, child);
18366
+ node.removeChild(child);
18367
+ // i stays the same since we removed child and inserted nodes before it
18368
+ }
18369
+ continue;
18370
+ }
18371
+
18372
+ var div = doc.createElement('div');
18373
+ if (child.getAttribute('class')) div.setAttribute('class', child.getAttribute('class'));
18374
+
18375
+ // Reconstruct inline style, preserving explicit style + any bound sizing attrs
18376
+ var existingStyle = child.getAttribute('style') || '';
18377
+ var styleExtra = '';
18378
+ // :default-width / default-width �?width + flex-shrink:0 so sidebar-like
18379
+ // components keep their width in the skeleton
18380
+ var defW = _extractBoundNumber(child, 'default-width') || child.getAttribute('default-width');
18381
+ var minW = _extractBoundNumber(child, 'min-width') || child.getAttribute('min-width');
18382
+ var maxW = _extractBoundNumber(child, 'max-width') || child.getAttribute('max-width');
18383
+ if (defW) styleExtra += ';width:' + defW + 'px;flex-shrink:0';
18384
+ if (minW) styleExtra += ';min-width:' + minW + 'px';
18385
+ if (maxW) styleExtra += ';max-width:' + maxW + 'px';
18386
+ var combinedStyle = (existingStyle + styleExtra).replace(/^;+/, '');
18387
+ if (combinedStyle) div.setAttribute('style', combinedStyle);
18388
+
18389
+ while (child.firstChild) div.appendChild(child.firstChild);
18390
+ node.replaceChild(div, child);
18391
+ _skeletonStructurePass(div, doc); // recurse into replacement
18392
+ i++;
18393
+ continue;
18394
+ }
18395
+
18396
+ // 5. Recurse into known elements
18397
+ _skeletonStructurePass(child, doc);
18398
+ i++;
18399
+ }
18400
+ }
18401
+
18402
+ // --- Pass 2: cleanup directives, replace text, handle media ---
18403
+ function _skeletonCleanupPass(node) {
18404
+ if (!node) return;
18405
+ if (node.nodeType === 1) {
18406
+ // Strip Vue directives / bindings / event listeners.
18407
+ // Preserve v-show so CSS-driven responsive visibility still works
18408
+ // (the skeleton lives inside a Vue-processed template).
18409
+ var attrsToRemove = [];
18410
+ for (var i = 0; i < node.attributes.length; i++) {
18411
+ var attrName = node.attributes[i].name;
18412
+ if (attrName === 'v-show') continue; // keep v-show for responsive toggling
18413
+ if (attrName.indexOf('v-') === 0 || attrName[0] === '@' || attrName[0] === ':' || attrName[0] === '#') {
18414
+ attrsToRemove.push(attrName);
18415
+ }
18416
+ }
18417
+ for (var i = 0; i < attrsToRemove.length; i++) {
18418
+ node.removeAttribute(attrsToRemove[i]);
18419
+ }
18420
+ // Remove delayOpen classes
18421
+ node.classList.remove('_pome-ui-opened');
18422
+ node.classList.remove('_pome-ui-opening');
18423
+ // Add shimmer class to leaf-level text containers
18424
+ var tag = node.tagName.toLowerCase();
18425
+ var shimmerTags = {span:1,a:1,p:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,li:1,label:1,button:1,input:1,textarea:1,select:1,dt:1,dd:1,figcaption:1,blockquote:1};
18426
+ if (shimmerTags[tag]) {
18427
+ node.classList.add('_pome-sk-shimmer');
18428
+ }
18429
+ if (tag === 'img') {
18430
+ // Replace img with a shimmer skeleton block that preserves dimensions
18431
+ var imgBlock = node.ownerDocument.createElement('span');
18432
+ imgBlock.className = '_pome-sk-img';
18433
+ // Preserve sizing from class or explicit attributes
18434
+ if (node.getAttribute('class')) imgBlock.className += ' ' + node.getAttribute('class');
18435
+ if (node.getAttribute('width')) imgBlock.style.width = node.getAttribute('width') + (/\d$/.test(node.getAttribute('width')) ? 'px' : '');
18436
+ else imgBlock.style.width = '24px';
18437
+ if (node.getAttribute('height')) imgBlock.style.height = node.getAttribute('height') + (/\d$/.test(node.getAttribute('height')) ? 'px' : '');
18438
+ else imgBlock.style.height = '24px';
18439
+ node.parentNode.replaceChild(imgBlock, node);
18440
+ return; // node replaced, skip children
18441
+ }
18442
+ if (tag === 'video' || tag === 'canvas' || tag === 'iframe') {
18443
+ node.removeAttribute('src');
18444
+ node.removeAttribute('srcset');
18445
+ node.style.backgroundColor = '#e8e8e8';
18446
+ node.style.borderRadius = '4px';
18447
+ }
18448
+ }
18449
+ var children = Array.from(node.childNodes);
18450
+ for (var i = 0; i < children.length; i++) {
18451
+ var child = children[i];
18452
+ if (child.nodeType === 3) { // text node
18453
+ // \u00A0 comes from mustache replacement �?treat it as content
18454
+ var text = child.textContent.replace(/[\s\u00A0]+/g, '');
18455
+ var hasNbsp = child.textContent.indexOf('\u00A0') >= 0;
18456
+ if (text || hasNbsp) {
18457
+ var parentTag = child.parentNode && child.parentNode.tagName
18458
+ ? child.parentNode.tagName.toLowerCase() : '';
18459
+ var block = child.ownerDocument.createElement('span');
18460
+ block.className = '_pome-sk-block';
18461
+ block.innerHTML = '\u00A0';
18462
+ child.parentNode.replaceChild(block, child);
18463
+ }
18464
+ } else if (child.nodeType === 1) {
18465
+ _skeletonCleanupPass(child);
18466
+ }
18467
+ }
18468
+ }
18469
+
18470
+ function _httpCached(url) {
18471
+ return !!_cache[url];
18472
+ }
18473
+
18474
+ function _httpGet(url) {
18475
+ if (_cache[url]) {
18476
+ return Promise.resolve(_cache[url]);
18477
+ }
18478
+
18479
+ var _url = url;
18480
+ if (_options.version) {
18481
+ if (url.indexOf('?') > 0) {
18482
+ _url += "&";
18483
+ } else {
18484
+ _url += "?"
18485
+ }
18486
+ _url += "v=" + _options.version;
18487
+ }
18488
+
18489
+ return _options.httpGet(_url).then(function (result) {
18490
+ if (result.status > 300 || result.status < 200) {
18491
+ return Promise.reject(result);
18492
+ }
18493
+
18494
+ var txt = result.text();
18495
+ _cache[url] = txt;
18496
+ return Promise.resolve(txt);
18497
+ }).catch(function (err) {
18498
+ return Promise.reject(err);
18499
+ });
18500
+ };
18501
+
18502
+ function _httpExist(url) {
18503
+ return _httpGet(url)
18504
+ .then(function () {
18505
+ return Promise.resolve(true);
18506
+ })
18507
+ .catch(function () {
18508
+ return Promise.resolve(false);
18509
+ });
18510
+ };
18511
+
18512
+ // Fetch a .skeleton.html file, returning null when the file does not
18513
+ // physically exist. Unlike _httpGet, this guards against SPA catch-all
18514
+ // routes that return the app entry page (status 200) for any URL:
18515
+ // if the response body starts with "<!DOCTYPE" or "<html" it is treated
18516
+ // as a missing file and null is returned.
18517
+ // Caches "not found" results so that repeated requests for the same
18518
+ // missing skeleton file do not produce additional network round-trips.
18519
+ var _skeletonNotFoundCache = {};
18520
+ function _httpGetSkeletonFile(url) {
18521
+ if (_skeletonNotFoundCache[url]) {
18522
+ return Promise.resolve(null);
18523
+ }
18524
+ return _httpGet(url).then(function (text) {
18525
+ if (!text) {
18526
+ _skeletonNotFoundCache[url] = true;
18527
+ return null;
18528
+ }
18529
+ var trimmed = text.replace(/^[\s\uFEFF]+/, ''); // strip BOM / whitespace
18530
+ if (/^<!DOCTYPE/i.test(trimmed) || /^<html/i.test(trimmed)) {
18531
+ _skeletonNotFoundCache[url] = true;
18532
+ return null; // SPA fallback page, not a real skeleton file
18533
+ }
18534
+ return text;
18535
+ }).catch(function () {
18536
+ _skeletonNotFoundCache[url] = true;
18537
+ return null;
18538
+ });
18539
+ };
18540
+
18541
+ function _serializeOptionsToUrl(options) {
18542
+ var fields = Object.getOwnPropertyNames(options);
18543
+ var str = '';
18544
+ for (var i = 0; i < fields.length; ++i) {
18545
+ str += encodeURIComponent(fields[i]) + '=' + encodeURIComponent(options[fields[i]]) + '&';
18546
+ }
18547
+
18548
+ if (str[str.length - 1] === '&') {
18549
+ str = str.substr(0, str.length - 1);
18550
+ }
18551
+
18552
+ return str;
18553
+ }
18554
+ function _addHyphenBeforeUppercase(str) {
18555
+ var ret = str.replace(/([A-Z])/g, '-$1').toLowerCase();
18556
+ while (ret.length && ret[0] == '-') {
18557
+ ret = ret.substr(1);
18558
+ }
18559
+ return ret;
18560
+ }
18561
+
18562
+ // Resolve the template option:
18563
+ // - If it ends with '.html', treat it as a path and fetch the HTML content
18564
+ // - Otherwise, treat it as inline HTML code and return it directly
18565
+ function _resolveTemplateOption(template) {
18566
+ if (!template || typeof template !== 'string') {
18567
+ return Promise.resolve(null);
18568
+ }
18569
+ if (template.toLowerCase().endsWith('.html')) {
18570
+ return _httpGet(template).then(function (html) {
18571
+ return _sanitizeTemplate(html);
18572
+ });
18573
+ }
18574
+ return Promise.resolve(template);
18575
+ }
18576
+
18577
+ function _sanitizeTemplate(template) {
18578
+ if (!template instanceof String) {
18579
+ return template;
18580
+ }
18581
+
18582
+ var result = [...template.matchAll(/(?<=:)[a-zA-Z0-9-_]{1,}(?=\=")/g)];
18583
+ for (var i = 0; i < result.length; ++i) {
18584
+ var propertyName = result[i].toString();
18585
+ var sanitizedPropertyName = _addHyphenBeforeUppercase(propertyName);
18586
+ template = template.replaceAll(':' + propertyName + '=', ':' + sanitizedPropertyName + '=');
18587
+ }
18588
+
18589
+ result = [...template.matchAll(/(?<=@)[a-zA-Z0-9-_]{1,}(?=\=")/g)];
18590
+ for (var i = 0; i < result.length; ++i) {
18591
+ var propertyName = result[i].toString();
18592
+ var sanitizedPropertyName = _addHyphenBeforeUppercase(propertyName);
18593
+ template = template.replaceAll('@' + propertyName + '=', '@' + sanitizedPropertyName + '=');
18594
+ }
18595
+
18596
+ return template;
18597
+ }
18598
+
18599
+ var _root = null;
18600
+ function root() {
18601
+ return _root;
18602
+ };
18603
+
18604
+ function _findRoot(instance) {
18605
+ var globalRoot = exports.root();
18606
+ if (globalRoot) return globalRoot;
18607
+ if (!instance) return null;
18608
+ var current = instance;
18609
+ while (current.parent) {
18610
+ current = current.parent;
18611
+ }
18612
+ return current.proxy || current;
18613
+ }
18614
+
18615
+ exports._rules = [];
18616
+
18617
+ function useRoutes(url) {
18618
+ var rules = _options.httpGetSync(url);
18619
+ rules = JSON.parse(rules);
18620
+ if (!exports._rules) {
18621
+ exports._rules = {};
18622
+ }
18623
+ _combineObject(rules, exports._rules);
18624
+ }
18625
+
18626
+ // Internal
18627
+ function _combineObject(src, dest) {
18628
+ if (!src) {
18629
+ return;
18630
+ }
18631
+
18632
+ var fields = Object.getOwnPropertyNames(src);
18633
+ for (var i = 0; i < fields.length; ++i) {
18634
+ dest[fields[i]] = src[fields[i]];
18635
+ }
18636
+ };
18637
+
18638
+ // Helper: Chain an async lifecycle hook onto an existing one
18639
+ function _chainHook(obj, hookName, fn) {
18640
+ var original = obj[hookName] || function () {};
18641
+ obj[hookName] = function () {
18642
+ var self = this;
18643
+ var result = original.call(self);
18644
+ var p = (result && result instanceof Promise) ? result : Promise.resolve();
18645
+ return p.then(function () {
18646
+ var p2;
18647
+ try {
18648
+ p2 = fn.call(self);
18649
+ } catch (ex) {
18650
+ console.error(ex);
18651
+ }
18652
+ return (p2 && p2 instanceof Promise) ? p2 : Promise.resolve();
18653
+ });
18654
+ };
18655
+ }
18656
+
18657
+ // Helper: Hook setup() to inject $app and optional extras
18658
+ function _hookSetup(opt, extraFn) {
18659
+ var originalSetup = opt.setup || function () {};
18660
+ opt.setup = function (props, context) {
18661
+ originalSetup(props, context);
18662
+ var instance = Vue.getCurrentInstance();
18663
+ instance.$app = exports;
18664
+ if (extraFn) {
18665
+ extraFn.call(this, instance, opt);
18666
+ }
18667
+ if (!instance.$root) {
18668
+ instance.$root = _findRoot(instance);
18669
+ }
18670
+ if (!instance.$parent) {
18671
+ instance.$parent = (instance.parent && instance.parent.proxy) || instance.$root;
18672
+ }
18673
+ };
18674
+ }
18675
+
18676
+ // Helper: Hook data() to pass exports and optionally merge params/query
18677
+ function _hookData(opt, params) {
18678
+ var originalData = opt.data || function () { return {}; };
18679
+ opt.data = function () {
18680
+ var data = originalData.call(this, exports);
18681
+ if (params) {
18682
+ _combineObject(params, data);
18683
+ _parseQueryString(data);
18684
+ }
18685
+ return data;
18686
+ };
18687
+ }
18688
+
18689
+ // Helper: Create PomeloModule require function
18690
+ function _createRequire(path) {
18691
+ if (!PomeloModule) return undefined;
18692
+ return function (script, workingDirectory, mode) {
18693
+ workingDirectory = workingDirectory || PomeloModule.getContainingFolder(path);
18694
+ return PomeloModule.require(script, workingDirectory, mode);
18695
+ };
18696
+ }
18697
+
18698
+ function _getQueryString() {
18699
+ var ret = window.location.search;
18700
+
18701
+ if (window.location.hash.indexOf('?') > 0) {
18702
+ var hashSearch = window.location.hash.substr(window.location.hash.indexOf('?'));
18703
+ if (ret) {
18704
+ ret += '&' + hashSearch.substr(1);
18705
+ } else {
18706
+ ret = hashSearch;
18707
+ }
18708
+ }
18709
+
18710
+ return ret;
18711
+ }
18712
+
18713
+ function _parseQueryString(dest) {
18714
+ var qs = _getQueryString();
18715
+ if (!qs) {
18716
+ return;
18717
+ }
18718
+
18719
+ var str = qs;
18720
+ if (str[0] == '?') {
18721
+ str = str.substr(1);
18722
+ }
18723
+
18724
+ var splited = str.split('&');
18725
+ for (var i = 0; i < splited.length; ++i) {
18726
+ var splited2 = splited[i].split('=');
18727
+ var key = decodeURIComponent(splited2[0]);
18728
+ var val = decodeURIComponent(splited2[1]);
18729
+ _fillObjectField(key, val, dest);
18730
+ }
18731
+ }
18732
+
18733
+ function _resolveModules(modules, viewName) { // viewName is only for parse macro
18734
+ if (!modules) {
18735
+ return Promise.resolve();
18736
+ }
18737
+
18738
+ if (_options.resolveModulesParallelly) {
18739
+ var promises = [];
18740
+ for (var i = 0; i < modules.length; ++i) {
18741
+ promises.push(LoadScript(parseMacroPath(viewName, modules[i])));
18742
+ }
18743
+
18744
+ return Promise.all(promises);
18745
+ } else {
18746
+ var promise = Promise.resolve(null);
18747
+ var makeFunc = function (module) {
18748
+ return function (result) {
18749
+ return LoadScript(parseMacroPath(viewName, module));
18750
+ };
18751
+ };
18752
+ for (var i = 0; i < modules.length; ++i) {
18753
+ var m = modules[i];
18754
+ promise = promise.then(makeFunc(m));
18755
+ }
18756
+ return promise;
18757
+ }
18758
+ }
18759
+
18760
+ function _buildApp(url, params, mobile, parent) {
18761
+ var componentObject = {};
18762
+ return _httpGet(url + '.js')
18763
+ .then(function (js) {
18764
+ var Page = function (options) {
18765
+ componentObject = options;
18766
+ };
18767
+
18768
+ var require = _createRequire(url);
18769
+ try {
18770
+ eval(js + '\r\n//# sourceURL=' + url + '.js');
18771
+ } catch (evalError) {
18772
+ console.error('[PomeUI] Failed to eval component JS. URL: ' + url + '.js', evalError);
18773
+ throw new Error('Failed to eval component JS (' + url + '.js): ' + (evalError.message || evalError));
18774
+ }
18775
+ if (!componentObject || (typeof componentObject !== 'object')) {
18776
+ console.error('[PomeUI] Component JS did not produce a valid component object. URL: ' + url + '.js', 'Got:', componentObject);
18777
+ throw new Error('Component JS (' + url + '.js) did not produce a valid component object. Got: ' + String(componentObject));
18778
+ }
18779
+ hookMountedAndUnmounted(componentObject, url + (mobile ? '.m' : ''));
18780
+ return _resolveModules(componentObject.modules || [], url).then(function () {
18781
+ return Promise.resolve(componentObject)
18782
+ });
18783
+ })
18784
+ .then(function (component) {
18785
+ var htmlPromise;
18786
+ if (mobile) {
18787
+ htmlPromise = _httpExist(url + '.m.html').then(function (res) {
18788
+ return _httpGet(url + (res ? '.m.html' : '.html'));
18789
+ });
18790
+ } else {
18791
+ htmlPromise = _httpGet(url + '.html');
18792
+ }
18793
+ // Load .skeleton.html in parallel; null if not found
18794
+ var skeletonFilePromise = _httpGetSkeletonFile(url + '.skeleton.html');
18795
+
18796
+ // If component.template is specified, resolve it (could be .html path or inline HTML)
18797
+ var templateOptionPromise = component.template
18798
+ ? _resolveTemplateOption(component.template)
18799
+ : Promise.resolve(null);
18800
+
18801
+ return Promise.all([htmlPromise, skeletonFilePromise, templateOptionPromise]).then(function (results) {
18802
+ var template = results[0];
18803
+ var skeletonFileHtml = results[1];
18804
+ var resolvedTemplate = results[2];
18805
+ if (resolvedTemplate) {
18806
+ component.template = resolvedTemplate;
18807
+ } else if (!component.template) {
18808
+ component.template = _sanitizeTemplate(template);
18809
+ }
18810
+ // .skeleton.html file takes top priority over skeleton: true / inline string
18811
+ if (skeletonFileHtml && component.skeleton) {
18812
+ component.skeleton = skeletonFileHtml;
18813
+ }
18814
+ if (component.delayOpen) {
18815
+ var dom = new DOMParser().parseFromString(component.template, 'text/html');
18816
+ var children = dom.querySelector('body').children;
18817
+ for (var i = 0; i < children.length; ++i) {
18818
+ if (children[i].tagName.toUpperCase() != 'DIV') {
18819
+ continue;
18820
+ }
18821
+ if (children[i].getAttribute('v-if') != null || children[i].getAttribute('v-else-if') || children[i].getAttribute('v-else')) {
18822
+ continue;
18823
+ }
18824
+ if (component.skeleton) {
18825
+ // Skeleton mode: delayOpen classes will be added by
18826
+ // _wrapTemplateWithSkeleton on an outer wrapper div.
18827
+ // No need to add them to individual children here.
18828
+ } else {
18829
+ children[i].classList.add('_pome-ui-opened');
18830
+ children[i].classList.add('_pome-ui-opening');
18831
+ }
18832
+ }
18833
+
18834
+ var tpl = template || component.template;
18835
+ var ret = tpl.indexOf('<html') >= 0 ? new XMLSerializer().serializeToString(dom) : dom.querySelector('body').innerHTML;
18836
+ component.template = ret;
18837
+ }
18838
+ _patchComponent(url, component, true);
18839
+ // _wrapTemplateWithSkeleton is deferred to after _loadComponents
18840
+ // so the component skeleton registry is fully populated.
18841
+ return Promise.resolve(component);
18842
+ });
18843
+ })
18844
+ .then(function (component) {
18845
+ _hookSetup(component, function (instance, comp) {
18846
+ instance.$parent = parent || _findRoot(instance);
18847
+ instance.$root = _findRoot(instance) || parent;
18848
+ instance.$view = url;
18849
+ instance.$data = comp.data || function () { return {}; };
18850
+ instance.$created = comp.created || function () { };
18851
+ instance.$mounted = comp.mounted || function () { };
18852
+ instance.$unmounted = comp.unmounted || function () { };
18853
+ instance.$delayClose = comp.delayClose || 0;
18854
+ _attachContainer(instance);
18855
+ });
18856
+
18857
+ _hookData(component, params);
18858
+
18859
+ // Create instance
18860
+ return _resolveModules(component.modules, url).then(function () {
18861
+ var components = component.components || [];
18862
+ var directives = component.directives || [];
18863
+ var _ret;
18864
+
18865
+ // Preload page's own CSS before mount
18866
+ var pageCssPromise = Promise.resolve();
18867
+ var viewName = url + (mobile ? '.m' : '');
18868
+ if (_options.preloadCss && component.style) {
18869
+ pageCssPromise = appendCssReferenceAsync(viewName, component.style);
18870
+ }
18871
+
18872
+ return Promise.all([pageCssPromise, _loadComponents(components, url)]).then(function (results) {
18873
+ var components = results[1];
18874
+ // Wrap skeleton template now that component registry is fully populated.
18875
+ _wrapTemplateWithSkeleton(component);
18876
+ var ret;
18877
+ try {
18878
+ ret = Vue.createApp(component);
18879
+ } catch (createAppError) {
18880
+ console.error('[PomeUI] Vue.createApp failed. URL: ' + url, createAppError);
18881
+ console.error('[PomeUI] Component object:', { template: component.template ? component.template.substring(0, 200) + '...' : '(none)', data: typeof component.data, methods: component.methods ? Object.keys(component.methods) : '(none)' });
18882
+ throw new Error('Vue.createApp failed for URL ' + url + ': ' + (createAppError.message || createAppError));
18883
+ }
18884
+
18885
+ for (var i = 0; i < components.length; ++i) {
18886
+ var com = components[i];
18887
+ ret.component(com.name, com.options);
18888
+ }
18889
+
18890
+ // Inherit parent's registered components
18891
+ if (parent && parent.$ && parent.$.appContext && parent.$.appContext.components) {
18892
+ var parentComps = parent.$.appContext.components;
18893
+ for (var pName in parentComps) {
18894
+ if (!ret._context.components[pName]) {
18895
+ ret.component(pName, parentComps[pName]);
18896
+ }
18897
+ }
18898
+ }
18899
+
18900
+ var originalMountFunc = ret.mount || function () { };
18901
+ ret.mount = function (el) {
18902
+ ret.proxy = originalMountFunc(el);
18903
+ return ret.proxy;
18904
+ }
18905
+
18906
+ _ret = ret;
18907
+ return _loadDirectives(directives, url);
18908
+ }).then(function (directives) {
18909
+ for (var i = 0; i < directives.length; ++i) {
18910
+ var dir = directives[i];
18911
+ _ret.directive(dir.name, dir.options);
18912
+ }
18913
+ return Promise.resolve(_ret);
18914
+ });
18915
+ });
18916
+ });
18917
+ };
18918
+
18919
+ function _replace(source, find, replace) {
18920
+ var idx = source.indexOf(find);
18921
+ if (idx < 0) {
18922
+ return source;
18923
+ }
18924
+
18925
+ var ret = source.substr(0, idx) + replace + source.substr(idx + find.length);
18926
+ return ret;
18927
+ }
18928
+
18929
+ function sleep(ms) {
18930
+ return new Promise(function (res) {
18931
+ setTimeout(function () { res(); }, ms);
18932
+ });
18933
+ };
18934
+
18935
+ function yield() {
18936
+ return sleep(0);
18937
+ }
18938
+
18939
+ function _attachContainer(instance) {
18940
+ if (!instance) {
18941
+ console.warn('Invalid view model');
18942
+ }
18943
+
18944
+ if (!instance.$containers) {
18945
+ instance.$containers = [];
18946
+ }
18947
+
18948
+ if (!instance.$containers) {
18949
+ instance.$containers = [];
18950
+ }
18951
+
18952
+ var containers = instance.$containers;
18953
+ instance.$container = function (el) {
18954
+ var container = containers.filter(x => x.selector == el)[0];
18955
+ if (!container) {
18956
+ container = {
18957
+ element: document.querySelector(el),
18958
+ selector: el,
18959
+ open: function (url, params) {
18960
+ var mobile = _options.mobile();
18961
+ var currentProxy = null;
18962
+ if (instance.proxy) {
18963
+ currentProxy = instance.proxy;
18964
+ }
18965
+ if (instance.$ && instance.$.proxy) {
18966
+ currentProxy = instance.$.proxy;
18967
+ }
18968
+
18969
+ var p = Promise.resolve();
18970
+ if (!this.active || this.active.$view != url || !_options.reuseContainerActiveView()) {
18971
+ p = this.close();
18972
+ }
18973
+
18974
+ var self = this;
18975
+
18976
+ return p.then(function () {
18977
+ var p = Promise.resolve();
18978
+ params = generateParametersFromRoute(params);
18979
+ _parseQueryString(params);
18980
+ if (_options.reuseContainerActiveView() && self.active?.$view == url) {
18981
+ var reuseComponentFunc = function (container) {
18982
+ if (!container || !container.active) {
18983
+ return p;
18984
+ }
18985
+
18986
+ if (_options.callUnmountedWhenReuseContainerActiveView(container.active.$view)) {
18987
+ p = p.then(function () {
18988
+ if (!container.active || !container.active.$unmounted) return Promise.resolve();
18989
+ var val = container.active.$unmounted();
18990
+ if (val instanceof Promise) {
18991
+ return val;
18992
+ } else {
18993
+ return Promise.resolve();
18994
+ }
18995
+ });
18996
+ }
18997
+ p = p.then(function () {
18998
+ if (!container.active || !container.active.$data) return Promise.resolve();
18999
+ var initData = container.active.$data();
19000
+ if (_options.resetDataWhenReuseContainerActiveView()) {
19001
+ _combineObject(initData, container.active);
19002
+ }
19003
+ _combineObject(params, container.active);
19004
+ return Promise.resolve();
19005
+ });
19006
+ if (_options.callCreatedWhenReuseContainerActiveView(container.active.$view)) {
19007
+ p = p.then(function () {
19008
+ if (!container.active || !container.active.$created) return Promise.resolve();
19009
+ var val = container.active.$created();
19010
+ if (val instanceof Promise) {
19011
+ return val;
19012
+ } else {
19013
+ return Promise.resolve();
19014
+ }
19015
+ });
19016
+ }
19017
+ if (_options.callMountedWhenReuseContainerActiveView(container.active.$view)) {
19018
+ p = p.then(function () {
19019
+ if (!container.active || !container.active.$mounted) return Promise.resolve();
19020
+ var val = container.active.$mounted();
19021
+ if (val instanceof Promise) {
19022
+ return val;
19023
+ } else {
19024
+ return Promise.resolve();
19025
+ }
19026
+ });
19027
+ }
19028
+
19029
+ if (container.active.$containers && container.active.$containers.length) {
19030
+ for (var i = 0; i < container.active.$containers.length; ++i) {
19031
+ reuseComponentFunc(container.active.$containers[i]);
19032
+ }
19033
+ }
19034
+
19035
+ return p.then(function () { if (!container.active) return Promise.resolve(null); container.active.$forceUpdate(); return Promise.resolve(container.active) });
19036
+
19037
+ }
19038
+ return Promise.resolve(reuseComponentFunc(self));
19039
+ }
19040
+
19041
+ var _result;
19042
+ var retryLeft = 20;
19043
+ var _lastMountError = null;
19044
+ var buildRetryPromise = function () {
19045
+ return new Promise(function (res, rej) {
19046
+ var containerEl = document.querySelector(self.selector);
19047
+ if (!containerEl) {
19048
+ if (--retryLeft > 0) {
19049
+ return res(sleep(50).then(function () {
19050
+ return buildRetryPromise();
19051
+ }));
19052
+ } else {
19053
+ var msg = 'Mount component to ' + self.selector + ' failed: container element not found in DOM after retries. URL: ' + url;
19054
+ console.error('[PomeUI]', msg);
19055
+ return rej(new Error(msg));
19056
+ }
19057
+ }
19058
+
19059
+ var active;
19060
+ try {
19061
+ active = _result.mount(self.selector);
19062
+ } catch (mountError) {
19063
+ _lastMountError = mountError;
19064
+ console.error('[PomeUI] Mount component to ' + self.selector + ' threw an error. URL: ' + url, mountError);
19065
+ return rej(new Error('Mount component to ' + self.selector + ' failed: ' + (mountError.message || mountError) + '. URL: ' + url));
19066
+ }
19067
+
19068
+ if (active) {
19069
+ self.active = active;
19070
+ return res(active);
19071
+ }
19072
+
19073
+ if (--retryLeft > 0) {
19074
+ return res(sleep(50).then(function () {
19075
+ return buildRetryPromise();
19076
+ }));
19077
+ } else {
19078
+ var detail = 'mount() returned ' + (active === null ? 'null' : (active === undefined ? 'undefined' : String(active)));
19079
+ if (_lastMountError) {
19080
+ detail += '; last error: ' + (_lastMountError.message || _lastMountError);
19081
+ }
19082
+ var msg = 'Mount component to ' + self.selector + ' failed: ' + detail + '. URL: ' + url;
19083
+ console.error('[PomeUI]', msg);
19084
+ console.error('[PomeUI] Diagnostics:', {
19085
+ selector: self.selector,
19086
+ url: url,
19087
+ containerElement: containerEl,
19088
+ containerInnerHTML: containerEl ? containerEl.innerHTML.substring(0, 200) : '(N/A)',
19089
+ appResult: _result,
19090
+ mobile: mobile
19091
+ });
19092
+ return rej(new Error(msg));
19093
+ }
19094
+ });
19095
+ };
19096
+
19097
+ return _buildApp(url, params, mobile, currentProxy).then(function (result) {
19098
+ _result = result;
19099
+ return buildRetryPromise();
19100
+ }).catch(function (err) {
19101
+ console.error('[PomeUI] Failed to build or mount component. URL: ' + url + ', Selector: ' + self.selector, err);
19102
+ return Promise.reject(err);
19103
+ });
19104
+ });
19105
+ },
19106
+ close: async function (recurse = true) {
19107
+ async function liftClose(container) {
19108
+ if (container.active && container.active.$) {
19109
+ if (recurse) {
19110
+ for (var i = 0; i < container.active.$containers.length; ++i) {
19111
+ liftClose(container.active.$containers[i]);
19112
+ }
19113
+ }
19114
+
19115
+ if (container.active.$delayClose) {
19116
+ try {
19117
+ if (container.active.$el) {
19118
+ container.active.$el.classList?.add('_pome-ui-closing');
19119
+ }
19120
+ } catch (ex) {
19121
+ console.warn(ex);
19122
+ }
19123
+ console.log(`sleeping ${container.active.$delayClose}ms...`);
19124
+ await sleep(container.active.$delayClose);
19125
+ }
19126
+
19127
+ try {
19128
+ container.active.$.appContext.app.unmount();
19129
+ } catch (ex) {
19130
+ console.warn(ex);
19131
+ }
19132
+ container.active = null;
19133
+ }
19134
+ }
19135
+
19136
+ await liftClose(this);
19137
+ },
19138
+ active: null
19139
+ };
19140
+ containers.push(container);
19141
+ }
19142
+ return container;
19143
+ };
19144
+ };
19145
+
19146
+ function Root(options, el, layout) {
19147
+ options = options || {};
19148
+ _hookSetup(options, function (instance) {
19149
+ instance.$parent = parent || _findRoot(instance);
19150
+ instance.$root = _findRoot(instance) || parent;
19151
+ instance.$onUpdating = options.onUpdating;
19152
+ if (layout) {
19153
+ instance.$layout = layout;
19154
+ instance.$view = layout;
19155
+ }
19156
+ _attachContainer(instance);
19157
+ });
19158
+
19159
+ return _resolveModules(options.modules, layout).then(function () {
19160
+ var _app;
19161
+
19162
+ return _loadComponents(options.components || [], layout)
19163
+ .then(function (components) {
19164
+ // Inject layout skeleton overlay now that component registry is populated.
19165
+ if (options._pomeLayoutSkeleton) {
19166
+ var ls = options._pomeLayoutSkeleton;
19167
+ var skHtml = ls.skeletonOverride
19168
+ ? ls.skeletonOverride
19169
+ : (function () {
19170
+ var html = _generateSkeletonHtml(ls.skeletonBody);
19171
+ // Post-process: remove empty top-level nodes (modals etc.),
19172
+ // set flex:1 on the main content area next to the sidebar.
19173
+ var tmp = document.createElement('div');
19174
+ tmp.innerHTML = html;
19175
+ var topChildren = Array.from(tmp.children);
19176
+ var sidebarIdx = -1;
19177
+ for (var ci = 0; ci < topChildren.length; ci++) {
19178
+ var ch = topChildren[ci];
19179
+ if (!ch.innerHTML.trim()) {
19180
+ tmp.removeChild(ch);
19181
+ topChildren = Array.from(tmp.children);
19182
+ ci--;
19183
+ continue;
19184
+ }
19185
+ if (sidebarIdx < 0 && /\bwidth\s*:/.test(ch.getAttribute('style') || '')) {
19186
+ sidebarIdx = ci;
19187
+ } else if (sidebarIdx >= 0 && ci === sidebarIdx + 1) {
19188
+ ch.style.flex = '1';
19189
+ ch.style.minWidth = '0';
19190
+ ch.style.overflow = 'hidden';
19191
+ }
19192
+ }
19193
+ return tmp.innerHTML;
19194
+ })();
19195
+ var appEl = document.querySelector(ls.appId);
19196
+ if (appEl) {
19197
+ var skDiv = document.createElement('div');
19198
+ skDiv.setAttribute('v-if', 'pomeSkeletonLoading || pomeSkeletonCloaked');
19199
+ skDiv.className = '_pome-skeleton _pome-layout-skeleton ' + ls.bodyClass;
19200
+ if (ls.overlayStyle) skDiv.setAttribute('style', ls.overlayStyle);
19201
+ skDiv.innerHTML = skHtml;
19202
+ appEl.insertBefore(skDiv, appEl.firstChild);
19203
+ }
19204
+ delete options._pomeLayoutSkeleton;
19205
+ }
19206
+ var app = Vue.createApp(options || {});
19207
+ for (var i = 0; i < components.length; ++i) {
19208
+ var com = components[i];
19209
+ app.component(com.name, com.options);
19210
+ }
19211
+
19212
+ _app = app;
19213
+ return _loadDirectives(options.directives || [], layout);
19214
+ })
19215
+ .then(function (directives) {
19216
+ for (var i = 0; i < directives.length; ++i) {
19217
+ var dir = directives[i];
19218
+ app.directive(dir.name, dir.options);
19219
+ }
19220
+
19221
+ _root = _app.mount(el);
19222
+ _root.$.proxy = _root;
19223
+ var _mountEl = document.querySelector(el);
19224
+ if (_mountEl) {
19225
+ _mountEl.classList.remove('_pome-vue-cloak');
19226
+ }
19227
+ });
19228
+ });
19229
+ }
19230
+
19231
+ function mount() {
19232
+ function parseHref(el) {
19233
+ if (!el) {
19234
+ return null;
19235
+ }
19236
+
19237
+ if (!el.getAttribute) {
19238
+ return null;
19239
+ }
19240
+
19241
+ var target = el.getAttribute('target') || '_self';
19242
+ var staticAttribute = el.getAttribute('static-link') || el.getAttribute('v-static') || el.getAttribute('pomelo-static');
19243
+
19244
+ if (staticAttribute == null
19245
+ && target.toLowerCase() == '_self'
19246
+ && el.tagName.toLowerCase() == "a") {
19247
+ return el.getAttribute('href');
19248
+ }
19249
+
19250
+ return parseHref(el.parentNode);
19251
+ }
19252
+
19253
+ window.addEventListener('click', function (e) {
19254
+ if (!e) return;
19255
+ var href = parseHref(e.target);
19256
+ if (href) {
19257
+ if (e.ctrlKey || e.metaKey) {
19258
+ return;
19259
+ }
19260
+ exports.redirect(href);
19261
+ e.preventDefault();
19262
+ return;
19263
+ }
19264
+ });
19265
+
19266
+ window.onpopstate = function () {
19267
+ UpdateLayout();
19268
+ };
19269
+
19270
+ return UpdateLayout();
19271
+ }
19272
+
19273
+ function UseConfig(options) {
19274
+ _combineObject(options, _options);
19275
+ }
19276
+
19277
+ function MapRoute(rule, view) {
19278
+ if (!exports._rules) {
19279
+ exports._rules = {};
19280
+ }
19281
+
19282
+ exports._rules[rule] = view;
19283
+ }
19284
+
19285
+ function ForceUpdate(proxy = exports.root()) {
19286
+ if (!proxy) return;
19287
+ proxy.$forceUpdate();
19288
+ if (proxy.$containers) {
19289
+ for (var i = 0; i < proxy.$containers.length; ++i) {
19290
+ if (proxy.$containers[i].active) {
19291
+ ForceUpdate(proxy.$containers[i].active);
19292
+ }
19293
+ }
19294
+ }
19295
+ }
19296
+
19297
+ function MatchRoute() {
19298
+ function replaceAll(str, s1, s2) {
19299
+ return str.replace(new RegExp(s1, "g"), s2);
19300
+ };
19301
+
19302
+ function matchAll(str) {
19303
+ var ret = [];
19304
+ if (!str) {
19305
+ return ret;
19306
+ }
19307
+
19308
+ var currentBrace = -1;
19309
+ var parenthesis = 0;
19310
+ for (var i = 0; i < str.length; ++i) {
19311
+ if (str[i] == '{' && !parenthesis) {
19312
+ currentBrace = i;
19313
+ parenthesis = 0;
19314
+ } else if (str[i] == '(') {
19315
+ ++parenthesis;
19316
+ } else if (str[i] == ')') {
19317
+ --parenthesis;
19318
+ } else if (str[i] == '}' && !parenthesis) {
19319
+ ret.push(str.substring(currentBrace, i + 1));
19320
+ }
19321
+ }
19322
+
19323
+ return ret;
19324
+ }
19325
+
19326
+ function unwrapBrackets(src) {
19327
+ if (src[0] === '{') {
19328
+ return src.substr(1, src.length - 2);
19329
+ } else {
19330
+ return src;
19331
+ }
19332
+ }
19333
+
19334
+ function regExpEscape(str) {
19335
+ return str.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
19336
+ }
19337
+
19338
+ function getRegExpPatterns(str) {
19339
+ var cnt = 0;
19340
+ if (str) {
19341
+ for (var i = 0; i < str.length; ++i) {
19342
+ if (str[i] == '(') {
19343
+ ++cnt;
19344
+ }
19345
+ if (str[i] == '?' && i > 0 && str[i - 1] == '(') {
19346
+ --cnt;
19347
+ }
19348
+ }
19349
+ }
19350
+ return cnt;
19351
+ }
19352
+
19353
+ function getSanitizedHash() {
19354
+ var hash = window.location.hash;
19355
+ var idx = hash.indexOf('?');
19356
+ if (idx == -1) {
19357
+ return hash;
19358
+ }
19359
+ return hash.substr(0, idx);
19360
+ }
19361
+
19362
+ var keys = Object.getOwnPropertyNames(exports._rules);
19363
+ for (var i = 0; i < keys.length; ++i) {
19364
+ var rule = keys[i];
19365
+ var isHash = rule[0] == '#';
19366
+ var view = exports._rules[keys[i]];
19367
+ var matches = matchAll(rule);
19368
+ var params = [];
19369
+ var patterns = [];
19370
+ for (var j = 0; j < matches.length; ++j) {
19371
+ var param = matches[j];
19372
+ var k = unwrapBrackets(param);
19373
+ regex = '([^/]+)';
19374
+ if (k[0] == '*') {
19375
+ regex = '(.*)';
19376
+ k = k.substr(1);
19377
+ }
19378
+ if (k.indexOf('=') > 0) {
19379
+ var value = k.substr(k.indexOf('=') + 1);
19380
+ regex = `(${regExpEscape(value)})`;
19381
+ params.push(k.substr(0, k.indexOf('=')));
19382
+ } else if (param.indexOf(':') > 0) {
19383
+ regex = param.substr(param.indexOf(':') + 1)
19384
+ regex = regex.substr(0, regex.length - 1);
19385
+ params.push(k.substr(0, k.indexOf(':')));
19386
+ } else {
19387
+ params.push(k);
19388
+ }
19389
+ patterns.push(getRegExpPatterns(regex));
19390
+ rule = _replace(rule, param, regex);
19391
+ }
19392
+
19393
+ var parsedReg = new RegExp('^' + rule + '$');
19394
+ var matches = parsedReg.exec(isHash ? getSanitizedHash() || '#' : window.location.pathname);
19395
+ if (matches) {
19396
+ var ret = {
19397
+ view: view,
19398
+ params: []
19399
+ };
19400
+ var _matches = matches;
19401
+ matches = [];
19402
+ var index = 0;
19403
+ for (var j = 1; j < _matches.length; ++j) {
19404
+ matches.push(_matches[j]);
19405
+ for (var k = 0; k < patterns[index] - 1; ++k) {
19406
+ ++j;
19407
+ }
19408
+ ++index;
19409
+ }
19410
+ var values = matches.map(function (x) { return decodeURIComponent(x); });
19411
+ for (var j = 0; j < params.length; ++j) {
19412
+ ret.params.push({ key: params[j], value: values[j] });
19413
+ }
19414
+ return ret;
19415
+ }
19416
+ }
19417
+
19418
+ return null;
19419
+ }
19420
+
19421
+ function _fillObjectField(param, value, dest) {
19422
+ if (!dest) {
19423
+ return;
19424
+ }
19425
+
19426
+ var splited = param.split('.');
19427
+ for (var i = 0; i < splited.length - 1; ++i) {
19428
+ if (!dest[splited[i]]) {
19429
+ dest[splited[i]] = {}
19430
+ }
19431
+ dest = dest[splited[i]];
19432
+ }
19433
+ dest[splited[splited.length - 1]] = value;
19434
+ }
19435
+ function _applyLayoutHtml(layout) {
19436
+ return _httpGet(layout + (_options.mobile() ? '.m.html' : '.html')).then(function (layoutHtml) {
19437
+ var htmlBeginTagIndex = layoutHtml.indexOf('<html');
19438
+ var htmlBeginTagIndex2 = layoutHtml.indexOf('>', htmlBeginTagIndex);
19439
+ layoutHtml = layoutHtml.substr(htmlBeginTagIndex2 + 1);
19440
+ var htmlEndTagIndex = layoutHtml.lastIndexOf('</html>');
19441
+ layoutHtml = layoutHtml.substr(0, htmlEndTagIndex);
19442
+ layoutHtml = _patchTemplate(layout, layoutHtml);
19443
+ document.querySelector('html').innerHTML = layoutHtml;
19444
+
19445
+ var ticks = new Date().getTime();
19446
+ var appId = 'pomelo-' + ticks;
19447
+ _ensureVueCloakStyle();
19448
+ document.querySelector('body').innerHTML = '<div id="' + appId + '" class="_pome-vue-cloak">' + document.querySelector('body').innerHTML + '</div>';
19449
+
19450
+ return Promise.resolve(appId);
19451
+ })
19452
+ }
19453
+
19454
+ function generateParametersFromRoute(params = {}) {
19455
+ var route = null;
19456
+ route = MatchRoute();
19457
+ if (route == null) {
19458
+ try {
19459
+ _options.onNotFound(window.location.pathname + window.location.search);
19460
+ return;
19461
+ } catch (ex) {
19462
+ throw "No available route found.";
19463
+ }
19464
+ }
19465
+
19466
+ for (var i = 0; i < route.params.length; ++i) {
19467
+ var param = route.params[i];
19468
+ _fillObjectField(param.key, param.value, params);
19469
+ }
19470
+
19471
+ return params;
19472
+ }
19473
+
19474
+ function parseMacroPath(viewName, href) {
19475
+ if (!href) {
19476
+ href = '';
19477
+ }
19478
+
19479
+ if (href.indexOf('@') < 0) {
19480
+ return href;
19481
+ }
19482
+
19483
+ var containingFolder = '/';
19484
+ var folderIndex = viewName.lastIndexOf('/');
19485
+ if (folderIndex >= 0) {
19486
+ containingFolder = viewName.substr(0, folderIndex);
19487
+ }
19488
+
19489
+ href = href.replaceAll('@(view)', viewName)
19490
+ .replaceAll('@(js)', viewName + '.js')
19491
+ .replaceAll('@(html)', viewName + '.html')
19492
+ .replaceAll('@(mobileHtml)', viewName + '.m.html')
19493
+ .replaceAll('@(css)', viewName + '.css')
19494
+ .replaceAll('@(mobileCss)', viewName + '.m.css')
19495
+ .replaceAll('@(less)', viewName + '.less')
19496
+ .replaceAll('@(mobileLess)', viewName + '.m.less')
19497
+ .replaceAll('@(mobileSass)', viewName + '.m.sass')
19498
+ .replaceAll('@(mobileScss)', viewName + '.m.scss')
19499
+ .replaceAll('@(containingFolder)', containingFolder);
19500
+
19501
+ if (href.length && href[0] != '/' && href.indexOf('http') == -1) {
19502
+ href = getContainingFolder(viewName) + href;
19503
+ }
19504
+
19505
+ return href;
19506
+ }
19507
+
19508
+ function appendCssReference(view, style) {
19509
+ if (typeof style == 'boolean') {
19510
+ var href = view + '.css';
19511
+ if (_options.version) {
19512
+ href += '?v=' + _options.version;
19513
+ }
19514
+ internalAppendCssReference(view, href);
19515
+ } else if (typeof style == 'string') {
19516
+ var href = parseMacroPath(view, style);
19517
+ href = resolveRelativePath(href, getContainingFolder(view));
19518
+ if (_options.version) {
19519
+ if (href.indexOf('>') < 0) {
19520
+ href += '?v=' + _options.version;
19521
+ } else {
19522
+ href += '&v=' + _options.version;
19523
+ }
19524
+ }
19525
+ internalAppendCssReference(view, href);
19526
+ } else if (style instanceof Array) {
19527
+ for (var i = 0; i < style.length; ++i) {
19528
+ if (typeof style[i] != 'string') {
19529
+ continue;
19530
+ }
19531
+ var href = parseMacroPath(view, style[i]);
19532
+ href = resolveRelativePath(href, getContainingFolder(view));
19533
+ if (_options.version) {
19534
+ if (href.indexOf('>') < 0) {
19535
+ href += '?v=' + _options.version;
19536
+ } else {
19537
+ href += '&v=' + _options.version;
19538
+ }
19539
+ }
19540
+ internalAppendCssReference(view, href);
19541
+ }
19542
+ } else {
19543
+ throw 'style type not supported'
19544
+ }
19545
+ }
19546
+
19547
+ function getContainingFolder(absolutePath) {
19548
+ if (!absolutePath) {
19549
+ console.warn('getContainingFolder: absolutePath is invalid');
19550
+ }
19551
+
19552
+ var slashIndex = absolutePath.lastIndexOf('/');
19553
+ if (slashIndex < 0) {
19554
+ return '/';
19555
+ }
19556
+
19557
+ return absolutePath.substr(0, slashIndex) + '/';
19558
+ }
19559
+
19560
+ function internalAppendCssReference(viewName, href) {
19561
+ if (document.querySelectorAll('link[data-style="' + viewName + '"][href="' + href + '"]').length) {
19562
+ return;
19563
+ }
19564
+
19565
+ var link = document.createElement('link');
19566
+ link.rel = 'stylesheet';
19567
+ link.type = 'text/' + getStyleSheetType(href);
19568
+ link.setAttribute('data-style', viewName)
19569
+ link.href = href;
19570
+ try {
19571
+ document.querySelector('head').appendChild(link);
19572
+ } catch (ex) { }
19573
+ }
19574
+
19575
+ function internalAppendCssReferenceAsync(viewName, href) {
19576
+ if (document.querySelectorAll('link[data-style="' + viewName + '"][href="' + href + '"]').length) {
19577
+ return Promise.resolve();
19578
+ }
19579
+
19580
+ return new Promise(function (resolve) {
19581
+ var link = document.createElement('link');
19582
+ link.rel = 'stylesheet';
19583
+ link.type = 'text/' + getStyleSheetType(href);
19584
+ link.setAttribute('data-style', viewName);
19585
+ var resolved = false;
19586
+ function onReady() {
19587
+ if (resolved) return;
19588
+ resolved = true;
19589
+ resolve();
19590
+ }
19591
+ setTimeout(onReady, 50);
19592
+ link.onload = onReady;
19593
+ link.onerror = onReady;
19594
+ link.href = href;
19595
+ try {
19596
+ document.querySelector('head').appendChild(link);
19597
+ } catch (ex) {
19598
+ resolve();
19599
+ }
19600
+ });
19601
+ }
19602
+
19603
+ function appendCssReferenceAsync(view, style) {
19604
+ var promises = [];
19605
+ if (typeof style == 'boolean') {
19606
+ var href = view + '.css';
19607
+ if (_options.version) {
19608
+ href += '?v=' + _options.version;
19609
+ }
19610
+ promises.push(internalAppendCssReferenceAsync(view, href));
19611
+ } else if (typeof style == 'string') {
19612
+ var href = parseMacroPath(view, style);
19613
+ href = resolveRelativePath(href, getContainingFolder(view));
19614
+ if (_options.version) {
19615
+ if (href.indexOf('>') < 0) {
19616
+ href += '?v=' + _options.version;
19617
+ } else {
19618
+ href += '&v=' + _options.version;
19619
+ }
19620
+ }
19621
+ promises.push(internalAppendCssReferenceAsync(view, href));
19622
+ } else if (style instanceof Array) {
19623
+ for (var i = 0; i < style.length; ++i) {
19624
+ if (typeof style[i] != 'string') {
19625
+ continue;
19626
+ }
19627
+ var href = parseMacroPath(view, style[i]);
19628
+ href = resolveRelativePath(href, getContainingFolder(view));
19629
+ if (_options.version) {
19630
+ if (href.indexOf('>') < 0) {
19631
+ href += '?v=' + _options.version;
19632
+ } else {
19633
+ href += '&v=' + _options.version;
19634
+ }
19635
+ }
19636
+ promises.push(internalAppendCssReferenceAsync(view, href));
19637
+ }
19638
+ }
19639
+ return Promise.all(promises);
19640
+ }
19641
+
19642
+ function getStyleSheetType(styleSheetUrl) {
19643
+ var questionMarkIndex = styleSheetUrl.lastIndexOf('?');
19644
+ if (questionMarkIndex >= 0) {
19645
+ styleSheetUrl = styleSheetUrl.substr(0, questionMarkIndex);
19646
+ }
19647
+
19648
+ var dotIndex = styleSheetUrl.lastIndexOf('.');
19649
+ if (dotIndex < 0) {
19650
+ return null;
19651
+ }
19652
+
19653
+ return styleSheetUrl.substr(dotIndex + 1).toLowerCase();
19654
+ }
19655
+
19656
+ function removeCssReference(view) {
19657
+ if (!_options.removeStyleWhenUnmount) {
19658
+ return;
19659
+ }
19660
+
19661
+ var dom = document.querySelectorAll('link[data-style="' + view + '"]');
19662
+ if (dom && dom.length) {
19663
+ for (var i = 0; i < dom.length; ++i) {
19664
+ dom[i].remove();
19665
+ }
19666
+ }
19667
+ }
19668
+
19669
+ function hookMountedAndUnmounted(options, view) {
19670
+ if (!options) {
19671
+ return;
19672
+ }
19673
+
19674
+ if (!options.mounted) {
19675
+ options.mounted = function () { };
19676
+ }
19677
+
19678
+ if (!options.unmounted) {
19679
+ options.unmounted = function () { };
19680
+ }
19681
+
19682
+ if (!options.created) {
19683
+ options.created = function () { };
19684
+ }
19685
+
19686
+ if (options.style || options.skeleton) {
19687
+ var originalCreated = options.created;
19688
+ options.created = function () {
19689
+ if (options.style) {
19690
+ if (!_css[view]) {
19691
+ _css[view] = 0;
19692
+ }
19693
+ if (_css[view] == 0) {
19694
+ if (_options.preloadCss) {
19695
+ this._cssLoadPromise = appendCssReferenceAsync(view, options.style);
19696
+ } else {
19697
+ appendCssReference(view, options.style);
19698
+ }
19699
+ }
19700
+ ++_css[view];
19701
+ }
19702
+
19703
+ this.createdPromise = Promise.resolve();
19704
+ var ret = originalCreated.call(this);
19705
+ if (ret instanceof Promise) {
19706
+ this.createdPromise = ret;
19707
+ if (options.skeleton) {
19708
+ var self = this;
19709
+ var skeletonShowing = false;
19710
+ var resolved = false;
19711
+ // Only activate the skeleton if the promise is still pending
19712
+ // after skeletonDelay ms. If it resolves faster, skip the
19713
+ // skeleton entirely to avoid a flash.
19714
+ var skeletonDelay = typeof options.skeletonDelay === 'number'
19715
+ ? options.skeletonDelay : 1000;
19716
+ var skeletonTimer = setTimeout(function () {
19717
+ if (resolved) return;
19718
+ skeletonShowing = true;
19719
+ self.pomeSkeletonCloaked = false;
19720
+ self.pomeSkeletonLoading = true;
19721
+ // Skeleton is now visible. If delayOpen is also set, kick
19722
+ // off its animation so it's primed when skeleton disappears.
19723
+ if (options.delayOpen) {
19724
+ self.$nextTick(function () {
19725
+ requestAnimationFrame(function () {
19726
+ requestAnimationFrame(function () {
19727
+ self.pomeDelayOpening = false;
19728
+ });
19729
+ });
19730
+ setTimeout(function () {
19731
+ self.pomeDelayOpened = false;
19732
+ }, options.delayOpen);
19733
+ });
19734
+ }
19735
+ }, skeletonDelay);
19736
+ ret.then(function () {
19737
+ resolved = true;
19738
+ clearTimeout(skeletonTimer);
19739
+ self.pomeSkeletonCloaked = false;
19740
+ self.pomeSkeletonLoading = false;
19741
+ // Fast path: resolved before skeleton appeared �?still need
19742
+ // to run the delayOpen animation now.
19743
+ if (!skeletonShowing && options.delayOpen) {
19744
+ self.$nextTick(function () {
19745
+ requestAnimationFrame(function () {
19746
+ requestAnimationFrame(function () {
19747
+ self.pomeDelayOpening = false;
19748
+ });
19749
+ });
19750
+ setTimeout(function () {
19751
+ self.pomeDelayOpened = false;
19752
+ }, options.delayOpen);
19753
+ });
19754
+ }
19755
+ }).catch(function (err) {
19756
+ resolved = true;
19757
+ clearTimeout(skeletonTimer);
19758
+ self.pomeSkeletonCloaked = false;
19759
+ self.pomeSkeletonLoading = false;
19760
+ console.error('[SKELETON] created Promise REJECTED:', err);
19761
+ });
19762
+ }
19763
+ } else if (options.skeleton) {
19764
+ // Sync created �?nothing to wait for, ensure skeleton is off.
19765
+ this.pomeSkeletonCloaked = false;
19766
+ this.pomeSkeletonLoading = false;
19767
+ // created() didn't return a Promise, so the skeleton
19768
+ // timer / promise path above won't run. We still need
19769
+ // to kick off the delayOpen animation that was deferred
19770
+ // under the assumption that skeleton would manage it.
19771
+ if (options.delayOpen) {
19772
+ var self = this;
19773
+ self.$nextTick(function () {
19774
+ requestAnimationFrame(function () {
19775
+ requestAnimationFrame(function () {
19776
+ self.pomeDelayOpening = false;
19777
+ });
19778
+ });
19779
+ setTimeout(function () {
19780
+ self.pomeDelayOpened = false;
19781
+ }, options.delayOpen);
19782
+ });
19783
+ }
19784
+ }
19785
+
19786
+ return ret;
19787
+ };
19788
+ }
19789
+
19790
+ var originalMounted = options.mounted;
19791
+ options.mounted = function () {
19792
+ // CSS cloak: hide element until CSS is fully loaded
19793
+ if (_options.preloadCss && this._cssLoadPromise) {
19794
+ _ensureCssCloakStyle();
19795
+ var el = this.$el;
19796
+ if (el && el.nodeType === 1) {
19797
+ el.classList.add('_pome-css-cloak');
19798
+ this._cssLoadPromise.then(function () {
19799
+ el.classList.remove('_pome-css-cloak');
19800
+ });
19801
+ }
19802
+ }
19803
+
19804
+ // Remove opening class if needed
19805
+ if (options.delayOpen && !options.skeleton) {
19806
+ var self = this;
19807
+ var delayOpenFunc = function () {
19808
+ requestAnimationFrame(function () {
19809
+ requestAnimationFrame(function () {
19810
+ if (!self.$el || !self.$el.parentNode) return;
19811
+ var doms = self.$el.parentNode.querySelectorAll('._pome-ui-opening');
19812
+ for (var i = 0; i < doms.length; ++i) {
19813
+ doms[i].classList.remove('_pome-ui-opening');
19814
+ }
19815
+ });
19816
+ });
19817
+
19818
+ setTimeout(function () {
19819
+ if (!self.$el || !self.$el.parentNode) return;
19820
+ var doms = self.$el.parentNode.querySelectorAll('._pome-ui-opened');
19821
+ for (var i = 0; i < doms.length; ++i) {
19822
+ doms[i].classList.remove('_pome-ui-opened');
19823
+ }
19824
+ }, options.delayOpen);
19825
+ };
19826
+
19827
+ (self.createdPromise || Promise.resolve()).then(function () {
19828
+ delayOpenFunc();
19829
+ });
19830
+ }
19831
+
19832
+ return originalMounted.call(this);
19833
+ };
19834
+
19835
+ var originalUnmounted = options.unmounted;
19836
+ options.unmounted = function () {
19837
+ if (options.style) {
19838
+ if (!_css[view]) {
19839
+ return originalUnmounted.call(this);
19840
+ }
19841
+
19842
+ --_css[view];
19843
+ if (_css[view] <= 0) {
19844
+ removeCssReference(view);
19845
+ delete _css[view];
19846
+ }
19847
+ }
19848
+ return originalUnmounted.call(this);
19849
+ };
19850
+ }
19851
+
19852
+ function pomeUiPassTitle(arr) {
19853
+ if (arr) {
19854
+ this.pomeUiSubTitles = arr;
19855
+ }
19856
+
19857
+ var parents = JSON.parse(JSON.stringify(this.pomeUiSubTitles));
19858
+ if (this.title) {
19859
+ parents.push(this.title);
19860
+ }
19861
+
19862
+ var p = this.$parent;
19863
+ while (p && p != window && !p.pomeUiPassTitle) {
19864
+ p = p.$parent;
19865
+ }
19866
+
19867
+ if (p && p != window && p.pomeUiPassTitle) {
19868
+ p.pomeUiPassTitle(parents);
19869
+ } else {
19870
+ document.querySelector('title').innerHTML = _options.generateTitle(parents);
19871
+ }
19872
+ }
19873
+
19874
+ function UpdateLayout() {
19875
+ var mobile = _options.mobile();
19876
+ var params = {};
19877
+ var route = null;
19878
+ var layout = _options.layout;
19879
+
19880
+ route = MatchRoute();
19881
+ params = generateParametersFromRoute();
19882
+
19883
+ var _def;
19884
+ var viewName = route.view + (_options.mobile() ? '.m' : '');
19885
+ return _httpGet(route.view + '.js').then(function (def) {
19886
+ _def = def;
19887
+ var modules = null;
19888
+ var _opt;
19889
+ var Page = function (options) {
19890
+ _opt = options;
19891
+ layout = options.layout || layout;
19892
+ modules = options.modules;
19893
+ };
19894
+
19895
+ var require = _createRequire(route.view);
19896
+ def = eval(def + '\r\n//# sourceURL=' + route.view + '.js');
19897
+ hookMountedAndUnmounted(_opt, viewName);
19898
+ return _resolveModules(modules, viewName);
19899
+ }).then(function () {
19900
+ if (exports.root() && exports.root().$layout) {
19901
+ if (exports.root().$layout === layout) {
19902
+ _parseQueryString(params);
19903
+ var fields = Object.getOwnPropertyNames(params);
19904
+ for (var i = 0; i < fields.length; ++i) {
19905
+ var val = params[fields[i]];
19906
+ exports.root()[fields[i]] = val;
19907
+ }
19908
+
19909
+ return exports.root().$containers[0].open(route.view, params).then(function () {
19910
+ var promise = Promise.resolve();
19911
+ if (typeof exports.root().$.$onUpdating == 'function') {
19912
+ var result = exports.root().$.$onUpdating.call(exports.root());
19913
+ if (result instanceof Promise) {
19914
+ promise = promise.then(() => result);
19915
+ }
19916
+ }
19917
+ return promise;
19918
+ });
19919
+ }
19920
+
19921
+ exports.root().$.appContext.app.unmount();
19922
+ }
19923
+
19924
+ if (layout) {
19925
+ var layoutName = layout + (mobile ? '.m' : '');
19926
+ var _layoutHtml;
19927
+ var _layoutSkeletonFileHtml; // hoisted so LayoutNext closure can access it
19928
+ // Load layout .html, .js and optional .skeleton.html all in parallel
19929
+ return Promise.all([
19930
+ _httpGet(layoutName + '.html'),
19931
+ _httpGet(layout + '.js'),
19932
+ _httpGetSkeletonFile(layoutName + '.skeleton.html')
19933
+ ]).then(function (layoutResults) {
19934
+ _layoutHtml = layoutResults[0];
19935
+ var js = layoutResults[1];
19936
+ _layoutSkeletonFileHtml = layoutResults[2]; // null when absent
19937
+ return js;
19938
+ }).then(function (js) {
19939
+ var _opt = null;
19940
+ var Layout = function (options) {
19941
+ _opt = options;
19942
+ };
19943
+ var LayoutNext = function (options) {
19944
+ _hookSetup(options);
19945
+
19946
+ if (!_opt.template) {
19947
+ _opt.template = _sanitizeTemplate(_layoutHtml);
19948
+ }
19949
+ _patchComponent(layout, _opt);
19950
+ _layoutHtml = _opt.template;
19951
+ var htmlBeginTagIndex = _layoutHtml.indexOf('<html');
19952
+ var htmlBeginTagIndex2 = _layoutHtml.indexOf('>', htmlBeginTagIndex);
19953
+ _layoutHtml = _layoutHtml.substr(htmlBeginTagIndex2 + 1);
19954
+ var htmlEndTagIndex = _layoutHtml.lastIndexOf('</html>');
19955
+ _layoutHtml = _layoutHtml.substr(0, htmlEndTagIndex);
19956
+ document.querySelector('html').innerHTML = _layoutHtml;
19957
+ _hookData(options, params);
19958
+
19959
+ var ticks = new Date().getTime();
19960
+ var appId = 'pomelo-' + ticks;
19961
+ var containerId = 'container-' + ticks;
19962
+ var bodyHtml = document.querySelector('body').innerHTML;
19963
+ var renderBodyRegex = /<render-body\s*(?:\/\s*)?>(?:<\/render-body\s*>)?/i;
19964
+ var body;
19965
+ if (renderBodyRegex.test(bodyHtml)) {
19966
+ body = bodyHtml.replace(renderBodyRegex, '<div id="' + containerId + '"></div>');
19967
+ } else {
19968
+ console.error('[PomeUI] <render-body> tag not found in layout body innerHTML. The container element will not be created.');
19969
+ console.error('[PomeUI] Body innerHTML (first 500 chars):', bodyHtml.substring(0, 500));
19970
+ body = bodyHtml;
19971
+ }
19972
+ // Layout skeleton: defer generation to Root→_loadComponents so the
19973
+ // component skeleton registry is fully populated before we generate HTML.
19974
+ if (options.skeleton) {
19975
+ _ensureSkeletonStyle();
19976
+ var bodyEl = document.querySelector('body');
19977
+ var bodyClass = bodyEl.getAttribute('class') || '';
19978
+ var bodyInlineStyle = bodyEl.getAttribute('style') || '';
19979
+ var bodyComputed = window.getComputedStyle(bodyEl);
19980
+ var overlayStyle = bodyInlineStyle;
19981
+ if (bodyComputed.display && bodyComputed.display.indexOf('flex') >= 0) {
19982
+ if (overlayStyle) overlayStyle += ';';
19983
+ overlayStyle += 'display:' + bodyComputed.display
19984
+ + ';flex-direction:' + bodyComputed.flexDirection
19985
+ + ';align-items:' + bodyComputed.alignItems;
19986
+ } else {
19987
+ if (overlayStyle) overlayStyle += ';';
19988
+ overlayStyle += 'display:flex;flex-direction:row;align-items:stretch';
19989
+ }
19990
+ var skeletonBody = body.replace('<div id="' + containerId + '"></div>', '<div style="flex:1;min-width:0"></div>');
19991
+ // Store pending data; Root will inject the overlay div after
19992
+ // _loadComponents so registered component skeletons are available.
19993
+ options._pomeLayoutSkeleton = {
19994
+ appId: '#' + appId,
19995
+ bodyClass: bodyClass,
19996
+ overlayStyle: overlayStyle,
19997
+ skeletonBody: skeletonBody,
19998
+ // Priority: .skeleton.html file > inline string in JS
19999
+ skeletonOverride: _layoutSkeletonFileHtml
20000
+ || (typeof options.skeleton === 'string' ? options.skeleton : null)
20001
+ };
20002
+ }
20003
+ _ensureVueCloakStyle();
20004
+ document.querySelector('body').innerHTML = '<div id="' + appId + '" class="_pome-vue-cloak">' + body + '</div>';
20005
+ if (!document.getElementById(containerId)) {
20006
+ console.error('[PomeUI] Container element #' + containerId + ' not found in DOM immediately after setting body innerHTML. The <render-body> replacement likely failed.');
20007
+ }
20008
+ options.template = null;
20009
+ if (!options.mounted) {
20010
+ options.mounted = function () { };
20011
+ }
20012
+
20013
+ var _layoutContainerId = containerId;
20014
+ var _layoutRouteView = route.view;
20015
+ var _layoutParams = params;
20016
+
20017
+ return Root(options, '#' + appId, layout).then(function () {
20018
+ var root = exports.root();
20019
+ if (!root) return;
20020
+ var container = root.$container('#' + _layoutContainerId);
20021
+ return container.open(_layoutRouteView, _layoutParams);
20022
+ });
20023
+ };
20024
+
20025
+ var require = _createRequire(layout);
20026
+ eval(js + '\r\n//# sourceURL=' + layout + ".js");
20027
+ hookMountedAndUnmounted(_opt, layoutName);
20028
+ // Resolve template option for Layout (could be .html path or inline HTML)
20029
+ var layoutTemplatePromise = _opt.template
20030
+ ? _resolveTemplateOption(_opt.template)
20031
+ : Promise.resolve(null);
20032
+ return Promise.all([_resolveModules(_opt.modules, layout), layoutTemplatePromise]).then(function (layoutResolveResults) {
20033
+ var resolvedLayoutTemplate = layoutResolveResults[1];
20034
+ if (resolvedLayoutTemplate) {
20035
+ _opt.template = resolvedLayoutTemplate;
20036
+ }
20037
+ return LayoutNext(_opt);
20038
+ });
20039
+ });
20040
+ } else {
20041
+ var viewName = route.view + (_options.mobile() ? '.m' : '');
20042
+ return _applyLayoutHtml(route.view).then(function (appId) {
20043
+ var _opt = null;
20044
+ var components = null;
20045
+ var Page = function (options) {
20046
+ _opt = options;
20047
+ };
20048
+ var PageNext = function (options) {
20049
+ modules = options.modules;
20050
+ components = options.components || [];
20051
+ Root(options, '#' + appId, route.view);
20052
+ };
20053
+
20054
+ var require = _createRequire(route.view);
20055
+ eval(_def + '\r\n//# sourceURL=' + route.view + '.js');
20056
+
20057
+ if (!_opt) {
20058
+ _opt = {};
20059
+ }
20060
+
20061
+ _hookData(_opt, params);
20062
+ hookMountedAndUnmounted(_opt, viewName);
20063
+ _patchComponent(viewName, _opt);
20064
+ return _resolveModules(_opt.modules, viewName).then(function () {
20065
+ PageNext(_opt);
20066
+ return Promise.resolve();
20067
+ });
20068
+ });
20069
+ }
20070
+ }).then(function () {
20071
+ ForceUpdate();
20072
+ }).catch(function (err) {
20073
+ console.error(err);
20074
+ })
20075
+ };
20076
+
20077
+ function Redirect(url) {
20078
+ var title = null;
20079
+ var titleTag = document.querySelector('title');
20080
+ if (titleTag) {
20081
+ title = titleTag.innerText;
20082
+ }
20083
+ window.history.pushState(null, title, url);
20084
+ UpdateLayout();
20085
+ }
20086
+
20087
+ function Replace(url) {
20088
+ var title = null;
20089
+ var titleTag = document.querySelector('title');
20090
+ if (titleTag) {
20091
+ title = titleTag.innerText;
20092
+ }
20093
+ window.history.replaceState(null, title, url);
20094
+ UpdateLayout();
20095
+ }
20096
+
20097
+
20098
+ function LoadScript(url) {
20099
+ if (_httpCached(url)) {
20100
+ with (window) {
20101
+ if (PomeloModule) {
20102
+ var require = function (script, workingDirectory, mode) {
20103
+ workingDirectory = workingDirectory || PomeloModule.getContainingFolder(url);
20104
+ return PomeloModule.require(script, workingDirectory, mode);
20105
+ };
20106
+ }
20107
+
20108
+ eval(_cache[url] + '\r\n//# sourceURL=' + url);
20109
+ }
20110
+ return Promise.resolve();
20111
+ }
20112
+
20113
+ return _httpGet(url).then(function (js) {
20114
+ with (window) {
20115
+
20116
+ if (PomeloModule) {
20117
+ var require = function (script, workingDirectory, mode) {
20118
+ workingDirectory = workingDirectory || PomeloModule.getContainingFolder(url);
20119
+ return PomeloModule.require(script, workingDirectory, mode);
20120
+ };
20121
+ }
20122
+
20123
+ eval(js + '\r\n//# sourceURL=' + url);
20124
+ }
20125
+ _cache[url] = js;
20126
+ return Promise.resolve();
20127
+ }).catch(err => {
20128
+ console.error('Load module ' + url + ' failed.');
20129
+ console.error(err);
20130
+ });
20131
+ }
20132
+
20133
+ function resolveRelativePathPlain(url) {
20134
+ if (url.indexOf('./') == -1 && url.indexOf('../') == -1) {
20135
+ return url;
20136
+ }
20137
+
20138
+ var index = url.lastIndexOf('../');
20139
+ if (index == 0) {
20140
+ return url;
20141
+ }
20142
+
20143
+ url = url.replaceAll('/./', '/');
20144
+ if (url.indexOf('./') == 0) {
20145
+ url = url.substr(2);
20146
+ }
20147
+
20148
+ if (index) {
20149
+ var w = url.substr(0, index);
20150
+ var f = url.substr(index);
20151
+ return resolveRelativePath(f, w);
20152
+ }
20153
+ }
20154
+
20155
+ function resolveRelativePath(file, workingDirectory) {
20156
+ if (file.length && (file[0] == '/') || file.indexOf('http') == 0) {
20157
+ return resolveRelativePathPlain(file);
20158
+ }
20159
+
20160
+ if (file.length && file[0] != '.') {
20161
+ return resolveRelativePathPlain(workingDirectory + file);
20162
+ }
20163
+
20164
+ if (file.indexOf('./') == 0) {
20165
+ return resolveRelativePath(file.substr(2), workingDirectory);
20166
+ }
20167
+
20168
+ if (file.indexOf('../') == 0) {
20169
+ file = file.substr(3);
20170
+ workingDirectory = getContainingFolder(workingDirectory.substr(0, workingDirectory.length - 1));
20171
+ return resolveRelativePath(file, workingDirectory);
20172
+ }
20173
+ }
20174
+
20175
+ function _loadComponents(components, viewName) {
20176
+ var ret = [];
20177
+ if (!components.length) {
20178
+ return Promise.resolve(ret);
20179
+ }
20180
+ var workingDirectory = getContainingFolder(viewName || '/');
20181
+ return Promise.all(components.map(function (c) {
20182
+ c = resolveRelativePath(parseMacroPath(viewName, c), workingDirectory);
20183
+ var componentPath = c;
20184
+ var _html;
20185
+ var _name;
20186
+ var _opt;
20187
+ // Load .html, .js and optional .skeleton.html in parallel
20188
+ return Promise.all([
20189
+ _httpGet(c + '.html'),
20190
+ _httpGet(c + '.js'),
20191
+ _httpGetSkeletonFile(c + '.skeleton.html')
20192
+ ]).then(function (results) {
20193
+ _html = results[0];
20194
+ var comJs = results[1];
20195
+ var skeletonFileHtml = results[2]; // null when file does not exist
20196
+ var Component = function (name, options) {
20197
+ _opt = options;
20198
+ _name = name;
20199
+ };
20200
+
20201
+ var require = _createRequire(c);
20202
+ eval(comJs + '\r\n//# sourceURL=' + c + ".js");
20203
+ hookMountedAndUnmounted(_opt, c);
20204
+ // Resolve template option for Component (could be .html path or inline HTML)
20205
+ var compTemplatePromise = _opt.template
20206
+ ? _resolveTemplateOption(_opt.template)
20207
+ : Promise.resolve(null);
20208
+ return compTemplatePromise.then(function (resolvedCompTemplate) {
20209
+ if (resolvedCompTemplate) {
20210
+ _opt.template = resolvedCompTemplate;
20211
+ } else if (!_opt.template) {
20212
+ _opt.template = _sanitizeTemplate(_html);
20213
+ }
20214
+ _hookSetup(_opt);
20215
+ _patchComponent(c, _opt, true);
20216
+ // Register the component's skeleton BEFORE wrapping the template,
20217
+ // so _generateSkeletonHtml still sees the clean original template.
20218
+ _registerComponentSkeleton(_name, _opt, _opt.template, skeletonFileHtml);
20219
+ _wrapTemplateWithSkeleton(_opt);
20220
+ _hookData(_opt);
20221
+ var cssPreloadPromise = Promise.resolve();
20222
+ if (_options.preloadCss && _opt.style) {
20223
+ cssPreloadPromise = appendCssReferenceAsync(c, _opt.style);
20224
+ }
20225
+ return Promise.all([cssPreloadPromise, _resolveModules(_opt.modules, c)]);
20226
+ }); // end of compTemplatePromise.then
20227
+ }).then(function () {
20228
+ // Recursively load sub-components for this component
20229
+ var subComponentRefs = _opt.components || [];
20230
+ return _loadComponents(subComponentRefs, componentPath);
20231
+ }).then(function (subComponents) {
20232
+ ret.push({ name: _name, options: _opt });
20233
+ for (var i = 0; i < subComponents.length; ++i) {
20234
+ if (!ret.some(function (x) { return x.name == subComponents[i].name; })) {
20235
+ ret.push(subComponents[i]);
20236
+ }
20237
+ }
20238
+ return Promise.resolve();
20239
+ });
20240
+ })).then(function () {
20241
+ return Promise.resolve(ret);
20242
+ });
20243
+ }
20244
+
20245
+ function _loadDirectives(directives, viewName) {
20246
+ var ret = [];
20247
+ if (!directives.length) {
20248
+ return Promise.resolve(ret);
20249
+ }
20250
+ var workingDirectory = getContainingFolder(viewName || '/');
20251
+ var viewName;
20252
+ var subComponentRefs = [];
20253
+ return Promise.all(directives.map(function (c) {
20254
+ c = resolveRelativePath(parseMacroPath(viewName, c), workingDirectory);
20255
+ viewName = c;
20256
+ var _name;
20257
+ var _opt;
20258
+ return _httpGet(c + ".js").then(function (comJs) {
20259
+ var Directive = function (name, options) {
20260
+ _opt = options;
20261
+ _name = name;
20262
+ };
20263
+
20264
+ var require = _createRequire(c);
20265
+ eval(comJs + '\r\n//# sourceURL=' + c + ".js");
20266
+ ret.push({ name: _name, options: _opt });
20267
+ return Promise.resolve();
20268
+ })
20269
+ })).then(function () {
20270
+ return Promise.resolve(ret);
20271
+ });
20272
+ }
20273
+
20274
+ exports._addins = [];
20275
+
20276
+ function _patchComponent(view, opt, isComponent) {
20277
+ prepared = true;
20278
+ if (!opt.data) {
20279
+ opt.data = function () {
20280
+ return {};
20281
+ };
20282
+ }
20283
+
20284
+ if (!opt.style) {
20285
+ opt.style = [];
20286
+ }
20287
+
20288
+ if (!opt.style instanceof Array) {
20289
+ if (opt.style instanceof String) {
20290
+ opt.style = [opt.style];
20291
+ } else {
20292
+ opt.style = ['@(css)'];
20293
+ }
20294
+ }
20295
+
20296
+ if (!opt.components) {
20297
+ opt.components = [];
20298
+ }
20299
+
20300
+ if (!opt.created) {
20301
+ opt.created = function () { };
20302
+ }
20303
+
20304
+ if (!opt.mounted) {
20305
+ opt.mounted = function () { };
20306
+ }
20307
+
20308
+ if (!opt.unmounted) {
20309
+ opt.unmounted = function () { };
20310
+ }
20311
+
20312
+ if (!opt.destroyed) {
20313
+ opt.destroyed = function () { };
20314
+ }
20315
+
20316
+ if (!opt.watch) {
20317
+ opt.watch = {};
20318
+ }
20319
+
20320
+ if (!opt.computed) {
20321
+ opt.computed = {};
20322
+ }
20323
+
20324
+ let func1 = opt.data;
20325
+ opt.data = function (app) {
20326
+ var data = func1.call(this, app);
20327
+ var data2 = {};
20328
+ if (!isComponent) {
20329
+ data2.pomeUiSubTitles = [];
20330
+ }
20331
+ if (opt.skeleton) {
20332
+ // Start hidden; skeleton is only shown after skeletonDelay ms
20333
+ // to avoid a flash when loading completes quickly.
20334
+ data2.pomeSkeletonLoading = false;
20335
+ // Cloak: hide real content until skeleton appears or data loads,
20336
+ // preventing a flash of uninitialized content during the delay.
20337
+ data2.pomeSkeletonCloaked = true;
20338
+ }
20339
+ if (opt.skeleton && opt.delayOpen) {
20340
+ data2.pomeDelayOpened = true;
20341
+ data2.pomeDelayOpening = true;
20342
+ }
20343
+ _combineObject(data2, data);
20344
+ return data;
20345
+ }
20346
+
20347
+ if (!opt.methods) {
20348
+ opt.methods = {};
20349
+ }
20350
+
20351
+ if (!isComponent) {
20352
+ opt.methods.pomeUiPassTitle = pomeUiPassTitle;
20353
+
20354
+ if (!opt.watch) {
20355
+ opt.watch = {};
20356
+ }
20357
+
20358
+ if (!opt.watch.title) {
20359
+ opt.watch.title = function () { };
20360
+ }
20361
+
20362
+
20363
+ _chainHook(opt.watch, 'title', function () {
20364
+ this.pomeUiPassTitle();
20365
+ });
20366
+ }
20367
+
20368
+ for (let i = 0; i < exports._addins.length; ++i) {
20369
+ let v = exports._addins[i].view;
20370
+ let addin = exports._addins[i].opt;
20371
+ if (v != '*' && view != v) {
20372
+ continue;
20373
+ }
20374
+
20375
+ if (addin.data) {
20376
+ let func2 = opt.data;
20377
+ opt.data = function (app) {
20378
+ var data = func2.call(this, app);
20379
+ var data2 = {};
20380
+ try {
20381
+ data2 = addin.data.call(this, app);
20382
+ } catch (ex) {
20383
+ console.error(ex);
20384
+ }
20385
+ _combineObject(data2, data);
20386
+ return data;
20387
+ }
20388
+ }
20389
+
20390
+ if (addin.style) {
20391
+ if (addin.style instanceof Boolean) {
20392
+ addin.style = ['@(css)'];
20393
+ }
20394
+
20395
+ if (addin.style instanceof String) {
20396
+ addin.style = [addin.style];
20397
+ }
20398
+
20399
+ addin.style.forEach(function (s) {
20400
+ if (!opt.style) {
20401
+ opt.style = [];
20402
+ }
20403
+ if (typeof opt.style == 'boolean') {
20404
+ opt.style = ['@(css)'];
20405
+ }
20406
+ if (!opt.style.some(x => x == s)) {
20407
+ opt.style.push(s);
20408
+ }
20409
+ });
20410
+ }
20411
+
20412
+ if (addin.components) {
20413
+ addin.components.forEach(function (c) {
20414
+ if (!opt.components.some(x => x == c)) {
20415
+ opt.components.push(c);
20416
+ }
20417
+ });
20418
+ }
20419
+
20420
+ if (addin.layout) {
20421
+ opt.layout = addin.layout;
20422
+ }
20423
+
20424
+ if (addin.props) {
20425
+ if (!opt.props) {
20426
+ opt.props = [];
20427
+ }
20428
+
20429
+ addin.props.forEach(function (p) {
20430
+ if (!opt.props.some(x => x == p)) {
20431
+ opt.props.push(p);
20432
+ }
20433
+ });
20434
+ }
20435
+
20436
+ if (addin.watch) {
20437
+ var properties = Object.getOwnPropertyNames(addin.watch);
20438
+ properties.forEach(function (key) {
20439
+ var _originalWatch = opt.watch[key];
20440
+ opt.watch[key] = function (a, b) {
20441
+ _originalWatch.invoke(this, a, b);
20442
+ try {
20443
+ addin.watch[key].invoke(this, a, b);
20444
+ } catch (ex) {
20445
+ console.error(ex);
20446
+ }
20447
+ }
20448
+ });
20449
+ }
20450
+
20451
+ if (addin.computed) {
20452
+ var properties = Object.getOwnPropertyNames(addin.computed);
20453
+ properties.forEach(function (key) {
20454
+ opt.computed[key] = addin.computed[key];
20455
+ });
20456
+ }
20457
+
20458
+ if (addin.methods) {
20459
+ var setup = opt.setup || function (props, context) {
20460
+ };
20461
+
20462
+ opt.setup = function (props, context) {
20463
+ setup(props, context);
20464
+ var methods = {};
20465
+ var originMethods = Object.getOwnPropertyNames(opt.methods);
20466
+ originMethods.forEach(function (m) {
20467
+ methods[m] = opt.methods[m];
20468
+ });
20469
+ var instance = Vue.getCurrentInstance();
20470
+ instance.$baseMethods = methods;
20471
+ };
20472
+
20473
+ var addinMethods = Object.getOwnPropertyNames(addin.methods);
20474
+ addinMethods.forEach(function (m) {
20475
+ opt.methods[m] = addin.methods[m];
20476
+ });
20477
+ }
20478
+
20479
+ if (addin.created) {
20480
+ _chainHook(opt, 'created', addin.created);
20481
+ }
20482
+
20483
+ if (addin.mounted) {
20484
+ _chainHook(opt, 'mounted', addin.mounted);
20485
+ }
20486
+
20487
+ if (addin.unmounted) {
20488
+ _chainHook(opt, 'unmounted', addin.unmounted);
20489
+ }
20490
+
20491
+ if (addin.destroyed) {
20492
+ _chainHook(opt, 'destroyed', addin.destroyed);
20493
+ }
20494
+
20495
+ if (addin.template) {
20496
+ if (addin.template instanceof Function) {
20497
+ if (opt.template) {
20498
+ if (opt.template.indexOf('<html') >= 0) {
20499
+ var template = new DOMParser().parseFromString(_sanitizeTemplate(opt.template), 'text/html');
20500
+ addin.template(template);
20501
+ opt.template = new XMLSerializer().serializeToString(template);
20502
+ } else {
20503
+ opt.template = `<pome-ui-template>${opt.template}</pome-ui-template>`
20504
+ var template = new DOMParser().parseFromString(_sanitizeTemplate(opt.template), 'text/html');
20505
+ addin.template(template);
20506
+ opt.template = new XMLSerializer().serializeToString(template);
20507
+ opt.template = opt.template.substr(opt.template.indexOf('<pome-ui-template>') + '<pome-ui-template>'.length);
20508
+ opt.template = opt.template.substr(0, opt.template.indexOf('</pome-ui-template>'));
20509
+ }
20510
+ }
20511
+ } else {
20512
+ opt.template = addin.template;
20513
+ }
20514
+ }
20515
+ }
20516
+
20517
+ if (!isComponent) {
20518
+ _chainHook(opt, 'created', function () {
20519
+ this.pomeUiPassTitle();
20520
+ });
20521
+
20522
+ _chainHook(opt, 'unmounted', function () {
20523
+ this.pomeUiPassTitle([]);
20524
+ });
20525
+ }
20526
+ }
20527
+
20528
+ function _patchTemplate(view, html) {
20529
+ for (let i = 0; i < exports._addins.length; ++i) {
20530
+ let v = exports._addins[i].view;
20531
+ let addin = exports._addins[i].opt;
20532
+ if (v != '*' && view != v) {
20533
+ continue;
20534
+ }
20535
+
20536
+ if (addin.template) {
20537
+ if (addin.template instanceof Function) {
20538
+ if (html.indexOf('<html') >= 0) {
20539
+ var template = new DOMParser().parseFromString(_sanitizeTemplate(html), 'text/html');
20540
+ addin.template(template);
20541
+ html = new XMLSerializer().serializeToString(template);
20542
+ } else {
20543
+ html = `<pome-ui-template>${html}</pome-ui-template>`
20544
+ var template = new DOMParser().parseFromString(_sanitizeTemplate(html), 'text/html');
20545
+ addin.template(template);
20546
+ html = new XMLSerializer().serializeToString(template);
20547
+ html = html.substr(html.indexOf('<pome-ui-template>') + '<pome-ui-template>'.length);
20548
+ html = html.substr(0, html.indexOf('</pome-ui-template>'));
20549
+ }
20550
+ } else {
20551
+ html = addin.template;
20552
+ }
20553
+ }
20554
+ }
20555
+ return html;
20556
+ }
20557
+
20558
+ function UseAddin(addinUrl) {
20559
+ var Addin = function (view, opt) {
20560
+ exports._addins.push({view, opt});
20561
+ };
20562
+
20563
+ var js = _options.httpGetSync(addinUrl);
20564
+ eval(js);
20565
+ }
20566
+
20567
+
20568
+ function UseInlineAddin(script) {
20569
+ var Addin = function (view, opt) {
20570
+ exports._addins.push({ view, opt });
20571
+ };
20572
+
20573
+ eval(script);
20574
+ }
20575
+
20576
+ function Backward() {
20577
+ window.history.back();
20578
+ }
20579
+
20580
+ exports.root = root;
20581
+ exports.useConfig = UseConfig;
20582
+ exports.mapRoute = MapRoute;
20583
+ exports.matchRoute = MatchRoute;
20584
+ exports.updateLayout = UpdateLayout;
20585
+ exports.redirect = Redirect;
20586
+ exports.replace = Replace;
20587
+ exports.backward = Backward;
20588
+ exports.loadScript = LoadScript;
20589
+ exports.forceUpdate = ForceUpdate;
20590
+ exports.mount = mount;
20591
+ exports.useRoutes = useRoutes;
20592
+ exports.useAddin = UseAddin;
20593
+ exports.useInlineAddin = UseInlineAddin;
20594
+
20595
+ return exports;
20596
+ };
20597
+
20591
20598
  exports.build = build;