Skip to content

feat: map post with post id in file name #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
},
{
"command": "vscode-cnb.post.show-local-file-info",
"title": "博客园关联博文",
"title": "关联博客园博文",
"enablement": "vscode-cnb.isAuthed"
},
{
Expand Down Expand Up @@ -616,7 +616,7 @@
},
"post-show-local-file-info": {
"order": 3,
"description": "博客园关联博文",
"description": "关联博客园博文",
"type": "boolean",
"default": true
},
Expand Down Expand Up @@ -677,7 +677,7 @@
},
"post-show-local-file-info": {
"order": 3,
"description": "博客园关联博文",
"description": "关联博客园博文",
"type": "boolean"
},
"post-open-in-blog-admin": {
Expand Down
7 changes: 4 additions & 3 deletions src/cmd/post-list/open-post-in-vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import { fsUtil } from '@/infra/fs/fsUtil'

export function buildLocalPostFileUri(post: Post, appendToFileName = ''): Uri {
const workspaceUri = WorkspaceCfg.getWorkspaceUri()
const ext = `.${post.isMarkdown ? 'md' : 'html'}`
const postTitle = sanitizeFileName(post.title)
return Uri.joinPath(workspaceUri, `${postTitle}${appendToFileName}.${post.id}${ext}`)
const ext = `${post.isMarkdown ? 'md' : 'html'}`
let postTitle = sanitizeFileName(post.title)
if (/\.\d+$/.test(postTitle)) postTitle += '_'
return Uri.joinPath(workspaceUri, `${postTitle}${appendToFileName}.${post.id}.${ext}`)
}

export async function openPostInVscode(postId: number, forceUpdateLocalPostFile = false): Promise<Uri | false> {
Expand Down
34 changes: 30 additions & 4 deletions src/cmd/post-list/post-pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { revealPostListItem } from '@/service/post/post-list-view'
import { PostTreeItem } from '@/tree-view/model/post-tree-item'
import { MarkdownCfg } from '@/ctx/cfg/markdown'
import { fsUtil } from '@/infra/fs/fsUtil'
import { searchPostByTitle } from '@/service/post/search-post-by-title'

export async function postPull(input: Post | PostTreeItem | Uri | undefined | null, showConfirm = true, mute = false) {
const ctxList: CmdCtx[] = []
Expand All @@ -30,7 +31,7 @@ export async function postPull(input: Post | PostTreeItem | Uri | undefined | nu
}
} else {
const uri = parseUriInput(input)
if (uri !== undefined) handleUriInput(uri, ctxList)
if (uri != null) await handleUriInput(uri, ctxList)
}

const fileName = resolveFileNames(ctxList)
Expand Down Expand Up @@ -77,9 +78,34 @@ function parseUriInput(input: InputType): Uri | undefined {
if (doc !== undefined && !doc.isUntitled) return doc.uri
}

function handleUriInput(fileUri: Uri, contexts: CmdCtx[]) {
const postId = PostFileMapManager.getPostId(fileUri.path)
if (postId === undefined) return Alert.fileNotLinkedToPost(fileUri)
async function handleUriInput(fileUri: Uri, contexts: CmdCtx[]) {
let postId = PostFileMapManager.getPostId(fileUri.path)
if (postId == null) {
const mapPost = '关联已有博文并拉取'
const selected = await Alert.info(
'本地文件尚未关联到博客园博文',
{
modal: true,
detail: `您可以将当前本地文件关联到已有博客园博文`,
},
mapPost
)

if (selected === mapPost) {
const fsPath = fileUri.fsPath
const filenName = path.basename(fsPath, path.extname(fsPath))
postId = PostFileMapManager.extractPostId(filenName)
if (postId == null) {
const selectedPost = await searchPostByTitle(filenName, '搜索要关联的博文')
if (selectedPost == null) return Alert.info('未选择要关联的博文')
postId = selectedPost.id
}
}

if (postId != null) await PostFileMapManager.updateOrCreate(postId, fileUri.path)
}

if (postId == null) return Alert.fileNotLinkedToPost(fileUri)

contexts.push({ postId, fileUri })
}
Expand Down
70 changes: 35 additions & 35 deletions src/cmd/post-list/upload-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,17 @@ import { Workspace } from '@/cmd/workspace'
import { fsUtil } from '@/infra/fs/fsUtil'

async function parseFileUri(fileUri?: Uri) {
if (fileUri !== undefined && fileUri.scheme !== 'file') return undefined
if (fileUri !== undefined && fileUri.scheme !== 'file') return
if (fileUri !== undefined) return fileUri

const { activeTextEditor } = window
if (activeTextEditor === undefined) return undefined
if (activeTextEditor == null) return

const { document } = activeTextEditor
if (document.languageId === 'markdown' && !document.isUntitled) {
await document.save()
return document.uri
}

return undefined
}

export async function saveLocalPost(localPost: LocalPost) {
Expand Down Expand Up @@ -202,43 +200,45 @@ export async function uploadPost(input?: Post | PostTreeItem | PostEditDto, conf

export async function uploadPostFile(fileUri?: Uri, confirm = true) {
const parsedFileUri = await parseFileUri(fileUri)
if (parsedFileUri === undefined) return

const { fsPath: filePath } = parsedFileUri
const postId = PostFileMapManager.getPostId(parsedFileUri.path)

if (postId !== undefined && postId >= 0) {
const dto = await PostService.getPostEditDto(postId)
if (dto !== undefined) await uploadPost(dto, confirm)
return
}
if (parsedFileUri == null) return

const fileContent = Buffer.from(await workspace.fs.readFile(parsedFileUri)).toString()
if (isEmptyBody(fileContent)) return

const selected = await Alert.info(
'本地文件尚未关联到博客园博文',
{
modal: true,
detail: `您可以选择新建一篇博文或将本地文件关联到一篇博客园博文(您可以根据标题搜索您在博客园博文)`,
},
'新建博文',
'关联已有博文'
)
if (selected === '关联已有博文') {
const selectedPost = await searchPostByTitle(
path.basename(filePath, path.extname(filePath)),
'搜索要关联的博文'
const { fsPath: fsPath } = parsedFileUri
let postId = PostFileMapManager.getPostId(parsedFileUri.path)

if (postId == null) {
const createPost = '新建博文'
const mapPost = '关联已有博文并上传'
const selected = await Alert.info(
'本地文件尚未关联到博客园博文',
{
modal: true,
detail: `您可以选择新建一篇博文或将当前本地文件关联到已有博客园博文`,
},
createPost,
mapPost
)
if (selectedPost === undefined) return

await PostFileMapManager.updateOrCreate(selectedPost.id, parsedFileUri.path)
const postEditDto = await PostService.getPostEditDto(selectedPost.id)
if (postEditDto === undefined) return
if (fileContent === '') await workspace.fs.writeFile(parsedFileUri, Buffer.from(postEditDto.post.postBody))
if (selected === mapPost) {
const filenName = path.basename(fsPath, path.extname(fsPath))
postId = PostFileMapManager.extractPostId(filenName)
if (postId == null) {
const selectedPost = await searchPostByTitle(filenName, '搜索要关联的博文')

await uploadPost(postEditDto.post, confirm)
} else if (selected === '新建博文') {
await saveLocalPost(new LocalPost(filePath))
if (selectedPost == null) return Alert.info('未选择要关联的博文')
postId = selectedPost.id
}
if (postId != null) await PostFileMapManager.updateOrCreate(postId, parsedFileUri.path)
} else if (selected === createPost) {
await saveLocalPost(new LocalPost(fsPath))
}
}

if (postId != null) {
const dto = await PostService.getPostEditDto(postId)
if (dto == null) return Alert.err(`对应的博文不存在(Id: ${postId})`)
await uploadPost(dto, confirm)
}
}
33 changes: 23 additions & 10 deletions src/cmd/show-local-file-to-post-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import format from 'date-fns/format'
* @param {(Uri | number)} input
* @returns {*} {Promise<void>}
*/
export async function showLocalFileToPostInfo(input: Uri | number): Promise<void> {
export async function showLocalFileToPostInfo(input: Uri | number): Promise<number | undefined> {
let filePath: string | undefined
let postId: number | undefined
if (input instanceof Uri && input.scheme === 'file') {
postId = PostFileMapManager.getPostId(input.path)
filePath = input.fsPath
if (postId === undefined) {
if (postId == null) {
const options = ['现在去关联']
const selected = await Alert.info(
'本地文件尚未关联到博文',
Expand All @@ -31,14 +31,27 @@ export async function showLocalFileToPostInfo(input: Uri | number): Promise<void
...options
)
if (selected === options[0]) {
const selectedPost = await searchPostByTitle(
path.basename(filePath, path.extname(filePath)),
'搜索要关联的博文'
)
if (selectedPost !== undefined) {
await PostFileMapManager.updateOrCreate(selectedPost.id, input.path)
void Alert.info(`本地文件已与博文(${selectedPost.title}, Id: ${selectedPost.id})建立关联`)
const filenName = path.basename(filePath, path.extname(filePath))
postId = PostFileMapManager.extractPostId(filenName)
if (postId == null) {
const selectedPost = await searchPostByTitle(filenName, '搜索要关联的博文')

if (selectedPost == null) {
void Alert.info('未选择要关联的博文')
return
}
postId = selectedPost.id
}

const dto = await PostService.getPostEditDto(postId)
if (dto == null) {
void Alert.err(`对应的博文不存在(Id: ${postId})`)
return
}

await PostFileMapManager.updateOrCreate(postId, input.path)
void Alert.info(`本地文件已与博文(Id: ${postId})建立关联`)
return postId
}
return
}
Expand Down Expand Up @@ -74,6 +87,6 @@ export async function showLocalFileToPostInfo(input: Uri | number): Promise<void
await viewPostOnline(post)
} else if (selected === options[1]) {
await PostFileMapManager.updateOrCreate(postId, '')
void Alert.info(`博文 ${post.title} 已与 ${filePath} 取消关联`)
void Alert.info(`本地文件已与博文(Id: ${postId})取消关联`)
}
}
14 changes: 9 additions & 5 deletions src/service/post/post-file-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { LocalState } from '@/ctx/local-state'
import { Uri } from 'vscode'

const validatePostFileMap = (map: PostFileMap) => map[0] >= 0 && map[1] !== ''

export type PostFileMap = [postId: number, filePath: string]

const storageKey = 'postFileMaps'

function getMaps(): PostFileMap[] {
Expand Down Expand Up @@ -36,7 +34,7 @@ export namespace PostFileMapManager {
}

export async function updateOrCreate(postId: number, filePath: string, { emitEvent = true } = {}) {
const validFileExt = ['.md', '.html']
const validFileExt = ['.md', '.mkd', '.htm', '.html']
if (filePath !== '' && !validFileExt.some(x => filePath.endsWith(x)))
throw Error('Invalid filepath, file must have type markdown or html')

Expand Down Expand Up @@ -72,9 +70,15 @@ export namespace PostFileMapManager {
return path.startsWith('/') ? Uri.parse(path).fsPath : path
}

export function getPostId(filePath: string) {
export function getPostId(filePath: string): number | undefined {
const map = findByFilePath(filePath)
if (map === undefined) return
if (map == null) return
return map[0]
}

export function extractPostId(fileNameWithoutExt: string): number | undefined {
const match = /\.(\d+)$/g.exec(fileNameWithoutExt)
if (match == null) return
return Number(match[1])
}
}