@lyhue1991/wxgzh 0.1.2 → 0.1.3

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/README.md CHANGED
@@ -1,6 +1,15 @@
1
1
  # wxgzh
2
2
 
3
- 一个面向微信公众号的 Node.js CLI 工具:把 Markdown 文章处理成适合公众号发布的 HTML,修复图片,并提交到公众号草稿箱。
3
+ 一个面向微信公众号的 SKILL,基于 NodeJS CLI.
4
+
5
+ 把 Markdown 文章处理成适合公众号发布的 HTML,上传图片,生成封面,并提交到公众号草稿箱。
6
+
7
+ <mark>安装此SKILL</mark>
8
+
9
+ ```
10
+ npx skills add lyhue1991/wxgzh
11
+ ```
12
+
4
13
 
5
14
  ## 一、功能概述
6
15
 
@@ -12,7 +21,7 @@
12
21
  - 支持主题样式、自定义 CSS、自动摘要、封面图生成。
13
22
  - 也支持分步执行,便于你单独检查 HTML、封面或发布结果。
14
23
 
15
- **操作方法**
24
+ **手动操作方法**
16
25
 
17
26
  * step1: 一键安装(要求:Node.js >= 18)
18
27
 
@@ -371,6 +371,9 @@ function escapeHtmlAttribute(value) {
371
371
  function isTextNodeEmpty(node) {
372
372
  return node.type === 'text' && !node.data.trim();
373
373
  }
374
+ function isTagNode(node, tagName) {
375
+ return node.type === 'tag' && node.tagName.toLowerCase() === tagName;
376
+ }
374
377
  function isStandaloneImageParagraph($paragraph) {
375
378
  const nodes = $paragraph.contents().toArray().filter((node) => !isTextNodeEmpty(node));
376
379
  return nodes.every((node) => node.type === 'tag' && ['img', 'br'].includes(node.tagName.toLowerCase()));
@@ -410,10 +413,33 @@ async function loadCustomCss() {
410
413
  function normalizeListItems($) {
411
414
  $('li').each((_, element) => {
412
415
  const $item = $(element);
413
- const childElements = $item
414
- .contents()
415
- .toArray()
416
- .filter((node) => !isTextNodeEmpty(node));
416
+ const initialChildren = $item.contents().toArray();
417
+ const hasParagraphChild = initialChildren.some((node) => isTagNode(node, 'p'));
418
+ if (hasParagraphChild) {
419
+ const fragments = [];
420
+ let previousWasParagraph = false;
421
+ for (const node of initialChildren) {
422
+ if (isTextNodeEmpty(node)) {
423
+ continue;
424
+ }
425
+ if (isTagNode(node, 'p')) {
426
+ const paragraphHtml = renderSoftBreakFriendlyHtml(node.children ?? []);
427
+ if (!paragraphHtml.trim()) {
428
+ continue;
429
+ }
430
+ if (previousWasParagraph) {
431
+ fragments.push('<br>');
432
+ }
433
+ fragments.push(paragraphHtml);
434
+ previousWasParagraph = true;
435
+ continue;
436
+ }
437
+ fragments.push(renderSoftBreakFriendlyNode(node, true));
438
+ previousWasParagraph = false;
439
+ }
440
+ $item.html(fragments.join(''));
441
+ }
442
+ const childElements = $item.contents().toArray().filter((node) => !isTextNodeEmpty(node));
417
443
  if (childElements.length === 0) {
418
444
  return;
419
445
  }
@@ -425,7 +451,7 @@ function normalizeListItems($) {
425
451
  return ['p', 'ul', 'ol', 'section', 'blockquote', 'pre', 'table'].includes(tagName);
426
452
  });
427
453
  const firstChild = childElements[0];
428
- if (!hasBlockChild && firstChild?.type === 'tag' && firstChild.tagName.toLowerCase() === 'span' && childElements.length === 1) {
454
+ if (!hasBlockChild && isTagNode(firstChild, 'span') && childElements.length === 1) {
429
455
  return;
430
456
  }
431
457
  if (hasBlockChild) {
@@ -585,12 +611,80 @@ function setInlineStyleProperty(existingStyle, property, value) {
585
611
  .map(([name, declarationValue]) => `${name}: ${declarationValue}`)
586
612
  .join('; ');
587
613
  }
614
+ function removeInlineStyleProperties(existingStyle, properties) {
615
+ if (!existingStyle) {
616
+ return undefined;
617
+ }
618
+ const propertiesToRemove = new Set(properties.map((property) => property.trim().toLowerCase()).filter(Boolean));
619
+ const declarations = existingStyle
620
+ .split(';')
621
+ .map((declaration) => declaration.trim())
622
+ .filter(Boolean)
623
+ .filter((declaration) => {
624
+ const separatorIndex = declaration.indexOf(':');
625
+ if (separatorIndex === -1) {
626
+ return true;
627
+ }
628
+ const name = declaration.slice(0, separatorIndex).trim().toLowerCase();
629
+ return !propertiesToRemove.has(name);
630
+ });
631
+ if (declarations.length === 0) {
632
+ return undefined;
633
+ }
634
+ return declarations.join('; ');
635
+ }
636
+ function normalizeInlinedListStyles($) {
637
+ $('ol').each((_, element) => {
638
+ const $list = $(element);
639
+ const depth = $list.parents('ol').length;
640
+ const cleanedStyle = removeInlineStyleProperties($list.attr('style'), ['list-style', 'list-style-type', 'list-style-position']);
641
+ const listType = depth === 0 ? '1' : depth === 1 ? 'a' : 'i';
642
+ if (cleanedStyle) {
643
+ $list.attr('style', cleanedStyle);
644
+ }
645
+ else {
646
+ $list.removeAttr('style');
647
+ }
648
+ $list.attr('type', listType);
649
+ });
650
+ $('ul').each((_, element) => {
651
+ const $list = $(element);
652
+ const cleanedStyle = removeInlineStyleProperties($list.attr('style'), ['list-style', 'list-style-type', 'list-style-position']);
653
+ if (cleanedStyle) {
654
+ $list.attr('style', cleanedStyle);
655
+ return;
656
+ }
657
+ $list.removeAttr('style');
658
+ });
659
+ $('ol > li, ul > li').each((_, element) => {
660
+ const $item = $(element);
661
+ const cleanedStyle = removeInlineStyleProperties($item.attr('style'), ['list-style', 'list-style-type', 'list-style-position']);
662
+ if (cleanedStyle) {
663
+ $item.attr('style', cleanedStyle);
664
+ return;
665
+ }
666
+ $item.removeAttr('style');
667
+ });
668
+ }
669
+ function removeWechatUnsafeListWhitespace($) {
670
+ $('ol, ul').each((_, element) => {
671
+ $(element)
672
+ .contents()
673
+ .toArray()
674
+ .filter((node) => isTextNodeEmpty(node))
675
+ .forEach((node) => {
676
+ $(node).remove();
677
+ });
678
+ });
679
+ }
588
680
  function cleanInlinedHtml(html) {
589
681
  const $ = cheerio.load(html);
590
682
  $('pre > code').each((_, element) => {
591
683
  const $element = $(element);
592
684
  $element.html(renderWechatFriendlyCodeHtml($element.contents().toArray()));
593
685
  });
686
+ normalizeInlinedListStyles($);
687
+ removeWechatUnsafeListWhitespace($);
594
688
  const $article = $('body > #write > article').first();
595
689
  const $firstChild = $article.children().first();
596
690
  if ($firstChild.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyhue1991/wxgzh",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Markdown to WeChat Official Account draft CLI",
5
5
  "license": "MIT",
6
6
  "main": "dist/cli/index.js",