From 8d53990aea7a0096d261f2a9e52024a6be8d7489 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Sat, 8 Oct 2022 17:33:42 +0200 Subject: [PATCH] #430 - support for post_asset_folder folder --- CHANGELOG.md | 1 + src/commands/Folders.ts | 22 +++--- src/constants/StaticFolderPlaceholder.ts | 8 +++ src/constants/index.ts | 1 + src/dashboardWebView/DashboardMessage.ts | 1 + .../components/Contents/Item.tsx | 2 + .../components/Media/FolderCreation.tsx | 44 +++++++++++- .../components/Media/Media.tsx | 59 ++++++++++----- src/dashboardWebView/hooks/useMedia.tsx | 6 +- .../state/atom/AllContentFoldersAtom.ts | 6 ++ .../state/atom/AllStaticFoldersAtom.ts | 6 ++ src/dashboardWebView/state/atom/index.ts | 2 + src/helpers/FrameworkDetector.ts | 71 ++++++++++++++++++- src/helpers/ImageHelper.ts | 19 ++++- src/helpers/MediaHelpers.ts | 64 +++++++++++------ src/listeners/dashboard/MediaListener.ts | 6 ++ src/listeners/dashboard/SettingsListener.ts | 4 +- src/models/MediaPaths.ts | 2 + src/services/PagesParser.ts | 12 +++- 19 files changed, 277 insertions(+), 59 deletions(-) create mode 100644 src/constants/StaticFolderPlaceholder.ts create mode 100644 src/dashboardWebView/state/atom/AllContentFoldersAtom.ts create mode 100644 src/dashboardWebView/state/atom/AllStaticFoldersAtom.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eb5cea4..a362d496 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [#406](https://github.com/estruyf/vscode-front-matter/issues/406): Added support for single data entries in the data dashboard - [#428](https://github.com/estruyf/vscode-front-matter/issues/428): Improved UX for inserting images to your content +- [#430](https://github.com/estruyf/vscode-front-matter/issues/430): Support for HEXO its `post_asset_folder` setting (image location) - [#434](https://github.com/estruyf/vscode-front-matter/issues/434): Webview errors are logged in the extension output ### ⚡️ Optimizations diff --git a/src/commands/Folders.ts b/src/commands/Folders.ts index 74238d0a..84b77fbd 100644 --- a/src/commands/Folders.ts +++ b/src/commands/Folders.ts @@ -1,3 +1,4 @@ +import { STATIC_FOLDER_PLACEHOLDER } from './../constants/StaticFolderPlaceholder'; import { Questions } from './../helpers/Questions'; import { SETTING_CONTENT_PAGE_FOLDERS, SETTING_CONTENT_STATIC_FOLDER, SETTING_CONTENT_SUPPORTED_FILETYPES, TelemetryEvent } from './../constants'; import { commands, Uri, workspace, window } from "vscode"; @@ -43,6 +44,10 @@ export class Folders { startPath += "/"; } + if (startPath.includes(STATIC_FOLDER_PLACEHOLDER.hexo.placeholder)) { + startPath = startPath.replace(STATIC_FOLDER_PLACEHOLDER.hexo.placeholder, STATIC_FOLDER_PLACEHOLDER.hexo.postsFolder); + } + const folderName = await window.showInputBox({ title: `Add media folder`, prompt: `Which name would you like to give to your folder (use "/" to create multi-level folders)?`, @@ -56,22 +61,17 @@ export class Folders { return; } - const folders = folderName.split("/").filter(f => f); - let parentFolders: string[] = []; + await Folders.createFolder(join(parseWinPath(wsFolder?.fsPath || ""), folderName)); + } - for (const folder of folders) { - const folderPath = join(parseWinPath(wsFolder?.fsPath || ""), parentFolders.join("/"), folder); - - parentFolders.push(folder); - - if (!(await existsAsync(folderPath))) { - await mkdirAsync(folderPath); - } + public static async createFolder(folderPath: string) { + if (!(await existsAsync(folderPath))) { + await mkdirAsync(folderPath, { recursive: true }); } if (Dashboard.isOpen) { MediaHelpers.resetMedia(); - MediaListener.sendMediaFiles(0, folderName); + MediaListener.sendMediaFiles(0, folderPath); } Telemetry.send(TelemetryEvent.addMediaFolder); diff --git a/src/constants/StaticFolderPlaceholder.ts b/src/constants/StaticFolderPlaceholder.ts new file mode 100644 index 00000000..259c9ae0 --- /dev/null +++ b/src/constants/StaticFolderPlaceholder.ts @@ -0,0 +1,8 @@ + + +export const STATIC_FOLDER_PLACEHOLDER = { + hexo: { + postsFolder: "source/_posts", + placeholder: "hexo:post_asset_folder", + } +} \ No newline at end of file diff --git a/src/constants/index.ts b/src/constants/index.ts index e268e063..a0cb97be 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -12,6 +12,7 @@ export * from './LocalStore'; export * from './Navigation'; export * from './NotificationType'; export * from './PreviewCommands'; +export * from './StaticFolderPlaceholder'; export * from './TelemetryEvent'; export * from './charCode'; export * from './charMap'; diff --git a/src/dashboardWebView/DashboardMessage.ts b/src/dashboardWebView/DashboardMessage.ts index a09ae77d..de42e892 100644 --- a/src/dashboardWebView/DashboardMessage.ts +++ b/src/dashboardWebView/DashboardMessage.ts @@ -31,6 +31,7 @@ export enum DashboardMessage { updateMediaMetadata = 'updateMediaMetadata', createMediaFolder = 'createMediaFolder', insertFile = 'insertFile', + createHexoAssetFolder = 'createHexoAssetFolder', // Data dashboard getDataEntries = 'getDataEntries', diff --git a/src/dashboardWebView/components/Contents/Item.tsx b/src/dashboardWebView/components/Contents/Item.tsx index 2b7f3d4a..20308edc 100644 --- a/src/dashboardWebView/components/Contents/Item.tsx +++ b/src/dashboardWebView/components/Contents/Item.tsx @@ -65,6 +65,8 @@ export const Item: React.FunctionComponent = ({ fmFilePath, date, ti return []; }, [settings, pageData]); + console.log(pageData[PREVIEW_IMAGE_FIELD]) + if (view === DashboardViewType.Grid) { return (
  • diff --git a/src/dashboardWebView/components/Media/FolderCreation.tsx b/src/dashboardWebView/components/Media/FolderCreation.tsx index d6591620..48b0801c 100644 --- a/src/dashboardWebView/components/Media/FolderCreation.tsx +++ b/src/dashboardWebView/components/Media/FolderCreation.tsx @@ -2,16 +2,34 @@ import * as React from 'react'; import {FolderAddIcon, LightningBoltIcon} from '@heroicons/react/outline'; import { useRecoilValue } from 'recoil'; import { DashboardMessage } from '../../DashboardMessage'; -import { SelectedMediaFolderAtom, SettingsSelector } from '../../state'; +import { AllContentFoldersAtom, AllStaticFoldersAtom, SelectedMediaFolderAtom, SettingsSelector, ViewDataSelector } from '../../state'; import { Messenger } from '@estruyf/vscode/dist/client'; import { ChoiceButton } from '../ChoiceButton'; import { CustomScript, ScriptType } from '../../../models'; +import { STATIC_FOLDER_PLACEHOLDER } from '../../../constants'; +import { useCallback, useMemo } from 'react'; +import { extname } from 'path'; +import { parseWinPath } from '../../../helpers/parseWinPath'; export interface IFolderCreationProps {} export const FolderCreation: React.FunctionComponent = (props: React.PropsWithChildren) => { const selectedFolder = useRecoilValue(SelectedMediaFolderAtom); const settings = useRecoilValue(SettingsSelector); + const allStaticFolders = useRecoilValue(AllStaticFoldersAtom); + const allContentFolders = useRecoilValue(AllContentFoldersAtom); + const viewData = useRecoilValue(ViewDataSelector); + + const hexoAssetFolderPath = useMemo(() => { + const path = viewData?.data?.filePath?.replace(extname(viewData.data.filePath), ''); + return parseWinPath(path); + }, [viewData?.data?.filePath]); + + const onAssetFolderCreation = useCallback(() => { + Messenger.send(DashboardMessage.createHexoAssetFolder, { + hexoAssetFolderPath + }); + }, [hexoAssetFolderPath]); const onFolderCreation = () => { Messenger.send(DashboardMessage.createMediaFolder, { @@ -23,11 +41,34 @@ export const FolderCreation: React.FunctionComponent = (pr Messenger.send(DashboardMessage.runCustomScript, {script, path: selectedFolder}); }; + const isHexoPostAssetsEnabled = useMemo(() => { + if (allStaticFolders && allContentFolders && settings?.staticFolder === STATIC_FOLDER_PLACEHOLDER.hexo.placeholder && hexoAssetFolderPath) { + return ![...allStaticFolders, ...allContentFolders].some(f => f.startsWith(hexoAssetFolderPath)); + } + return false; + }, [settings?.staticFolder, allStaticFolders, allContentFolders, hexoAssetFolderPath]); + const scripts = (settings?.scripts || []).filter(script => script.type === ScriptType.MediaFolder && !script.hidden); + const renderPostAssetsButton = useMemo(() => { + if (isHexoPostAssetsEnabled) { + return ( + + ); + } + return null; + }, [isHexoPostAssetsEnabled]); + if (scripts.length > 0) { return (
    + { renderPostAssetsButton } ({ @@ -43,6 +84,7 @@ export const FolderCreation: React.FunctionComponent = (pr return (
    + { renderPostAssetsButton }
    ) @@ -147,7 +168,7 @@ export const Media: React.FunctionComponent = (props: React.PropsWi { group.folders.map((folder) => ( - + )) } @@ -160,13 +181,13 @@ export const Media: React.FunctionComponent = (props: React.PropsWi publicFolders && publicFolders.length > 0 && (
    { - contentFolders && contentFolders.length > 0 && (

    Public folder{settings?.staticFolder && (: {settings?.staticFolder})}

    ) + contentFolders && contentFolders.length > 0 && (

    Public folder{currentStaticFolder && (: {currentStaticFolder})}

    ) } { publicFolders.map((folder) => ( - + )) } diff --git a/src/dashboardWebView/hooks/useMedia.tsx b/src/dashboardWebView/hooks/useMedia.tsx index 44c4ddeb..b0b359fd 100644 --- a/src/dashboardWebView/hooks/useMedia.tsx +++ b/src/dashboardWebView/hooks/useMedia.tsx @@ -4,7 +4,7 @@ import { useState, useEffect, useCallback } from 'react'; import { useRecoilState, useRecoilValue } from 'recoil'; import { MediaInfo, MediaPaths } from '../../models'; import { DashboardCommand } from '../DashboardCommand'; -import { LoadingAtom, MediaFoldersAtom, MediaTotalAtom, PageAtom, SearchAtom, SelectedMediaFolderAtom, SettingsAtom } from '../state'; +import { AllContentFoldersAtom, AllStaticFoldersAtom, LoadingAtom, MediaFoldersAtom, MediaTotalAtom, PageAtom, SearchAtom, SelectedMediaFolderAtom, SettingsAtom } from '../state'; import Fuse from 'fuse.js'; import usePagination from './usePagination'; @@ -26,6 +26,8 @@ export default function useMedia() { const [ , setSelectedFolder ] = useRecoilState(SelectedMediaFolderAtom); const [ , setTotal ] = useRecoilState(MediaTotalAtom); const [ , setFolders ] = useRecoilState(MediaFoldersAtom); + const [ , setAllContentFolders ] = useRecoilState(AllContentFoldersAtom); + const [ , setAllStaticFolders ] = useRecoilState(AllStaticFoldersAtom); const [ , setLoading ] = useRecoilState(LoadingAtom); const search = useRecoilValue(SearchAtom); const settings = useRecoilValue(SettingsAtom); @@ -44,6 +46,8 @@ export default function useMedia() { setFolders(data.folders); setSelectedFolder(data.selectedFolder); setSearchedMedia(data.media); + setAllContentFolders(data.allContentFolders); + setAllStaticFolders(data.allStaticfolders); } }; diff --git a/src/dashboardWebView/state/atom/AllContentFoldersAtom.ts b/src/dashboardWebView/state/atom/AllContentFoldersAtom.ts new file mode 100644 index 00000000..a3d54611 --- /dev/null +++ b/src/dashboardWebView/state/atom/AllContentFoldersAtom.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const AllContentFoldersAtom = atom({ + key: 'AllContentFoldersAtom', + default: undefined +}); \ No newline at end of file diff --git a/src/dashboardWebView/state/atom/AllStaticFoldersAtom.ts b/src/dashboardWebView/state/atom/AllStaticFoldersAtom.ts new file mode 100644 index 00000000..735c8496 --- /dev/null +++ b/src/dashboardWebView/state/atom/AllStaticFoldersAtom.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const AllStaticFoldersAtom = atom({ + key: 'AllStaticFoldersAtom', + default: undefined +}); \ No newline at end of file diff --git a/src/dashboardWebView/state/atom/index.ts b/src/dashboardWebView/state/atom/index.ts index e6341726..c2275c67 100644 --- a/src/dashboardWebView/state/atom/index.ts +++ b/src/dashboardWebView/state/atom/index.ts @@ -1,3 +1,5 @@ +export * from './AllContentFoldersAtom'; +export * from './AllStaticFoldersAtom'; export * from './CategoryAtom'; export * from './DashboardViewAtom'; export * from './FolderAtom'; diff --git a/src/helpers/FrameworkDetector.ts b/src/helpers/FrameworkDetector.ts index 1c5a54e5..989791ab 100644 --- a/src/helpers/FrameworkDetector.ts +++ b/src/helpers/FrameworkDetector.ts @@ -1,13 +1,16 @@ +import { parseWinPath } from './parseWinPath'; import * as jsoncParser from 'jsonc-parser'; import jsyaml = require("js-yaml"); import { join, resolve } from "path"; import { commands, Uri } from "vscode"; import { Folders } from "../commands/Folders"; -import { COMMAND_NAME } from "../constants"; +import { COMMAND_NAME, SETTING_CONTENT_STATIC_FOLDER, SETTING_FRAMEWORK_ID, STATIC_FOLDER_PLACEHOLDER } from "../constants"; import { FrameworkDetectors } from "../constants/FrameworkDetectors"; import { Framework } from "../models"; import { Logger } from "./Logger"; import { existsAsync, readFileAsync } from '../utils'; +import { Settings } from '.'; +import { parse } from 'path'; export class FrameworkDetector { @@ -84,10 +87,76 @@ export class FrameworkDetector { public static async checkDefaultSettings(framework: Framework) { if (framework.name.toLowerCase() === "jekyll") { await FrameworkDetector.jekyll(); + } else if (framework.name.toLowerCase() === "hexo") { + await FrameworkDetector.hexo(); } } + /** + * Check if there are any changes for the current framework that need to be applied + * @param relAssetPath + * @param filePath + */ + public static relAssetPathUpdate(relAssetPath: string, filePath: string): string { + const staticFolder = Folders.getStaticFolderRelativePath(); + const frameworkId = Settings.get(SETTING_FRAMEWORK_ID); + // Support for HEXO post asset folders + if (staticFolder === STATIC_FOLDER_PLACEHOLDER.hexo.placeholder) { + relAssetPath = relAssetPath.replace(STATIC_FOLDER_PLACEHOLDER.hexo.postsFolder, ""); + + // Filename without the extension + const fileParsing = parse(filePath); + const name = fileParsing.name; + relAssetPath = relAssetPath.replace(name, ""); + relAssetPath = join(relAssetPath); + + // Remove remove the slash at the beginning + relAssetPath = parseWinPath(relAssetPath); + if (relAssetPath.startsWith("/")) { + relAssetPath = relAssetPath.substring(1); + } + } + // Support for HEXO image folder + else if (frameworkId === "hexo") { + relAssetPath = parseWinPath(relAssetPath); + if (relAssetPath.startsWith("/")) { + relAssetPath = relAssetPath.substring(1); + } + } + + return parseWinPath(relAssetPath); + } + + /** + * Define the default settings for Hexo + */ + private static async hexo() { + try { + const wsFolder = Folders.getWorkspaceFolder(); + const hexoConfig = join(wsFolder?.fsPath || "", '_config.yml'); + let assetFoler = "source/images"; + + if (await existsAsync(hexoConfig)) { + const content = await readFileAsync(hexoConfig, "utf8"); + // Convert YAML to JSON + const config = jsyaml.safeLoad(content); + + // Check if post assets are used: https://hexo.io/docs/asset-folders.html#Post-Asset-Folder + if (config.post_asset_folder) { + assetFoler = STATIC_FOLDER_PLACEHOLDER.hexo.placeholder; + } + } + + await Settings.update(SETTING_CONTENT_STATIC_FOLDER, assetFoler, true); + } catch (e) { + Logger.error(`Something failed while processing your Hexo configuration. ${(e as Error).message}`); + } + } + + /** + * Define the default settings for Jekyll + */ private static async jekyll() { try { const wsFolder = Folders.getWorkspaceFolder(); diff --git a/src/helpers/ImageHelper.ts b/src/helpers/ImageHelper.ts index 84d19142..78a8925f 100644 --- a/src/helpers/ImageHelper.ts +++ b/src/helpers/ImageHelper.ts @@ -1,6 +1,7 @@ +import { STATIC_FOLDER_PLACEHOLDER } from './../constants/StaticFolderPlaceholder'; import { ExplorerView } from './../explorerView/ExplorerView'; import { Uri, window } from 'vscode'; -import { dirname, join } from "path"; +import { dirname, extname, join } from "path"; import { Field } from '../models'; import { existsSync } from 'fs'; import { Folders } from '../commands/Folders'; @@ -49,7 +50,21 @@ export class ImageHelper { */ public static relToAbs(filePath: string, value: string) { const wsFolder = Folders.getWorkspaceFolder(); - const staticFolder = Folders.getStaticFolderRelativePath(); + let staticFolder = Folders.getStaticFolderRelativePath(); + + if (staticFolder === STATIC_FOLDER_PLACEHOLDER.hexo.placeholder) { + const editor = window.activeTextEditor; + if (editor) { + const document = editor.document; + const filePath = parseWinPath(document.fileName); + const pathWithoutExtension = filePath.replace(extname(filePath), ''); + const assetFilePath = join(pathWithoutExtension, value); + + if (existsSync(assetFilePath)) { + return Uri.file(assetFilePath); + } + } + } const staticPath = join(parseWinPath(wsFolder?.fsPath || ""), staticFolder || "", value); const contentFolderPath = filePath ? join(dirname(filePath), value) : null; diff --git a/src/helpers/MediaHelpers.ts b/src/helpers/MediaHelpers.ts index 68d77bc6..3643db30 100644 --- a/src/helpers/MediaHelpers.ts +++ b/src/helpers/MediaHelpers.ts @@ -1,4 +1,5 @@ -import { decodeBase64, Extension, MediaLibrary, Notifications, parseWinPath, Settings, Sorting } from "."; +import { STATIC_FOLDER_PLACEHOLDER } from './../constants/StaticFolderPlaceholder'; +import { decodeBase64, Extension, FrameworkDetector, MediaLibrary, Notifications, parseWinPath, Settings, Sorting } from "."; import { Dashboard } from "../commands/Dashboard"; import { Folders } from "../commands/Folders"; import { DEFAULT_CONTENT_TYPE, ExtensionState, HOME_PAGE_NAVIGATION_ID, SETTING_MEDIA_SUPPORTED_MIMETYPES } from "../constants"; @@ -78,11 +79,17 @@ export class MediaHelpers { allMedia = [...media]; } else { - if (staticFolder) { + if (staticFolder && staticFolder !== STATIC_FOLDER_PLACEHOLDER.hexo.placeholder) { const folderSearch = join(staticFolder || "", '/*'); const files = await workspace.findFiles(folderSearch); const media = await MediaHelpers.updateMediaData(MediaHelpers.filterMedia(files)); + allMedia = [...media]; + } else if (staticFolder && staticFolder === STATIC_FOLDER_PLACEHOLDER.hexo.placeholder) { + const folderSearch = join(STATIC_FOLDER_PLACEHOLDER.hexo.postsFolder, '/*'); + const files = await workspace.findFiles(folderSearch); + const media = await MediaHelpers.updateMediaData(MediaHelpers.filterMedia(files)); + allMedia = [...media]; } @@ -150,31 +157,40 @@ export class MediaHelpers { let allContentFolders: string[] = []; let allFolders: string[] = []; + let foldersFromSelection: string[] = []; + if (selectedFolder) { if (await existsAsync(selectedFolder)) { - allFolders = (await readdirAsync(selectedFolder, { withFileTypes: true })).filter(dir => dir.isDirectory()).map(dir => parseWinPath(join(selectedFolder, dir.name))); + foldersFromSelection = (await readdirAsync(selectedFolder, { withFileTypes: true })).filter(dir => dir.isDirectory()).map(dir => parseWinPath(join(selectedFolder, dir.name))); } - } else { - if (pageBundleContentTypes.length > 0) { - for (const contentFolder of contentFolders) { - const contentPath = contentFolder.path; - if (contentPath && await existsAsync(contentPath)) { - const subFolders = (await readdirAsync(contentPath, { withFileTypes: true })).filter(dir => dir.isDirectory()).map(dir => parseWinPath(join(contentPath, dir.name))); - allContentFolders = [...allContentFolders, ...subFolders]; - } + } + + // Retrieve all the content folders + if (pageBundleContentTypes.length > 0) { + for (const contentFolder of contentFolders) { + const contentPath = contentFolder.path; + if (contentPath && await existsAsync(contentPath)) { + const subFolders = (await readdirAsync(contentPath, { withFileTypes: true })).filter(dir => dir.isDirectory()).map(dir => parseWinPath(join(contentPath, dir.name))); + allContentFolders = [...allContentFolders, ...subFolders]; } } - - const staticPath = join(parseWinPath(wsFolder?.fsPath || ""), staticFolder || ""); - if (staticPath && await existsAsync(staticPath)) { - allFolders = (await readdirAsync(staticPath, { withFileTypes: true })).filter(dir => dir.isDirectory()).map(dir => parseWinPath(join(staticPath, dir.name))); - } + } + + // Retrieve all the static folders + let staticPath = join(parseWinPath(wsFolder?.fsPath || ""), staticFolder || ""); + if (staticFolder === STATIC_FOLDER_PLACEHOLDER.hexo.placeholder) { + staticPath = join(parseWinPath(wsFolder?.fsPath || ""), STATIC_FOLDER_PLACEHOLDER.hexo.postsFolder); + } + + if (staticPath && await existsAsync(staticPath)) { + allFolders = (await readdirAsync(staticPath, { withFileTypes: true })).filter(dir => dir.isDirectory()).map(dir => parseWinPath(join(staticPath, dir.name))); } // Store the last opened folder await Extension.getInstance().setState(ExtensionState.SelectedFolder, requestedFolder === HOME_PAGE_NAVIGATION_ID ? HOME_PAGE_NAVIGATION_ID : selectedFolder, "workspace"); - let sortedFolders = [...allContentFolders, ...allFolders]; + let sortedFolders = selectedFolder ? foldersFromSelection : [...allContentFolders, ...allFolders]; + sortedFolders = sortedFolders.sort((a, b) => { if (a.toLowerCase() < b.toLowerCase()) { return -1; @@ -193,7 +209,9 @@ export class MediaHelpers { media: files, total: total, folders: sortedFolders, - selectedFolder + selectedFolder, + allContentFolders, + allStaticfolders: allFolders, } as MediaPaths } @@ -276,6 +294,10 @@ export class MediaHelpers { Dashboard.resetViewData(); const editor = window.activeTextEditor; + if (!editor) { + return; + } + const wsFolder = Folders.getWorkspaceFolder(); const filePath = data.file; let relPath = data.relPath; @@ -304,7 +326,7 @@ export class MediaHelpers { // Snippets are already parsed, so update the URL of the image if (data.snippet) { - data.snippet = data.snippet.replace(data.relPath, relPath); + data.snippet = data.snippet.replace(data.relPath, FrameworkDetector.relAssetPathUpdate(relPath, editor.document.fileName)); } } } @@ -325,7 +347,7 @@ export class MediaHelpers { const caption = isFile ? `${data.title || ""}` : `${data.alt || data.caption || ""}`; - const snippet = data.snippet || `${isFile ? "" : "!"}[${caption}](${relPath.replace(/ /g, "%20")})`; + const snippet = data.snippet || `${isFile ? "" : "!"}[${caption}](${FrameworkDetector.relAssetPathUpdate(relPath, editor.document.fileName).replace(/ /g, "%20")})`; if (selection !== undefined) { builder.replace(selection, snippet); } else { @@ -339,7 +361,7 @@ export class MediaHelpers { DataListener.updateMetadata({ field: data.fieldName, - value: relPath, + value: FrameworkDetector.relAssetPathUpdate(relPath, editor.document.fileName), parents: data.parents, blockData: data.blockData }); diff --git a/src/listeners/dashboard/MediaListener.ts b/src/listeners/dashboard/MediaListener.ts index 6be6ac55..6c01f8aa 100644 --- a/src/listeners/dashboard/MediaListener.ts +++ b/src/listeners/dashboard/MediaListener.ts @@ -7,6 +7,7 @@ import { SortingOption } from '../../dashboardWebView/models'; import { commands, env, Uri } from 'vscode'; import { COMMAND_NAME, TelemetryEvent } from '../../constants'; import * as os from 'os'; +import { Folders } from '../../commands'; export class MediaListener extends BaseListener { @@ -51,6 +52,11 @@ export class MediaListener extends BaseListener { case DashboardMessage.createMediaFolder: await commands.executeCommand(COMMAND_NAME.createFolder, msg?.data); break; + case DashboardMessage.createHexoAssetFolder: + if (msg?.data.hexoAssetFolderPath) { + Folders.createFolder(msg?.data.hexoAssetFolderPath); + } + break; } } diff --git a/src/listeners/dashboard/SettingsListener.ts b/src/listeners/dashboard/SettingsListener.ts index d8c7402b..6b457dee 100644 --- a/src/listeners/dashboard/SettingsListener.ts +++ b/src/listeners/dashboard/SettingsListener.ts @@ -66,7 +66,9 @@ export class SettingsListener extends BaseListener { const allFrameworks = FrameworkDetector.getAll(); const framework = allFrameworks.find((f: Framework) => f.name === frameworkId); if (framework) { - await Settings.update(SETTING_CONTENT_STATIC_FOLDER, framework.static, true); + if (framework.static) { + await Settings.update(SETTING_CONTENT_STATIC_FOLDER, framework.static, true); + } await FrameworkDetector.checkDefaultSettings(framework); } else { diff --git a/src/models/MediaPaths.ts b/src/models/MediaPaths.ts index 03104007..cc4b28ed 100644 --- a/src/models/MediaPaths.ts +++ b/src/models/MediaPaths.ts @@ -4,6 +4,8 @@ export interface MediaPaths { media: MediaInfo[]; total: number; folders: string[]; + allContentFolders: string[]; + allStaticfolders: string[]; selectedFolder: string; } diff --git a/src/services/PagesParser.ts b/src/services/PagesParser.ts index df4e9dfa..2f7200b9 100644 --- a/src/services/PagesParser.ts +++ b/src/services/PagesParser.ts @@ -1,5 +1,6 @@ +import { STATIC_FOLDER_PLACEHOLDER } from './../constants/StaticFolderPlaceholder'; import { parseWinPath } from './../helpers/parseWinPath'; -import { dirname, join } from "path"; +import { dirname, extname, join } from "path"; import { StatusBarAlignment, Uri, window } from "vscode"; import { Dashboard } from "../commands/Dashboard"; import { Folders } from "../commands/Folders"; @@ -236,7 +237,14 @@ export class PagesParser { // Revalidate as the array could have been empty if (fieldValue) { - const staticPath = join(wsFolder.fsPath, staticFolder || "", fieldValue); + let staticPath = join(wsFolder.fsPath, staticFolder || "", fieldValue); + + if (staticFolder === STATIC_FOLDER_PLACEHOLDER.hexo.placeholder) { + const crntFilePath = parseWinPath(filePath) + const pathWithoutExtension = crntFilePath.replace(extname(crntFilePath), ''); + staticPath = join(pathWithoutExtension, fieldValue); + } + const contentFolderPath = join(dirname(filePath), fieldValue); let previewUri = null;