diff --git a/src/commands.ts b/src/commands.ts
index 75f5de0..907033e 100644
--- a/src/commands.ts
+++ b/src/commands.ts
@@ -224,22 +224,13 @@ const cmd_export_wxmp = (plugin:NoteSyncPlugin) => ({
let htmls = [];
let ctx = plugin.easyapi.ceditor.getSelection();
if(!ctx){
- ctx = await plugin.app.vault.read(plugin.easyapi.cfile);
- for(let section of plugin.easyapi.cmeta?.sections || []){
- if(section.type=='yaml'){
- continue
- }
- let sec = plugin.easyapi.editor.slice_by_position(ctx,section.position);
- let html = plugin.wxmp.marked.marked(sec);
- let rhtml = await plugin.wxmp.html_to_wxmp(html);
- htmls.push(rhtml);
- }
+ plugin.wxmp.tfile_to_wxmp(plugin.easyapi.cfile);
}else{
let html = plugin.wxmp.marked.marked(ctx);
let rhtml = await plugin.wxmp.html_to_wxmp(html);
htmls.push(rhtml);
+ plugin.wxmp.copy_as_html(htmls);
}
- plugin.wxmp.copy_as_html(htmls);
new Notice(`${plugin.strings.cmd_export_wxmp}: OK`,5000)
}
});
diff --git a/src/wxmp.ts b/src/wxmp.ts
index 1a9a1b0..67c89fb 100644
--- a/src/wxmp.ts
+++ b/src/wxmp.ts
@@ -16,31 +16,38 @@ export class Wxmp {
this.hljs = require('highlight.js');
}
- get ctx_map(){
- let config:{[key:string]:any} = {};
- for(let line of this.plugin.settings.wxmp_config.split('\n')){
- let [key, value] = line.split(':');
- if(!key || !value){continue}
- key = key.trim();
- value = value.trim();
- if(!key || !value){continue}
- config[key] = value;
+ get ctx_map() {
+ let msg = this.plugin.settings.wxmp_config.trim();
+ if(msg.trim()==''){
+ return {};
+ }
+ let config = this.plugin.easyapi.editor.yamljs.load(msg);
+ if(!config){
+ return {};
}
if(!config['h1']){
config['h1'] = this.format_wxmp_h1;
}
- if(!config['h2']){
+
+ if (!config['h1']) {
+ config['h1'] = this.format_wxmp_h1;
+ }
+ if (!config['h2']) {
config['h2'] = this.format_wxmp_h2;
}
- if(!config['h3']){
+ if (!config['h3']) {
config['h3'] = this.format_wxmp_h3;
}
- if(!config['p code']){
+ if (!config['p code']) {
config['p code'] = this.format_wxmp_p_code;
}
- if(!config['li code']){
+ if (!config['li code']) {
config['li code'] = this.format_wxmp_li_code;
}
+
+ if (!config['section@cards-album']) {
+ config['section@cards-album'] = this.format_code_block_cards_album.bind(this);
+ }
return config;
}
@@ -64,7 +71,7 @@ export class Wxmp {
}
}
- async replace_regx_with_tpl(rhtml:string, regx:RegExp, tpl:string) {
+ async replace_regx_with_tpl(rhtml: string, regx: RegExp, tpl: string) {
let matches = [...rhtml.matchAll(regx)];
let replacements = await Promise.all(
@@ -82,13 +89,13 @@ export class Wxmp {
return rhtml;
}
- convertVaultImageLinksToImgTag(htmlString:string) {
+ convertVaultImageLinksToImgTag(htmlString: string) {
return htmlString.replace(/!\[\[([^\]]+?)\]\]/g, (match, filename) => {
return `
`;
});
}
- async convertImageTagsToBase64(htmlString:string) {
+ async convertImageTagsToBase64(htmlString: string) {
const parser = new DOMParser();
const doc = parser.parseFromString(htmlString, 'text/html');
@@ -114,8 +121,57 @@ export class Wxmp {
return new XMLSerializer().serializeToString(doc.body);
}
+ async tfile_to_wxmp(tfile: TFile) {
+ let htmls = [];
+ let ctx = await this.app.vault.read(tfile);
+ for (let section of this.app.metadataCache.getFileCache(tfile)?.sections || []) {
+ if (section.type == 'yaml') {
+ continue
+ }
+ let sec = this.plugin.easyapi.editor.slice_by_position(ctx, section.position);
- async html_to_wxmp(html:string) {
+ let rhtml:any = null;
+
+ for(let k in this.ctx_map){
+ if(k.startsWith('section@')){
+ let tpl = this.ctx_map[k];
+ if (typeof tpl == 'function') {
+ rhtml = await tpl(section,sec);
+ } else {
+ let rendered = await this.plugin.easyapi.tpl.parse_templater(
+ tpl, true,{section:section,sec:sec},[0]
+ );
+ if (rendered.length > 0 && rendered[0].trim() != '') {
+ rhtml = rendered[0];
+ }
+ }
+ if(rhtml){
+ break;
+ }
+ }
+ }
+
+ if(!rhtml){
+ if(section.type == 'code'){
+ let items = sec.split('\n');
+ items[0] = items[0].slice(0,3)+'js'+'\n//'+items[0].slice(3);
+ sec = items.join('\n');
+ }
+ let html = this.marked.marked(sec);
+ rhtml = await this.html_to_wxmp(html);
+ htmls.push(rhtml);
+ }else{
+ if(Array.isArray(rhtml)){
+ htmls.push(...rhtml);
+ }else{
+ htmls.push(rhtml);
+ }
+ }
+ }
+ this.plugin.wxmp.copy_as_html(htmls);
+ }
+
+ async html_to_wxmp(html: string) {
let rhtml;
// 替换图片
@@ -129,6 +185,7 @@ export class Wxmp {
// 替换标题
for (let k in this.ctx_map) {
+ if(k.contains('@')){continue;}
rhtml = await this.set_tag_with_tpl(rhtml, k, this.ctx_map[k]);
}
@@ -142,7 +199,7 @@ export class Wxmp {
return rhtml
}
- async set_tag_with_tpl(htmlString:string, selector:string, tpl:string|Function) {
+ async set_tag_with_tpl(htmlString: string, selector: string, tpl: string | Function) {
let parser = new DOMParser();
let doc = parser.parseFromString(htmlString, 'text/html');
let items = doc.querySelectorAll(selector);
@@ -150,12 +207,12 @@ export class Wxmp {
await Promise.all(Array.from(items).map(async (item) => {
let content = item.textContent;
- if(typeof tpl == 'function'){
+ if (typeof tpl == 'function') {
let rendered = tpl(content);
- if(rendered){
+ if (rendered) {
item.innerHTML = rendered;
}
- }else{
+ } else {
// 模板渲染,传入content
let rendered = await this.plugin.easyapi.tpl.parse_templater(tpl, true, content);
if (rendered.length > 0) {
@@ -171,7 +228,7 @@ export class Wxmp {
}
- setLastLiMargin(htmlString:string) {
+ setLastLiMargin(htmlString: string) {
let parser = new DOMParser();
let doc = parser.parseFromString(htmlString, 'text/html');
@@ -197,7 +254,7 @@ export class Wxmp {
}
- setParagraphSpacingBeforeList(htmlString:string) {
+ setParagraphSpacingBeforeList(htmlString: string) {
// 创建一个新的DOM解析器
let parser = new DOMParser();
// 将HTML字符串解析为文档对象
@@ -222,7 +279,7 @@ export class Wxmp {
return modifiedHtmlString;
}
- html_replace_url(html:string) {
+ html_replace_url(html: string) {
let regx = /]*class="external-link"[^>]*href="(.*?)"[^>]*?>([\s\S]*?)<\/a>/g
let rhtml = html.replace(regx, (m, href, text) => {
@@ -245,7 +302,7 @@ export class Wxmp {
}
- html_replace_code(html:string) {
+ html_replace_code(html: string) {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const codeBlocks = Array.from(doc.querySelectorAll('pre > code[class^="language-"]'));
@@ -359,7 +416,7 @@ export class Wxmp {
await navigator.clipboard.write([data]);
}
- formatWeChatImageLink(inputHtml:string) {
+ formatWeChatImageLink(inputHtml: string) {
// 创建一个临时的 div 元素来解析 HTML
let tempDiv = document.createElement('div');
tempDiv.innerHTML = inputHtml;
@@ -397,36 +454,119 @@ export class Wxmp {
return tempDiv.innerHTML;
}
- format_wxmp_h1(title:string){
+ format_wxmp_h1(title: string) {
let css = `
${title}
`.trim()
return css;
}
- format_wxmp_h2(title:string){
+ format_wxmp_h2(title: string) {
let css = `
${title}
`.trim()
return css;
}
- format_wxmp_h3(title:string){
+ format_wxmp_h3(title: string) {
let css = `
${title}
`.trim()
return css;
}
- format_wxmp_p_code(code:string){
+ format_wxmp_p_code(code: string) {
let css = `
${code}`.trim()
return css;
}
- format_wxmp_li_code(code:string){
+ format_wxmp_li_code(code: string) {
let css = `
${code}`.trim()
return css;
}
+
+ is_code_balck(section:any,sec:string,lang:string){
+ return section.type == 'code' && sec.trim().slice(3).startsWith(lang)
+ }
+
+ async format_code_block_cards_album(section: any, sec:string) {
+ if(section.type != 'code' || !sec.trim().slice(3).startsWith('cards-album')){
+ return null;
+ }
+ let items = [];
+ for(let ctx of sec.split('images:')[1].split(/\n\s+/)){
+ if(ctx.trim() == ''){
+ continue;
+ }
+ let img = await this.images2html(ctx);
+ if(img){
+ items.push(img);;
+ }
+ }
+ if(items.length == 0){
+ return null;
+ }
+ return items;
+ }
+
+
+ generateSideBySideImages(base64Images: string[]) {
+ const sectionStart = ``;
+
+ const sectionEnd = ``;
+
+ const imageSections = base64Images.map((base64, index) => {
+ return `
+
+
+
+
+
+
+
+ `;
+ }).join("");
+
+ return sectionStart + imageSections + sectionEnd;
+ }
+
+ async images2html(imgs: string | string[]): Promise {
+ if (Array.isArray(imgs)) {
+ let ximgs = [];
+ for (let x of imgs) {
+ if (x.startsWith('http')) {
+ ximgs.push(x)
+ } else {
+ let c = await this.image_to_img(x, true);
+ ximgs.push(c)
+ }
+ }
+ ximgs = ximgs.filter((x): x is string => x !== undefined && x !== null);
+ if (ximgs.length > 0) {
+ let html = this.generateSideBySideImages(ximgs);
+ return html
+ } else {
+ return null;
+ }
+ } else if (typeof imgs == 'string') {
+ let obsidianImgs = imgs.match(/!?\[\[([^|\]]+\.(?:png|jpg|jpeg|gif|webp|bmp|svg))(?:\|.*?)?]]/g) || [];
+
+ let markdownImgs = Array.from(
+ imgs.matchAll(/!\[\]\((https?:\/\/[^\s)]+)\)/g),
+ m => m[1]
+ );
+
+ // 合并两种图片链接
+ let ximgs = [...obsidianImgs, ...markdownImgs];
+ return this.images2html(ximgs);
+ }else{
+ return null;
+ }
+ }
+
+
}