@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 +8 -2
- package/dist/core/converter.js +161 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# wxgzh
|
|
1
|
+
# wxgzh,这个SKILL打通了AI写公众号文章的最后一公里
|
|
2
2
|
|
|
3
|
-
|
|
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
|
+

|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
13
19
|
|
|
14
20
|
## 一、功能概述
|
|
15
21
|
|
package/dist/core/converter.js
CHANGED
|
@@ -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 =
|
|
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
|
|
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
|
|
633
|
+
return entries;
|
|
617
634
|
}
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
.
|
|
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
|
-
|
|
642
|
+
continue;
|
|
627
643
|
}
|
|
628
|
-
const name =
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
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
|
|
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
|