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" ;
2025-03-07 23:38:52 +08:00
import { fetchPost } from "../../util/fetch" ;
2022-11-13 23:34:26 +08:00
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" ;
2024-01-01 23:25:27 +08:00
import { isPaidUser } from "../../util/needSubscribe" ;
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-12-27 22:26:51 +08:00
< div style = "${isMobile() ? " padding : 16px ; margin : 8px 0 " : " padding : 48px ; margin : 8px 0 "};" class = "export-img" >
< div class = "protyle-wysiwyg${window.siyuan.config.editor.displayBookmarkIcon ? " protyle - wysiwyg - - attr " : " "}" > < / div >
< div class = "export-img__watermark" > < / div >
< / div >
2022-11-13 23:34:26 +08:00
< / 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 >
2023-12-27 22:26:51 +08:00
< label class = "fn__flex" style = "margin-left: 24px" >
2024-01-28 10:35:09 +08:00
$ { window . siyuan . languages . export30 }
2023-12-27 11:54:22 +08:00
< span class = "fn__space" > < / span >
< input id = "watermark" class = "b3-switch fn__flex-center" type = "checkbox" $ { window.siyuan.storage [ Constants.LOCAL_EXPORTIMG ] .watermark ? "checked" : "" } >
< / label >
2024-01-26 19:49:35 +08:00
< span class = "fn__flex-1 export-img__space" > < / 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
} ) ;
2024-01-10 22:31:28 +08:00
exportDialog . element . setAttribute ( "data-key" , Constants . DIALOG_EXPORTIMAGE ) ;
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 ( ( ) = > {
2025-03-07 13:45:49 +08:00
addScript ( "/stage/protyle/js/html-to-image.min.js?v=1.11.13" , "protyleHtml2image" ) . then ( ( ) = > {
window . htmlToImage . toBlob ( exportDialog . element . querySelector ( ".b3-dialog__content" ) ) . then ( ( 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 ) ;
2023-01-22 12:21:20 +08:00
} ) ;
2025-03-07 13:45:49 +08:00
hideMessage ( msgId ) ;
exportDialog . destroy ( ) ;
2023-01-22 12:21:20 +08:00
} ) ;
} ) ;
2023-05-10 20:18:40 +08:00
} , Constants . TIMEOUT_LOAD ) ;
2023-01-22 12:21:20 +08:00
} ) ;
2023-12-27 22:26:51 +08:00
const previewElement = exportDialog . element . querySelector ( ".protyle-wysiwyg" ) 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
} ) ;
2023-12-27 11:54:22 +08:00
const watermarkElement = ( exportDialog . element . querySelector ( "#watermark" ) as HTMLInputElement ) ;
watermarkElement . addEventListener ( "change" , ( ) = > {
window . siyuan . storage [ Constants . LOCAL_EXPORTIMG ] . watermark = watermarkElement . checked ;
2024-01-01 23:25:09 +08:00
if ( watermarkElement . checked && ! isPaidUser ( ) ) {
2023-12-27 11:54:22 +08:00
watermarkElement . checked = false ;
2024-01-01 23:25:09 +08:00
showMessage ( window . siyuan . languages . _kernel [ 214 ] ) ;
2023-12-27 11:54:22 +08:00
}
updateWatermark ( ) ;
} ) ;
const updateWatermark = ( ) = > {
2024-01-01 23:25:09 +08:00
if ( ! isPaidUser ( ) ) {
return ;
}
2023-12-27 11:54:22 +08:00
const watermarkPreviewElement = exportDialog . element . querySelector ( ".export-img__watermark" ) as HTMLElement ;
2023-12-27 22:53:25 +08:00
watermarkPreviewElement . innerHTML = "" ;
2023-12-27 11:54:22 +08:00
if ( watermarkElement . checked ) {
if ( window . siyuan . config . export . imageWatermarkDesc ) {
2023-12-27 22:53:25 +08:00
watermarkPreviewElement . innerHTML = window . siyuan . config . export . imageWatermarkDesc ;
2023-12-27 11:54:22 +08:00
} else if ( window . siyuan . config . export . imageWatermarkStr ) {
2023-12-27 22:53:25 +08:00
if ( window . siyuan . config . export . imageWatermarkStr . startsWith ( "http" ) ) {
2023-12-29 15:00:36 +08:00
watermarkPreviewElement . setAttribute ( "style" , ` background-image: url( ${ window . siyuan . config . export . imageWatermarkStr } );background-repeat: repeat;position: absolute;top: 0;left: 0;width: 100%;height: 100%;border-radius: var(--b3-border-radius-b); ` ) ;
2023-12-27 22:53:25 +08:00
} else {
2025-03-07 13:45:49 +08:00
addScript ( "/stage/protyle/js/html-to-image.min.js?v=1.11.13" , "protyleHtml2image" ) . then ( ( ) = > {
2023-12-29 15:00:36 +08:00
const width = Math . max ( exportDialog . element . querySelector ( ".export-img" ) . clientWidth / 3 , 150 ) ;
watermarkPreviewElement . setAttribute ( "style" , ` width: ${ width } px;height: ${ width } px;display: flex;justify-content: center;align-items: center;color: var(--b3-border-color);font-size: 14px; ` ) ;
2023-12-27 22:53:25 +08:00
watermarkPreviewElement . innerHTML = ` <div style="transform: rotate(-45deg)"> ${ window . siyuan . config . export . imageWatermarkStr } </div> ` ;
2025-03-07 13:45:49 +08:00
window . htmlToImage . toCanvas ( watermarkPreviewElement ) . then ( ( canvas ) = > {
2023-12-27 22:53:25 +08:00
watermarkPreviewElement . innerHTML = "" ;
2023-12-29 15:00:36 +08:00
watermarkPreviewElement . setAttribute ( "style" , ` background-image: url( ${ canvas . toDataURL ( "image/png" ) } );background-repeat: repeat;position: absolute;top: 0;left: 0;width: 100%;height: 100%;border-radius: var(--b3-border-radius-b); ` ) ;
2023-12-27 22:53:25 +08:00
} ) ;
2023-12-27 22:26:51 +08:00
} ) ;
2023-12-27 22:53:25 +08:00
}
2023-12-27 11:54:22 +08:00
}
} else {
watermarkPreviewElement . removeAttribute ( "style" ) ;
}
2023-12-29 15:00:36 +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-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 ) ;
}
2024-09-05 11:54:14 +08:00
previewElement . querySelectorAll ( ".code-block" ) . forEach ( item = > {
item . setAttribute ( "linewrap" , "true" ) ;
} ) ;
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
}
} ) ;
2025-03-07 23:38:52 +08:00
2023-12-27 11:54:22 +08:00
updateWatermark ( ) ;
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
} ;