pug-site-core 2.0.20 → 3.0.0

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/lib/utils.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import fse from "fs-extra";
2
2
  import path from "path";
3
- import tcpPortUsed from "tcp-port-used";
4
3
  import JavaScriptObfuscator from "javascript-obfuscator";
5
4
  import { paths } from "./paths.js";
5
+ import detectPort from "detect-port";
6
+
6
7
 
7
8
  const { config } = await import(paths.config);
8
9
 
@@ -82,17 +83,21 @@ export async function sleep(ms) {
82
83
  /**
83
84
  * 获取可用的端口号
84
85
  * @param {number} port - 起始端口号
85
- * @param {string} Ip - IP地址
86
86
  * @returns {Promise<number>} 返回可用的端口号
87
87
  */
88
- export async function getIdleProt(port, Ip) {
89
- while (1) {
90
- if (!(await tcpPortUsed.check(port, Ip))) {
91
- break;
88
+ export async function getIdleProt(port) {
89
+ while (true) {
90
+ try {
91
+ // 使用detect-port检查端口是否可用
92
+ const availablePort = await detectPort(port);
93
+ if (Number(availablePort) === Number(port)) {
94
+ return port;
95
+ }
96
+ } catch (error) {
97
+ console.error(`端口检查出错: ${error.message}`);
92
98
  }
93
99
  port++;
94
100
  }
95
- return port;
96
101
  }
97
102
 
98
103
  /**
@@ -383,3 +388,264 @@ export async function getJsonData(jsonDataPath) {
383
388
  let jsonData = await fse.readJSON(filePath);
384
389
  return jsonData;
385
390
  }
391
+
392
+
393
+ /**
394
+ * 为HTML字符串中的template标签添加作用域隔离(优化版本)
395
+ * @param {string} htmlString - HTML字符串
396
+ * @param {string} scopePrefix - 作用域前缀,默认为"xy"
397
+ * @param {Object} options - 配置选项
398
+ * @param {number} options.maxDepth - 最大递归深度,默认为10
399
+ * @param {boolean} options.preserveComments - 是否保留注释,默认为true
400
+ * @returns {string} 处理后的HTML字符串
401
+ */
402
+ export function addTemplateScopeIsolation(htmlString, scopePrefix = "xy", options = {}) {
403
+ // 参数验证
404
+ if (!htmlString || typeof htmlString !== "string") {
405
+ return htmlString;
406
+ }
407
+
408
+ // 快速检查,避免不必要的处理
409
+ if (!htmlString.includes("<template>") || !htmlString.includes("</template>")) {
410
+ return htmlString;
411
+ }
412
+
413
+ // 配置选项
414
+ const config = {
415
+ maxDepth: options.maxDepth || 10,
416
+ preserveComments: options.preserveComments !== false,
417
+ _currentDepth: 0
418
+ };
419
+
420
+ // 生成唯一的作用域ID(使用更稳定的方法)
421
+ function generateScopeId(prefix) {
422
+ const timestamp = Date.now().toString(36);
423
+ const random = Math.random().toString(36).substring(2, 8);
424
+ return `${prefix}-${timestamp}-${random}`;
425
+ }
426
+
427
+ // 为简单选择器添加作用域(移到外部作用域)
428
+ function addScopeToSimpleSelector(selector, scopeId) {
429
+ // 处理空选择器
430
+ if (!selector || !selector.trim()) {
431
+ return selector;
432
+ }
433
+
434
+ selector = selector.trim();
435
+
436
+ // 处理伪类和伪元素(更完善的正则)
437
+ const pseudoMatch = selector.match(/^([^:]+?)(::?[^[]+)?$/);
438
+ if (pseudoMatch) {
439
+ const [, base, pseudo = ''] = pseudoMatch;
440
+ // 处理属性选择器
441
+ if (base.includes('[')) {
442
+ const attrMatch = base.match(/^([^[]+)(\[.+\])$/);
443
+ if (attrMatch) {
444
+ return `${attrMatch[1]}[data-${scopeId}]${attrMatch[2]}${pseudo}`;
445
+ }
446
+ }
447
+ return `${base}[data-${scopeId}]${pseudo}`;
448
+ }
449
+
450
+ return `${selector}[data-${scopeId}]`;
451
+ }
452
+
453
+ // 处理template标签
454
+ function parseHTML(html, depth = 0) {
455
+ // 检查递归深度
456
+ if (depth >= config.maxDepth) {
457
+ console.warn(`Maximum recursion depth (${config.maxDepth}) reached in template processing`);
458
+ return html;
459
+ }
460
+
461
+ // 使用更精确的模板匹配(避免贪婪匹配问题)
462
+ const templates = [];
463
+ let tempHtml = html;
464
+ let placeholder = 0;
465
+
466
+ // 先收集所有template标签的位置和内容
467
+ const templateRegex = /<template([^>]*)>([\s\S]*?)<\/template>/gi;
468
+ let match;
469
+
470
+ while ((match = templateRegex.exec(html)) !== null) {
471
+ templates.push({
472
+ full: match[0],
473
+ attributes: match[1] || '',
474
+ content: match[2] || '',
475
+ start: match.index,
476
+ placeholder: `__TEMPLATE_PLACEHOLDER_${placeholder++}__`
477
+ });
478
+ }
479
+
480
+ // 从后往前替换,避免索引偏移问题
481
+ for (let i = templates.length - 1; i >= 0; i--) {
482
+ const template = templates[i];
483
+ const scopeId = generateScopeId(scopePrefix);
484
+
485
+ // 处理内容
486
+ const processedContent = addScopeToHTML(template.content, scopeId);
487
+
488
+ // 创建新的div标签,保留原有属性
489
+ const attributesStr = template.attributes ? ` ${template.attributes.trim()}` : '';
490
+ const newDiv = `<div data-${scopeId}=""${attributesStr}>${processedContent}</div>`;
491
+
492
+ // 替换原始template
493
+ tempHtml = tempHtml.substring(0, template.start) +
494
+ newDiv +
495
+ tempHtml.substring(template.start + template.full.length);
496
+ }
497
+
498
+ // 检查是否还有嵌套的template需要处理
499
+ if (tempHtml.includes('<template>') && depth < config.maxDepth - 1) {
500
+ return parseHTML(tempHtml, depth + 1);
501
+ }
502
+
503
+ return tempHtml;
504
+ }
505
+
506
+ // 为HTML内容添加作用域属性
507
+ function addScopeToHTML(html, scopeId) {
508
+ // 处理HTML标签(改进的正则,支持自闭合标签)
509
+ let processedHtml = html.replace(
510
+ /<(\w+)([^>]*?)(\/?)>/g,
511
+ (match, tagName, attributes, selfClosing) => {
512
+ // 跳过已经有作用域属性的标签
513
+ if (attributes.includes('data-v-') ||
514
+ attributes.includes(`data-${scopeId}`) ||
515
+ attributes.includes(`data-${scopePrefix}-`)) {
516
+ return match;
517
+ }
518
+
519
+ // 处理特殊标签(不需要作用域的)
520
+ const skipTags = ['script', 'style', 'template'];
521
+ if (skipTags.includes(tagName.toLowerCase())) {
522
+ return match;
523
+ }
524
+
525
+ // 为标签添加作用域属性
526
+ return `<${tagName} data-${scopeId}=""${attributes}${selfClosing}>`;
527
+ }
528
+ );
529
+
530
+ // 处理style标签中的CSS
531
+ processedHtml = processedHtml.replace(
532
+ /<style([^>]*?)>([\s\S]*?)<\/style>/gi,
533
+ (match, styleAttrs, cssContent) => {
534
+ // 跳过已处理的CSS
535
+ if (cssContent.includes(`[data-${scopeId}]`) ||
536
+ cssContent.includes(`[data-${scopePrefix}-`)) {
537
+ return match;
538
+ }
539
+
540
+ const scopedCSS = addScopeToCSS(cssContent, scopeId);
541
+ return `<style${styleAttrs}>${scopedCSS}</style>`;
542
+ }
543
+ );
544
+
545
+ return processedHtml;
546
+ }
547
+
548
+ // 为CSS添加作用域(改进版本)
549
+ function addScopeToCSS(cssContent, scopeId) {
550
+ // 保存注释
551
+ const comments = [];
552
+ let commentIndex = 0;
553
+
554
+ if (config.preserveComments) {
555
+ cssContent = cssContent.replace(/\/\*[\s\S]*?\*\//g, (match) => {
556
+ const placeholder = `__CSS_COMMENT_${commentIndex++}__`;
557
+ comments.push({ placeholder, content: match });
558
+ return placeholder;
559
+ });
560
+ }
561
+
562
+ // 改进的CSS规则处理
563
+ function processCSS(css, level = 0) {
564
+ if (level > 5) return css; // 防止过深的嵌套
565
+
566
+ // 匹配CSS规则块
567
+ const ruleRegex = /([^{}]+)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
568
+
569
+ return css.replace(ruleRegex, (match, selectors, content) => {
570
+ const trimmedSelectors = selectors.trim();
571
+
572
+ // 处理@规则
573
+ if (trimmedSelectors.startsWith('@')) {
574
+ // @keyframes不需要作用域
575
+ if (trimmedSelectors.startsWith('@keyframes')) {
576
+ return match;
577
+ }
578
+
579
+ // @media, @supports等需要递归处理内部规则
580
+ if (content.includes('{')) {
581
+ const processedContent = processCSS(content, level + 1);
582
+ return `${selectors} {${processedContent}}`;
583
+ }
584
+
585
+ return match;
586
+ }
587
+
588
+ // 处理普通选择器
589
+ const processedSelectors = trimmedSelectors
590
+ .split(',')
591
+ .map(selector => {
592
+ selector = selector.trim();
593
+
594
+ // 跳过特殊情况
595
+ if (!selector ||
596
+ selector.startsWith('@') ||
597
+ /^(from|to|\d+%)$/.test(selector) ||
598
+ selector.includes(`[data-${scopeId}]`)) {
599
+ return selector;
600
+ }
601
+
602
+ // 清理现有的作用域属性
603
+ selector = selector.replace(/\[data-[a-z0-9-]+\]/gi, '').trim();
604
+
605
+ // 处理复杂选择器
606
+ const selectorParts = selector.split(/\s+/);
607
+
608
+ // 处理第一个选择器部分
609
+ if (selectorParts.length > 0) {
610
+ // 处理组合选择器(如 .class1.class2)
611
+ const firstPart = selectorParts[0];
612
+ const combinedSelectors = firstPart.split(/(?=[.#[])/);
613
+
614
+ if (combinedSelectors.length > 1) {
615
+ // 在第一个实际选择器后添加作用域
616
+ combinedSelectors[0] = addScopeToSimpleSelector(combinedSelectors[0], scopeId);
617
+ selectorParts[0] = combinedSelectors.join('');
618
+ } else {
619
+ selectorParts[0] = addScopeToSimpleSelector(firstPart, scopeId);
620
+ }
621
+ }
622
+
623
+ return selectorParts.join(' ');
624
+ })
625
+ .join(', ');
626
+
627
+ return `${processedSelectors} {${content}}`;
628
+ });
629
+ }
630
+
631
+ // 处理CSS
632
+ let processedCSS = processCSS(cssContent);
633
+
634
+ // 恢复注释
635
+ if (config.preserveComments) {
636
+ comments.forEach(({ placeholder, content }) => {
637
+ processedCSS = processedCSS.replace(placeholder, content);
638
+ });
639
+ }
640
+
641
+ return processedCSS;
642
+ }
643
+
644
+ // 开始处理
645
+ try {
646
+ return parseHTML(htmlString);
647
+ } catch (error) {
648
+ console.error('Error in addTemplateScopeIsolation:', error);
649
+ return htmlString; // 出错时返回原始内容
650
+ }
651
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pug-site-core",
3
- "version": "2.0.20",
3
+ "version": "3.0.0",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -13,7 +13,8 @@
13
13
  "lang": "node index.js",
14
14
  "imagemin": "node index.js",
15
15
  "build": "npm run getData && npm run buildFn",
16
- "update": "npm install pug-site-core@latest"
16
+ "update": "npm install pug-site-core@latest",
17
+ "debug": "node index.js"
17
18
  },
18
19
  "keywords": [],
19
20
  "author": "xy",
@@ -21,7 +22,10 @@
21
22
  "@google-cloud/translate": "^8.5.0",
22
23
  "async": "^3.2.6",
23
24
  "axios": "^1.7.7",
25
+ "cheerio": "^1.0.0",
24
26
  "chokidar": "^3.6.0",
27
+ "css": "^3.0.0",
28
+ "detect-port": "^2.1.0",
25
29
  "express": "^4.19.2",
26
30
  "express-useragent": "^1.0.15",
27
31
  "fs-extra": "^11.2.0",
@@ -37,16 +41,17 @@
37
41
  "jstransformer-autoprefixer": "^2.0.0",
38
42
  "jstransformer-less": "^2.3.0",
39
43
  "jstransformer-scss": "^2.0.0",
40
- "less": "^4.2.0",
41
44
  "lodash": "^4.17.21",
42
45
  "nodemon": "^3.1.4",
43
46
  "pug": "^3.0.3",
44
- "tcp-port-used": "^1.0.2",
47
+ "pug-lexer": "^5.0.1",
48
+ "pug-parser": "^6.0.0",
49
+ "pug-walk": "^2.0.0",
45
50
  "uglify-js": "^3.19.3",
46
51
  "ws": "^8.18.0"
47
52
  },
48
53
  "license": "ISC",
49
- "description": "再次修复错误的删除文件问题",
54
+ "description": "增加debug模板、添加abtest功能",
50
55
  "files": [
51
56
  "lib/",
52
57
  "index.js"
@@ -54,4 +59,4 @@
54
59
  "exports": {
55
60
  ".": "./index.js"
56
61
  }
57
- }
62
+ }