2022-11-14 17:50:54 +08:00
/// #if !BROWSER
import { escapeHtml } from "../../util/escape" ;
import * as path from "path" ;
/// #endif
2022-05-26 15:18:53 +08:00
import { hideMessage , showMessage } from "../../dialog/message" ;
2022-11-13 23:34:26 +08:00
import { fetchPost } from "../../util/fetch" ;
import { Dialog } from "../../dialog" ;
import { addScript } from "../util/addScript" ;
import { isMobile } from "../../util/functions" ;
import { Constants } from "../../constants" ;
2023-06-07 10:36:20 +08:00
import { highlightRender } from "../render/highlightRender" ;
2022-11-14 19:00:56 +08:00
import { processRender } from "../util/processCode" ;
2023-01-22 12:21:20 +08:00
import { openByMobile , setStorageVal } from "../util/compatibility" ;
2023-09-19 09:45:57 +08:00
import { showFileInFolder } from "../../util/pathName" ;
2022-05-26 15:18:53 +08:00
2022-06-06 23:04:56 +08:00
export const afterExport = ( exportPath : string , msgId : string ) = > {
2022-11-14 17:50:54 +08:00
/// #if !BROWSER
2022-12-11 11:51:04 +08:00
showMessage ( ` ${ window . siyuan . languages . exported } ${ escapeHtml ( exportPath ) }
2022-06-06 23:04:56 +08:00
< div class = "fn__space" > < / div >
< button class = "b3-button b3-button--white" > $ { window . siyuan . languages . showInFolder } < / button > ` , 6000, "info", msgId);
document . querySelector ( ` #message [data-id=" ${ msgId } "] button ` ) . addEventListener ( "click" , ( ) = > {
2023-09-19 09:45:57 +08:00
showFileInFolder ( path . join ( exportPath ) ) ;
2022-06-06 23:04:56 +08:00
hideMessage ( msgId ) ;
2022-05-26 15:18:53 +08:00
} ) ;
2022-11-14 17:50:54 +08:00
/// #endif
2022-05-26 15:18:53 +08:00
} ;
2022-11-13 23:34:26 +08:00
2023-10-25 09:49:43 +08:00
export const exportImage = ( id : string ) = > {
2022-11-13 23:34:26 +08:00
const exportDialog = new Dialog ( {
2023-04-20 10:05:24 +08:00
title : window.siyuan.languages.exportAsImage ,
2023-05-22 22:08:01 +08:00
content : ` <div class="b3-dialog__content" style=" ${ isMobile ( ) ? "padding:8px;" : "" } ;background-color: var(--b3-theme-background)">
2023-10-24 10:39:37 +08:00
< div style = "${isMobile() ? " padding : 16px ; margin : 16px 0 " : " padding : 48px ; margin : 8px 0 24px "};border: 1px solid var(--b3-border-color);border-radius: var(--b3-border-radius-b);"
class = "export-img protyle-wysiwyg${window.siyuan.config.editor.displayBookmarkIcon ? " protyle - wysiwyg -- attr " : " "}"
id = "preview" > < / div >
2022-11-13 23:34:26 +08:00
< div class = "fn__hr--b" > < / div >
< div class = "fn__hr--b" > < / div >
< / div >
< div class = "b3-dialog__action" >
2023-04-20 10:05:24 +08:00
< label class = "fn__flex" >
$ { window . siyuan . languages . exportPDF5 }
< span class = "fn__space" > < / span >
< input id = "keepFold" class = "b3-switch fn__flex-center" type = "checkbox" $ { window.siyuan.storage [ Constants.LOCAL_EXPORTIMG ] .keepFold ? "checked" : "" } >
< / label >
< span class = "fn__flex-1" > < / span >
2023-01-22 12:21:20 +08:00
< button disabled class = "b3-button b3-button--cancel" > $ { window . siyuan . languages . cancel } < / button > < div class = "fn__space" > < / div >
< button disabled class = "b3-button b3-button--text" > $ { window . siyuan . languages . confirm } < / button >
< / div >
< div class = "fn__loading" > < img height = "128px" width = "128px" src = "stage/loading-pure.svg" > < / div > ` ,
2023-04-20 10:05:24 +08:00
width : isMobile ( ) ? "92vw" : "990px" ,
2023-05-22 22:08:01 +08:00
height : "70vh"
2022-11-13 23:34:26 +08:00
} ) ;
2023-01-22 12:21:20 +08:00
const btnsElement = exportDialog . element . querySelectorAll ( ".b3-button" ) ;
btnsElement [ 0 ] . addEventListener ( "click" , ( ) = > {
exportDialog . destroy ( ) ;
} ) ;
btnsElement [ 1 ] . addEventListener ( "click" , ( ) = > {
const msgId = showMessage ( window . siyuan . languages . exporting , 0 ) ;
2023-05-22 22:08:01 +08:00
( exportDialog . element . querySelector ( ".b3-dialog__container" ) as HTMLElement ) . style . height = "" ;
2023-01-22 12:21:20 +08:00
setStorageVal ( Constants . LOCAL_EXPORTIMG , window . siyuan . storage [ Constants . LOCAL_EXPORTIMG ] ) ;
setTimeout ( ( ) = > {
2023-06-15 10:20:06 +08:00
addScript ( "/stage/protyle/js/html2canvas.min.js?v=1.4.1" , "protyleHtml2canvas" ) . then ( ( ) = > {
2023-05-10 18:01:33 +08:00
window . html2canvas ( previewElement . parentElement , { useCORS : true } ) . then ( ( canvas ) = > {
2023-01-22 12:21:20 +08:00
canvas . toBlob ( ( blob : Blob ) = > {
const formData = new FormData ( ) ;
formData . append ( "file" , blob , btnsElement [ 1 ] . getAttribute ( "data-title" ) ) ;
formData . append ( "type" , "image/png" ) ;
fetchPost ( "/api/export/exportAsFile" , formData , ( response ) = > {
openByMobile ( response . data . file ) ;
} ) ;
hideMessage ( msgId ) ;
exportDialog . destroy ( ) ;
} ) ;
} ) ;
} ) ;
2023-05-10 20:18:40 +08:00
} , Constants . TIMEOUT_LOAD ) ;
2023-01-22 12:21:20 +08:00
} ) ;
const previewElement = exportDialog . element . querySelector ( "#preview" ) as HTMLElement ;
2023-01-24 20:33:13 +08:00
const foldElement = ( exportDialog . element . querySelector ( "#keepFold" ) as HTMLInputElement ) ;
2023-01-22 12:21:20 +08:00
foldElement . addEventListener ( "change" , ( ) = > {
btnsElement [ 0 ] . setAttribute ( "disabled" , "disabled" ) ;
btnsElement [ 1 ] . setAttribute ( "disabled" , "disabled" ) ;
2023-01-27 10:44:31 +08:00
btnsElement [ 1 ] . parentElement . insertAdjacentHTML ( "afterend" , '<div class="fn__loading"><img height="128px" width="128px" src="stage/loading-pure.svg"></div>' ) ;
2023-01-22 12:21:20 +08:00
window . siyuan . storage [ Constants . LOCAL_EXPORTIMG ] . keepFold = foldElement . checked ;
fetchPost ( "/api/export/exportPreviewHTML" , {
id ,
keepFold : foldElement.checked ,
image : true ,
} , ( response ) = > {
refreshPreview ( response ) ;
2023-01-24 20:33:13 +08:00
} ) ;
2023-01-22 12:21:20 +08:00
} ) ;
const refreshPreview = ( response : IWebSocketData ) = > {
2022-11-13 23:34:26 +08:00
previewElement . innerHTML = response . data . content ;
2023-11-22 09:46:06 +08:00
// https://github.com/siyuan-note/siyuan/issues/9685
2023-11-30 13:08:06 +08:00
previewElement . querySelectorAll ( '[data-type~="mark"], [data-type~="u"], [data-type~="text"], [data-type~="code"], [data-type~="tag"], [data-type~="kbd"]' ) . forEach ( ( markItem : HTMLElement ) = > {
2023-11-22 09:46:06 +08:00
markItem . childNodes . forEach ( ( item ) = > {
2023-11-23 11:35:26 +08:00
let spanHTML = "" ;
2023-11-22 09:46:06 +08:00
Array . from ( item . textContent ) . forEach ( str = > {
2023-11-30 13:08:06 +08:00
spanHTML += ` <span style=" ${ markItem . getAttribute ( "style" ) || "" } ;border-radius: 0;padding-left: 0;padding-right: 0;box-shadow: none;border-left:0;border-right:0;border-top:0" data-type=" ${ markItem . getAttribute ( "data-type" ) } "> ${ str } </span> ` ;
2023-11-23 11:35:26 +08:00
} ) ;
2023-11-22 09:46:06 +08:00
const templateElement = document . createElement ( "template" ) ;
templateElement . innerHTML = spanHTML ;
item . after ( templateElement . content ) ;
item . remove ( ) ;
2023-11-23 11:35:26 +08:00
} ) ;
2023-11-22 09:46:06 +08:00
if ( markItem . childNodes . length > 0 ) {
2023-11-30 13:08:06 +08:00
markItem . setAttribute ( "style" , "" ) ;
markItem . setAttribute ( "data-type" , markItem . getAttribute ( "data-type" ) . replace ( /mark|u|text|code|tag|kbd/g , "" ) ) ;
2023-11-22 09:46:06 +08:00
}
} ) ;
2023-10-25 09:49:43 +08:00
previewElement . setAttribute ( "data-doc-type" , response . data . type || "NodeDocument" ) ;
if ( response . data . attrs . memo ) {
previewElement . setAttribute ( "memo" , response . data . attrs . memo ) ;
}
if ( response . data . attrs . name ) {
previewElement . setAttribute ( "name" , response . data . attrs . name ) ;
}
if ( response . data . attrs . bookmark ) {
previewElement . setAttribute ( "bookmark" , response . data . attrs . bookmark ) ;
}
if ( response . data . attrs . alias ) {
previewElement . setAttribute ( "alias" , response . data . attrs . alias ) ;
}
2022-11-14 19:00:56 +08:00
processRender ( previewElement ) ;
2022-11-13 23:34:26 +08:00
highlightRender ( previewElement ) ;
previewElement . querySelectorAll ( "table" ) . forEach ( ( item : HTMLElement ) = > {
if ( item . clientWidth > item . parentElement . clientWidth ) {
2023-02-12 23:23:44 +08:00
item . setAttribute ( "style" , ` margin-bottom: ${ item . parentElement . clientWidth * item . clientHeight / item . clientWidth - item . parentElement . clientHeight + 1 } px;transform: scale( ${ item . parentElement . clientWidth / item . clientWidth } );transform-origin: top left; ` ) ;
2023-02-12 23:03:17 +08:00
item . parentElement . style . overflow = "hidden" ;
2022-11-13 23:34:26 +08:00
}
} ) ;
2022-11-16 19:57:18 +08:00
previewElement . querySelectorAll ( ".li > .protyle-action > svg" ) . forEach ( item = > {
2022-11-19 10:49:43 +08:00
const id = item . firstElementChild . getAttribute ( "xlink:href" ) ;
const symbolElements = document . querySelectorAll ( id ) ;
2022-11-16 19:57:18 +08:00
let viewBox = "0 0 32 32" ;
if ( id === "#iconDot" ) {
viewBox = "0 0 20 20" ;
}
item . setAttribute ( "viewBox" , viewBox ) ;
item . innerHTML = symbolElements [ symbolElements . length - 1 ] . innerHTML ;
} ) ;
2023-01-22 12:21:20 +08:00
btnsElement [ 0 ] . removeAttribute ( "disabled" ) ;
btnsElement [ 1 ] . removeAttribute ( "disabled" ) ;
exportDialog . element . querySelector ( ".fn__loading" ) . remove ( ) ;
} ;
fetchPost ( "/api/export/exportPreviewHTML" , {
id ,
keepFold : foldElement.checked ,
image : true ,
} , ( response ) = > {
refreshPreview ( response ) ;
btnsElement [ 1 ] . setAttribute ( "data-title" , response . data . name + ".png" ) ;
2022-11-13 23:34:26 +08:00
} ) ;
2022-11-14 19:02:56 +08:00
} ;