@lyhue1991/wxgzh 0.1.3 → 0.1.4

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,6 @@
1
- # wxgzh
1
+ # wxgzh,这个SKILL打通了AI写公众号文章的最后一公里
2
2
 
3
- 一个面向微信公众号的 SKILL,基于 NodeJS CLI.
3
+ 这是一个面向微信公众号的 SKILL,基于 NodeJS CLI.
4
4
 
5
5
  把 Markdown 文章处理成适合公众号发布的 HTML,上传图片,生成封面,并提交到公众号草稿箱。
6
6
 
@@ -10,6 +10,12 @@
10
10
  npx skills add lyhue1991/wxgzh
11
11
  ```
12
12
 
13
+ 效果演示
14
+
15
+ ![](wxgzh_shot1.png)
16
+
17
+ ![](wxgzh_shot2.png)
18
+
13
19
 
14
20
  ## 一、功能概述
15
21
 
@@ -260,6 +260,32 @@ section.tbl-wrapper a {
260
260
  text-decoration: none !important;
261
261
  }
262
262
  `;
263
+ const WECHAT_CODE_BLOCK_INLINE_CSS = `
264
+ pre {
265
+ overflow-x: auto !important;
266
+ overflow-y: hidden !important;
267
+ -webkit-overflow-scrolling: touch;
268
+ }
269
+
270
+ pre code.hljs,
271
+ pre code[class*="language-"] {
272
+ display: block !important;
273
+ width: max-content !important;
274
+ min-width: 100% !important;
275
+ box-sizing: border-box !important;
276
+ white-space: nowrap !important;
277
+ word-break: normal !important;
278
+ overflow-wrap: normal !important;
279
+ overflow: visible !important;
280
+ }
281
+
282
+ pre code.hljs *,
283
+ pre code[class*="language-"] * {
284
+ white-space: inherit !important;
285
+ word-break: inherit !important;
286
+ overflow-wrap: inherit !important;
287
+ }
288
+ `;
263
289
  const WECHAT_MATH_INLINE_CSS = `
264
290
  span.math-inline {
265
291
  display: inline-block !important;
@@ -587,51 +613,59 @@ function createDocumentHtml(content, metadata) {
587
613
  ].join('\n');
588
614
  }
589
615
  function setInlineStyleProperty(existingStyle, property, value) {
590
- const entries = new Map();
591
- if (existingStyle) {
592
- for (const declaration of existingStyle.split(';')) {
593
- const trimmed = declaration.trim();
594
- if (!trimmed) {
595
- continue;
596
- }
597
- const separatorIndex = trimmed.indexOf(':');
598
- if (separatorIndex === -1) {
599
- continue;
600
- }
601
- const name = trimmed.slice(0, separatorIndex).trim();
602
- const declarationValue = trimmed.slice(separatorIndex + 1).trim();
603
- if (!name || !declarationValue) {
604
- continue;
605
- }
606
- entries.set(name, declarationValue);
607
- }
608
- }
616
+ const entries = parseInlineStyle(existingStyle);
609
617
  entries.set(property, value);
610
- return Array.from(entries.entries())
611
- .map(([name, declarationValue]) => `${name}: ${declarationValue}`)
612
- .join('; ');
618
+ return stringifyInlineStyle(entries) ?? '';
613
619
  }
614
620
  function removeInlineStyleProperties(existingStyle, properties) {
621
+ const entries = parseInlineStyle(existingStyle);
622
+ const propertiesToRemove = new Set(properties.map((property) => property.trim().toLowerCase()).filter(Boolean));
623
+ for (const name of Array.from(entries.keys())) {
624
+ if (propertiesToRemove.has(name.toLowerCase())) {
625
+ entries.delete(name);
626
+ }
627
+ }
628
+ return stringifyInlineStyle(entries);
629
+ }
630
+ function parseInlineStyle(existingStyle) {
631
+ const entries = new Map();
615
632
  if (!existingStyle) {
616
- return undefined;
633
+ return entries;
617
634
  }
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(':');
635
+ for (const declaration of existingStyle.split(';')) {
636
+ const trimmed = declaration.trim();
637
+ if (!trimmed) {
638
+ continue;
639
+ }
640
+ const separatorIndex = trimmed.indexOf(':');
625
641
  if (separatorIndex === -1) {
626
- return true;
642
+ continue;
627
643
  }
628
- const name = declaration.slice(0, separatorIndex).trim().toLowerCase();
629
- return !propertiesToRemove.has(name);
630
- });
631
- if (declarations.length === 0) {
644
+ const name = trimmed.slice(0, separatorIndex).trim();
645
+ const declarationValue = trimmed.slice(separatorIndex + 1).trim();
646
+ if (!name || !declarationValue) {
647
+ continue;
648
+ }
649
+ entries.set(name, declarationValue);
650
+ }
651
+ return entries;
652
+ }
653
+ function stringifyInlineStyle(entries) {
654
+ if (entries.size === 0) {
632
655
  return undefined;
633
656
  }
634
- return declarations.join('; ');
657
+ return Array.from(entries.entries())
658
+ .map(([name, declarationValue]) => `${name}: ${declarationValue}`)
659
+ .join('; ');
660
+ }
661
+ function getInlineStyleProperty(existingStyle, property) {
662
+ const entries = parseInlineStyle(existingStyle);
663
+ for (const [name, declarationValue] of entries.entries()) {
664
+ if (name.trim().toLowerCase() === property.trim().toLowerCase()) {
665
+ return declarationValue;
666
+ }
667
+ }
668
+ return undefined;
635
669
  }
636
670
  function normalizeInlinedListStyles($) {
637
671
  $('ol').each((_, element) => {
@@ -677,6 +711,95 @@ function removeWechatUnsafeListWhitespace($) {
677
711
  });
678
712
  });
679
713
  }
714
+ function normalizeWechatCodeBlocks($) {
715
+ const backgroundStyleProperties = [
716
+ 'background',
717
+ 'background-color',
718
+ 'background-image',
719
+ 'background-repeat',
720
+ 'background-position',
721
+ 'background-size'
722
+ ];
723
+ const codeStyleProperties = [
724
+ ...backgroundStyleProperties,
725
+ 'border',
726
+ 'border-top',
727
+ 'border-right',
728
+ 'border-bottom',
729
+ 'border-left',
730
+ 'border-color',
731
+ 'border-style',
732
+ 'border-width',
733
+ 'border-radius',
734
+ 'box-shadow',
735
+ 'padding',
736
+ 'padding-top',
737
+ 'padding-right',
738
+ 'padding-bottom',
739
+ 'padding-left'
740
+ ];
741
+ const wrapperStyleProperties = ['margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left'];
742
+ $('pre').each((_, element) => {
743
+ const $pre = $(element);
744
+ const $code = $pre.children('code').first();
745
+ if ($code.length === 0) {
746
+ return;
747
+ }
748
+ if (!$pre.parent().is('section.code-block-wrapper')) {
749
+ $pre.wrap('<section class="code-block-wrapper"></section>');
750
+ }
751
+ const $wrapper = $pre.parent();
752
+ const codeStyle = $code.attr('style');
753
+ const preStyle = $pre.attr('style');
754
+ for (const property of wrapperStyleProperties) {
755
+ const value = getInlineStyleProperty(codeStyle, property) ?? getInlineStyleProperty(preStyle, property);
756
+ if (!value) {
757
+ continue;
758
+ }
759
+ $wrapper.attr('style', setInlineStyleProperty($wrapper.attr('style'), property, value));
760
+ }
761
+ $wrapper.attr('style', setInlineStyleProperty($wrapper.attr('style'), 'display', 'block !important'));
762
+ $wrapper.attr('style', setInlineStyleProperty($wrapper.attr('style'), 'overflow-x', 'auto !important'));
763
+ $wrapper.attr('style', setInlineStyleProperty($wrapper.attr('style'), 'overflow-y', 'hidden !important'));
764
+ $wrapper.attr('style', setInlineStyleProperty($wrapper.attr('style'), '-webkit-overflow-scrolling', 'touch'));
765
+ for (const property of codeStyleProperties) {
766
+ const value = getInlineStyleProperty(codeStyle, property);
767
+ if (!value) {
768
+ continue;
769
+ }
770
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), property, value));
771
+ }
772
+ $pre.attr('style', removeInlineStyleProperties($pre.attr('style'), wrapperStyleProperties));
773
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'display', 'inline-block !important'));
774
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'width', 'max-content !important'));
775
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'min-width', '100% !important'));
776
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'max-width', 'none !important'));
777
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'box-sizing', 'border-box !important'));
778
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'white-space', 'normal !important'));
779
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'word-break', 'normal !important'));
780
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'overflow', 'visible !important'));
781
+ $pre.attr('style', setInlineStyleProperty($pre.attr('style'), 'vertical-align', 'top !important'));
782
+ $code.attr('style', removeInlineStyleProperties($code.attr('style'), [...codeStyleProperties, ...wrapperStyleProperties]));
783
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'display', 'inline-block !important'));
784
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'width', 'max-content !important'));
785
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'min-width', '100% !important'));
786
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'max-width', 'none !important'));
787
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'white-space', 'nowrap !important'));
788
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'word-break', 'normal !important'));
789
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'overflow-wrap', 'normal !important'));
790
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'border', '0 !important'));
791
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'border-radius', '0 !important'));
792
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'padding', '0 !important'));
793
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), 'margin', '0 !important'));
794
+ for (const property of backgroundStyleProperties) {
795
+ const value = getInlineStyleProperty(codeStyle, property) ?? getInlineStyleProperty(preStyle, property);
796
+ if (!value) {
797
+ continue;
798
+ }
799
+ $code.attr('style', setInlineStyleProperty($code.attr('style'), property, value));
800
+ }
801
+ });
802
+ }
680
803
  function cleanInlinedHtml(html) {
681
804
  const $ = cheerio.load(html);
682
805
  $('pre > code').each((_, element) => {
@@ -685,6 +808,7 @@ function cleanInlinedHtml(html) {
685
808
  });
686
809
  normalizeInlinedListStyles($);
687
810
  removeWechatUnsafeListWhitespace($);
811
+ normalizeWechatCodeBlocks($);
688
812
  const $article = $('body > #write > article').first();
689
813
  const $firstChild = $article.children().first();
690
814
  if ($firstChild.length > 0) {
@@ -739,7 +863,7 @@ async function renderMarkdownToHtml(body, metadata) {
739
863
  const articleHtml = $('article').html() ?? '';
740
864
  const baseHtml = createDocumentHtml(articleHtml, metadata);
741
865
  const inlinedHtml = (0, css_inline_1.inline)(baseHtml, {
742
- extraCss: `${themeCss}\n${HIGHLIGHT_INLINE_CSS}\n${WECHAT_BLOCKQUOTE_INLINE_CSS}\n${WECHAT_TABLE_INLINE_CSS}\n${WECHAT_MATH_INLINE_CSS}\n${WECHAT_LAYOUT_INLINE_CSS}\n${customCss}`,
866
+ extraCss: `${themeCss}\n${HIGHLIGHT_INLINE_CSS}\n${WECHAT_BLOCKQUOTE_INLINE_CSS}\n${WECHAT_TABLE_INLINE_CSS}\n${WECHAT_CODE_BLOCK_INLINE_CSS}\n${WECHAT_MATH_INLINE_CSS}\n${WECHAT_LAYOUT_INLINE_CSS}\n${customCss}`,
743
867
  keepAtRules: true,
744
868
  applyWidthAttributes: false,
745
869
  applyHeightAttributes: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyhue1991/wxgzh",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Markdown to WeChat Official Account draft CLI",
5
5
  "license": "MIT",
6
6
  "main": "dist/cli/index.js",