diff --git a/package.json b/package.json index 064bb2c..0424321 100644 --- a/package.json +++ b/package.json @@ -192,6 +192,19 @@ "default": 50, "minimum": 5, "markdownDescription": "プレビューパネルに表示されるタブタイトルを指定した文字数で切り詰めます。" + }, + "zenn-preview.sortArticle": { + "type": "string", + "default": null, + "enum": [ + null, + "title" + ], + "enumDescriptions": [ + "ファイルパスの昇順で表示", + "タイトルの昇順で表示" + ], + "markdownDescription": "記事の並び順を設定します。" } } } @@ -257,4 +270,4 @@ "zenn-markdown-html": "^0.1.155", "zenn-model": "^0.1.155" } -} +} \ No newline at end of file diff --git a/src/treeview/previewTreeItem.ts b/src/treeview/previewTreeItem.ts index 5fb6440..5964a66 100644 --- a/src/treeview/previewTreeItem.ts +++ b/src/treeview/previewTreeItem.ts @@ -1,9 +1,9 @@ -import naturalCompare from "natural-compare-lite"; import * as vscode from "vscode"; import { AppContext } from "../context/app"; import { ContentError } from "../schemas/error"; import { Contents, ContentsType } from "../types"; +import { EMOJI_REGEX } from "../utils/patterns"; /** TreeItem の `contextValue` に設定できる値 */ export type TreeItemType = ContentsType | "error" | "none"; @@ -64,6 +64,43 @@ export abstract class PreviewTreeItem extends vscode.TreeItem { * TreeItemをソートする */ static sortTreeItems(items: PreviewTreeItem[]): PreviewTreeItem[] { - return items.sort((a, b) => naturalCompare(a.path, b.path)); + // 設定からソート順を取得 + const sortArticle = vscode.workspace + .getConfiguration("zenn-preview") + .get("sortArticle"); + + return items.sort((a, b) => { + // 記事タイトルでソート + if (sortArticle === "title") { + const getCleanLabel = (item: PreviewTreeItem): string => { + const labelProp = item.label; + let labelStr = ""; + if (typeof labelProp === "string") { + labelStr = labelProp; + } else if (labelProp && typeof labelProp.label === "string") { + labelStr = labelProp.label; + } + return labelStr.replace(EMOJI_REGEX, "").trim(); + }; + + const aCleanLabel = getCleanLabel(a); + const bCleanLabel = getCleanLabel(b); + + if (aCleanLabel || bCleanLabel) { + // どちらかに絵文字除去後ラベルがあれば比較 + return aCleanLabel.localeCompare(bCleanLabel, "ja", { + sensitivity: "base", + }); + } + + // 絵文字除去後ラベルが両方空の場合はpathで比較 (元々ラベルがなかった場合など) + return a.path.localeCompare(b.path, "ja", { sensitivity: "base" }); + } + + // ファイルパスでソート + else { + return a.path.localeCompare(b.path, "ja", { sensitivity: "base" }); + } + }); } }