mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-18 07:30:12 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
3afc7cefc4
10 changed files with 84 additions and 20 deletions
|
|
@ -858,7 +858,7 @@
|
||||||
"Children": [
|
"Children": [
|
||||||
{
|
{
|
||||||
"Type": "NodeText",
|
"Type": "NodeText",
|
||||||
"Data": "Does not support exporting to formats such as PDF, HTML, and Word"
|
"Data": "Does not support exporting to formats such as PDF and Word"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -866,7 +866,7 @@
|
||||||
"Children": [
|
"Children": [
|
||||||
{
|
{
|
||||||
"Type": "NodeText",
|
"Type": "NodeText",
|
||||||
"Data": "不支持导出 PDF、HTML 和 Word 等格式"
|
"Data": "不支持导出 PDF 和 Word 等格式"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -829,7 +829,7 @@
|
||||||
"Children": [
|
"Children": [
|
||||||
{
|
{
|
||||||
"Type": "NodeText",
|
"Type": "NodeText",
|
||||||
"Data": "不支援導出 PDF、HTML 和 Word 等格式"
|
"Data": "不支援匯出 PDF 和 Word 等格式"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -978,7 +978,7 @@
|
||||||
"Children": [
|
"Children": [
|
||||||
{
|
{
|
||||||
"Type": "NodeText",
|
"Type": "NodeText",
|
||||||
"Data": "PDF、HTML、Word などの形式でのエクスポートはサポートしていません"
|
"Data": "PDF や Word などの形式へのエクスポートはサポートされていません"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,8 @@ export const exportMd = (id: string) => {
|
||||||
keepFold: localData.keepFold,
|
keepFold: localData.keepFold,
|
||||||
merge: localData.mergeSubdocs,
|
merge: localData.mergeSubdocs,
|
||||||
}, async response => {
|
}, async response => {
|
||||||
const html = await onExport(response, undefined, {type: "pdf", id});
|
const servePath = window.location.protocol + "//" + window.location.host + "/";
|
||||||
|
const html = await onExport(response, undefined, servePath, {type: "pdf", id});
|
||||||
if (isInAndroid()) {
|
if (isInAndroid()) {
|
||||||
window.JSAndroid.print(html);
|
window.JSAndroid.print(html);
|
||||||
} else if (isInHarmony()) {
|
} else if (isInHarmony()) {
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ export const saveExport = (option: IExportOptions) => {
|
||||||
merge: true,
|
merge: true,
|
||||||
savePath: ""
|
savePath: ""
|
||||||
}, async exportResponse => {
|
}, async exportResponse => {
|
||||||
const html = await onExport(exportResponse, undefined, option);
|
const html = await onExport(exportResponse, undefined, "", option);
|
||||||
fetchPost("/api/export/exportBrowserHTML", {
|
fetchPost("/api/export/exportBrowserHTML", {
|
||||||
folder: exportResponse.data.folder,
|
folder: exportResponse.data.folder,
|
||||||
html: html,
|
html: html,
|
||||||
|
|
@ -684,7 +684,7 @@ const getExportPath = (option: IExportOptions, removeAssets?: boolean, mergeSubd
|
||||||
}
|
}
|
||||||
afterExport(exportResponse.data.path, msgId);
|
afterExport(exportResponse.data.path, msgId);
|
||||||
} else {
|
} else {
|
||||||
onExport(exportResponse, savePath, option, msgId);
|
onExport(exportResponse, savePath, "", option, msgId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -692,7 +692,7 @@ const getExportPath = (option: IExportOptions, removeAssets?: boolean, mergeSubd
|
||||||
};
|
};
|
||||||
/// #endif
|
/// #endif
|
||||||
|
|
||||||
export const onExport = async (data: IWebSocketData, filePath: string, exportOption: IExportOptions, msgId?: string) => {
|
export const onExport = async (data: IWebSocketData, filePath: string, servePath: string, exportOption: IExportOptions, msgId?: string) => {
|
||||||
let themeName = window.siyuan.config.appearance.themeLight;
|
let themeName = window.siyuan.config.appearance.themeLight;
|
||||||
let mode = 0;
|
let mode = 0;
|
||||||
if (["html", "htmlmd"].includes(exportOption.type) && window.siyuan.config.appearance.mode === 1) {
|
if (["html", "htmlmd"].includes(exportOption.type) && window.siyuan.config.appearance.mode === 1) {
|
||||||
|
|
@ -700,8 +700,6 @@ export const onExport = async (data: IWebSocketData, filePath: string, exportOpt
|
||||||
mode = 1;
|
mode = 1;
|
||||||
}
|
}
|
||||||
const isDefault = (window.siyuan.config.appearance.mode === 1 && window.siyuan.config.appearance.themeDark === "midnight") || (window.siyuan.config.appearance.mode === 0 && window.siyuan.config.appearance.themeLight === "daylight");
|
const isDefault = (window.siyuan.config.appearance.mode === 1 && window.siyuan.config.appearance.themeDark === "midnight") || (window.siyuan.config.appearance.mode === 0 && window.siyuan.config.appearance.themeLight === "daylight");
|
||||||
const isLocalExport = typeof filePath !== "undefined";
|
|
||||||
const servePath = isLocalExport ? "" : window.location.protocol + "//" + window.location.host + "/";
|
|
||||||
let themeStyle = "";
|
let themeStyle = "";
|
||||||
if (!isDefault) {
|
if (!isDefault) {
|
||||||
themeStyle = `<link rel="stylesheet" type="text/css" id="themeStyle" href="${servePath}appearance/themes/${themeName}/theme.css?${Constants.SIYUAN_VERSION}"/>`;
|
themeStyle = `<link rel="stylesheet" type="text/css" id="themeStyle" href="${servePath}appearance/themes/${themeName}/theme.css?${Constants.SIYUAN_VERSION}"/>`;
|
||||||
|
|
|
||||||
50
kernel/cache/asset.go
vendored
50
kernel/cache/asset.go
vendored
|
|
@ -28,14 +28,60 @@ import (
|
||||||
"github.com/siyuan-note/siyuan/kernel/util"
|
"github.com/siyuan-note/siyuan/kernel/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type AssetHash struct {
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
assetHashCache = map[string]*AssetHash{}
|
||||||
|
assetHashLock = sync.Mutex{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func RemoveAssetHash(hash string) {
|
||||||
|
assetHashLock.Lock()
|
||||||
|
defer assetHashLock.Unlock()
|
||||||
|
|
||||||
|
delete(assetHashCache, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetAssetHash(hash, path string) {
|
||||||
|
assetHashLock.Lock()
|
||||||
|
defer assetHashLock.Unlock()
|
||||||
|
|
||||||
|
assetHashCache[hash] = &AssetHash{
|
||||||
|
Hash: hash,
|
||||||
|
Path: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAssetHash(hash string) *AssetHash {
|
||||||
|
assetHashLock.Lock()
|
||||||
|
defer assetHashLock.Unlock()
|
||||||
|
|
||||||
|
for _, a := range assetHashCache {
|
||||||
|
if a.Hash == hash {
|
||||||
|
if filelock.IsExist(filepath.Join(util.DataDir, a.Path)) {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(assetHashCache, hash)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Asset struct {
|
type Asset struct {
|
||||||
HName string `json:"hName"`
|
HName string `json:"hName"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Updated int64 `json:"updated"`
|
Updated int64 `json:"updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var assetsCache = map[string]*Asset{}
|
var (
|
||||||
var assetsLock = sync.Mutex{}
|
assetsCache = map[string]*Asset{}
|
||||||
|
assetsLock = sync.Mutex{}
|
||||||
|
)
|
||||||
|
|
||||||
func GetAssets() (ret map[string]*Asset) {
|
func GetAssets() (ret map[string]*Asset) {
|
||||||
assetsLock.Lock()
|
assetsLock.Lock()
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,19 @@ import (
|
||||||
"github.com/siyuan-note/siyuan/kernel/util"
|
"github.com/siyuan-note/siyuan/kernel/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func GetAssetPathByHash(hash string) string {
|
||||||
|
assetHash := cache.GetAssetHash(hash)
|
||||||
|
if nil == assetHash {
|
||||||
|
sqlAsset := sql.QueryAssetByHash(hash)
|
||||||
|
if nil == sqlAsset {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
cache.SetAssetHash(sqlAsset.Hash, sqlAsset.Path)
|
||||||
|
return sqlAsset.Path
|
||||||
|
}
|
||||||
|
return assetHash.Path
|
||||||
|
}
|
||||||
|
|
||||||
func HandleAssetsRemoveEvent(assetAbsPath string) {
|
func HandleAssetsRemoveEvent(assetAbsPath string) {
|
||||||
removeIndexAssetContent(assetAbsPath)
|
removeIndexAssetContent(assetAbsPath)
|
||||||
removeAssetThumbnail(assetAbsPath)
|
removeAssetThumbnail(assetAbsPath)
|
||||||
|
|
@ -648,6 +661,7 @@ func RemoveUnusedAssets() (ret []string) {
|
||||||
|
|
||||||
hash, _ := util.GetEtag(p)
|
hash, _ := util.GetEtag(p)
|
||||||
hashes = append(hashes, hash)
|
hashes = append(hashes, hash)
|
||||||
|
cache.RemoveAssetHash(hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -703,6 +717,7 @@ func RemoveUnusedAsset(p string) (ret string) {
|
||||||
|
|
||||||
hash, _ := util.GetEtag(absPath)
|
hash, _ := util.GetEtag(absPath)
|
||||||
sql.BatchRemoveAssetsQueue([]string{hash})
|
sql.BatchRemoveAssetsQueue([]string{hash})
|
||||||
|
cache.RemoveAssetHash(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = filelock.Remove(absPath); err != nil {
|
if err = filelock.Remove(absPath); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/siyuan-note/filelock"
|
"github.com/siyuan-note/filelock"
|
||||||
"github.com/siyuan-note/logging"
|
"github.com/siyuan-note/logging"
|
||||||
"github.com/siyuan-note/siyuan/kernel/sql"
|
"github.com/siyuan-note/siyuan/kernel/cache"
|
||||||
"github.com/siyuan-note/siyuan/kernel/treenode"
|
"github.com/siyuan-note/siyuan/kernel/treenode"
|
||||||
"github.com/siyuan-note/siyuan/kernel/util"
|
"github.com/siyuan-note/siyuan/kernel/util"
|
||||||
)
|
)
|
||||||
|
|
@ -90,9 +90,9 @@ func InsertLocalAssets(id string, assetAbsPaths []string, isUpload bool) (succMa
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if existAsset := sql.QueryAssetByHash(hash); nil != existAsset {
|
if existAssetPath := GetAssetPathByHash(hash); "" != existAssetPath {
|
||||||
// 已经存在同样数据的资源文件的话不重复保存
|
// 已经存在同样数据的资源文件的话不重复保存
|
||||||
succMap[baseName] = existAsset.Path
|
succMap[baseName] = existAssetPath
|
||||||
} else {
|
} else {
|
||||||
fName = util.AssetName(fName, ast.NewNodeID())
|
fName = util.AssetName(fName, ast.NewNodeID())
|
||||||
writePath := filepath.Join(assetsDirPath, fName)
|
writePath := filepath.Join(assetsDirPath, fName)
|
||||||
|
|
@ -105,7 +105,10 @@ func InsertLocalAssets(id string, assetAbsPaths []string, isUpload bool) (succMa
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
succMap[baseName] = "assets/" + fName
|
|
||||||
|
p := "assets/" + fName
|
||||||
|
succMap[baseName] = p
|
||||||
|
cache.SetAssetHash(hash, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IncSync()
|
IncSync()
|
||||||
|
|
@ -197,9 +200,9 @@ func Upload(c *gin.Context) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if existAsset := sql.QueryAssetByHash(hash); nil != existAsset {
|
if existAssetPath := GetAssetPathByHash(hash); "" != existAssetPath {
|
||||||
// 已经存在同样数据的资源文件的话不重复保存
|
// 已经存在同样数据的资源文件的话不重复保存
|
||||||
succMap[baseName] = existAsset.Path
|
succMap[baseName] = existAssetPath
|
||||||
} else {
|
} else {
|
||||||
if skipIfDuplicated {
|
if skipIfDuplicated {
|
||||||
// 复制 PDF 矩形注解时不再重复插入图片 No longer upload image repeatedly when copying PDF rectangle annotation https://github.com/siyuan-note/siyuan/issues/10666
|
// 复制 PDF 矩形注解时不再重复插入图片 No longer upload image repeatedly when copying PDF rectangle annotation https://github.com/siyuan-note/siyuan/issues/10666
|
||||||
|
|
@ -310,7 +313,9 @@ func Upload(c *gin.Context) {
|
||||||
os.RemoveAll(tmpDir2)
|
os.RemoveAll(tmpDir2)
|
||||||
}
|
}
|
||||||
|
|
||||||
succMap[baseName] = strings.TrimPrefix(path.Join(relAssetsDirPath, fName), "/")
|
p := strings.TrimPrefix(path.Join(relAssetsDirPath, fName), "/")
|
||||||
|
succMap[baseName] = p
|
||||||
|
cache.SetAssetHash(hash, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,6 @@ func BlockCount(fsize int64) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CalSha1(b []byte, r io.Reader) ([]byte, error) {
|
func CalSha1(b []byte, r io.Reader) ([]byte, error) {
|
||||||
|
|
||||||
h := sha1.New()
|
h := sha1.New()
|
||||||
_, err := io.Copy(h, r)
|
_, err := io.Copy(h, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue