Compare commits

...

80 Commits

Author SHA1 Message Date
Elio Struyf 60c8dd6185 Multiple taxonomy management #731 2024-01-16 14:22:17 +01:00
Elio Struyf 033baea418 Insert taxonomy mappings 2024-01-15 22:23:10 +01:00
Elio Struyf 624afe9029 Content tagging 2024-01-15 14:41:10 +01:00
Elio Struyf e161fe23d5 Updated icons 2024-01-15 13:48:21 +01:00
Elio Struyf 51517c6a43 #730 - Added debounce 2024-01-15 10:12:22 +01:00
Elio Struyf e7de1209c3 Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2024-01-11 14:11:15 +01:00
Elio Struyf 9fcdf75c89 Remove reference 2024-01-11 14:11:10 +01:00
Elio Struyf 430ce8940c Issue: keyword usage not works for Cyrillic keywords/content #721 2024-01-11 14:11:02 +01:00
Elio Struyf 5c8228bd17 Updated changelog 2024-01-09 16:57:07 +01:00
Elio Struyf 577ff2f13a Remove obsolete keys 2024-01-09 16:52:41 +01:00
Elio Struyf f9134f1167 Merge pull request #727 from mayumih387/dev
Added Japanese Translation
2024-01-09 16:51:25 +01:00
Elio Struyf 42b5a4ac9e Remove obsolete translation strings 2024-01-09 16:49:55 +01:00
mayumih387 0657c6307f Added Japanese translation 2024-01-09 16:21:45 +09:00
mayumihara d4bef8a4e5 Merge branch 'estruyf:dev' into dev 2024-01-07 22:48:34 +09:00
mayumih387 c3f51c6764 Added Japanese translation (still working) 2023-12-27 16:03:59 +09:00
Elio Struyf 91f127ef94 #725 - fix menu of pinned items 2023-12-21 14:05:27 +01:00
Elio Struyf 6158971fd8 Hide frontMatter.config.reload from command palette 2023-12-21 09:47:05 +01:00
Elio Struyf 9d2cc7cd9f Make sure settings listeners are intialized 2023-12-20 12:29:22 +01:00
mayumih387 964c943e88 Added Japanese translation (still working) 2023-12-19 20:40:59 +09:00
Elio Struyf 0a6e2fac36 9.5.0 2023-12-15 14:25:33 +01:00
Elio Struyf 2a8c3abac6 Ignore node_modules on startup 2023-12-15 14:25:20 +01:00
Elio Struyf 7e4c5b0469 Merge branch 'main' into dev 2023-12-12 16:24:43 +01:00
Elio Struyf 5fcd8d6fe7 Enhancement: In data, provide extra space between objects #719 2023-12-12 09:30:07 +01:00
Elio Struyf 0f07be3e3b Issue: DataFileHelper::process: Function yaml.safeLoad is removed in js-yaml 4. #717 2023-12-08 10:26:42 +01:00
Elio Struyf 5444925cf4 Fix ct - boolean field 2023-12-08 09:33:15 +01:00
Elio Struyf 2b89dda08c Added release notes 2023-12-07 17:41:53 +01:00
Elio Struyf c4feb205fc New localization files 2023-12-07 16:12:21 +01:00
Elio Struyf 78bfa62ed4 #722 - sub-content support 2023-12-07 11:04:18 +01:00
Elio Struyf f350d4af91 #718 - Fix JSON schema 2023-12-01 10:34:26 +01:00
Elio Struyf d15f2554a1 Add ability to always use quotes around string
values in front matter #713
2023-11-23 15:24:40 +01:00
Elio Struyf ab603d9419 Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-11-22 10:44:32 +01:00
Elio Struyf 1acf85c6da Fix taxonomy filtering from taxonomy view to content view #714 2023-11-22 10:44:11 +01:00
Elio Struyf 3383a770b4 Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-11-17 18:44:29 +01:00
Elio Struyf a6d2fffeb9 Update media 2023-11-17 18:43:35 +01:00
Elio Struyf 3d530f7929 #712 - Add fix for media file deletion search context 2023-11-17 18:42:54 +01:00
Elio Struyf f02f994174 Update changelog 2023-11-16 15:27:30 +01:00
Elio Struyf 343dfb2d5d #711 - Fix character mapping 2023-11-16 15:26:32 +01:00
Elio Struyf 9ddaedaaf2 #710 - Remove the fields from FM when the when clause is not met 2023-11-15 15:09:42 +01:00
Elio Struyf 32c6b4c5ea Unused reference 2023-11-15 13:34:15 +01:00
Elio Struyf 90f4d92741 Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-11-15 10:07:12 +01:00
Elio Struyf 580b1dca6d Array check in taxonomy picker 2023-11-15 10:07:05 +01:00
Elio Struyf 520bdf2be3 #709 - Where clause on content creation 2023-11-15 09:44:22 +01:00
Elio Struyf 9724168c3f Updated docs 2023-11-14 19:46:59 +01:00
Elio Struyf ab02e64708 Remove pnpm lock 2023-11-14 19:45:38 +01:00
Elio Struyf f857b0eaa8 #707 - Fix clearempty 2023-11-13 20:29:49 +00:00
Elio Struyf 03aee57221 Fix style of divider 2023-11-13 20:11:34 +00:00
Elio Struyf 07db685666 #706 - Error handling 2023-11-13 17:57:45 +01:00
Elio Struyf 8684f32d98 Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-11-13 16:35:22 +01:00
Elio Struyf 2e536a4de7 Update sponsor check 2023-11-13 16:34:58 +01:00
Elio Struyf 739dffe274 Enhancement: Better content type creation for Astro #704 2023-11-11 13:27:07 -08:00
Elio Struyf 41d2f3f22b Enhancement: Better content type creation for Astro #704 2023-11-11 13:10:41 -08:00
Elio Struyf e285e8d775 Enhancement: Better content type creation for Astro #704 2023-11-11 12:47:41 -08:00
Elio Struyf 9cf4ae46dd Update changelog 2023-11-11 12:36:20 -08:00
Elio Struyf 72c9d1e25f Merge branch 'localization' into dev 2023-11-11 12:35:52 -08:00
Elio Struyf 5f13d318c2 Enhancement: Better content type creation for Astro #704 2023-11-11 12:35:32 -08:00
Elio Struyf ffdf8262d7 Localization updates 2023-11-11 12:33:55 -08:00
Elio Struyf 7fcbdb4ade Merge branch 'dev' into localization 2023-11-11 11:25:15 -08:00
Elio Struyf a8407920bc Enhancement: Better content type creation for Astro #704 2023-11-11 11:19:11 -08:00
Elio Struyf e1f6c90fc0 Enhancement: Better content type creation for Astro #704 2023-11-11 10:38:31 -08:00
Elio Struyf 11354ad8e5 #704 - Fix in zod optional check 2023-11-11 10:12:21 -08:00
Elio Struyf af3e63046c empty commit 2023-11-09 15:39:38 -08:00
Elio Struyf cee4621964 Merge branch 'dev' into localization 2023-11-09 14:16:14 -08:00
Elio Struyf 8db76abf51 #703 - fix pnpm support in astro script 2023-11-09 14:15:43 -08:00
Elio Struyf 3ca50bbe58 Remove reference 2023-11-09 13:52:51 -08:00
Elio Struyf e4cb93274b Localization updates 2023-11-06 14:57:03 -08:00
Elio Struyf 39ad0e034e Localization updates 2023-11-06 13:26:45 -08:00
Elio Struyf cef607ffc8 #701 - Fix content creation 2023-11-06 15:19:46 +01:00
Elio Struyf 258c5fe670 Updates to localization 2023-11-06 15:11:00 +01:00
Elio Struyf 046b24337d Merge branch 'dev' into localization 2023-11-05 08:55:13 +01:00
Elio Struyf 24fb1347df Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-11-02 18:31:53 +01:00
Elio Struyf 3665823803 #700 - added relative path token 2023-11-02 18:31:40 +01:00
Elio Struyf a020b9ad8c Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-11-02 17:23:56 +01:00
Elio Struyf 2c026ff5e5 Started localizing the backend 2023-11-02 17:17:40 +01:00
Elio Struyf 966d0107d9 Enhancement: Allow the contentRelationship field to have a quick search feature #690 2023-11-01 14:44:59 +01:00
Elio Struyf c770a9035f Merge branch 'combobox' into dev 2023-11-01 14:42:39 +01:00
Elio Struyf f4816afa65 Merge pull request #698 from estruyf/issue/697 2023-10-27 09:25:26 +02:00
Elio Struyf 6d43ff11a4 9.3.1 2023-10-27 09:20:45 +02:00
Elio Struyf 1c5e98d40c #697 - Fix missing localization key 2023-10-27 09:20:29 +02:00
Elio Struyf ff1c00167c Merge pull request #682 from estruyf/dev 2023-10-06 17:26:09 +02:00
Elio Struyf 599d43b254 Merge pull request #658 from estruyf/dev 2023-09-11 10:05:26 +02:00
159 changed files with 3589 additions and 9334 deletions
+38 -1
View File
@@ -1,19 +1,47 @@
# Change Log
## [9.4.0] - 2023-xx-xx
## [9.5.0] - 2024-xx-xx
### ✨ New features
- [#731](https://github.com/estruyf/vscode-front-matter/issues/731): Added the ability to map/unmap taxonomy to multiple pages at once
### 🎨 Enhancements
- [#727](https://github.com/estruyf/vscode-front-matter/pull/727): Updated Japanese translations thanks to [mayumihara](https://github.com/mayumih387)
### ⚡️ Optimizations
### 🐞 Fixes
- [#721](https://github.com/estruyf/vscode-front-matter/issues/721): Fix keywords regex to support unicode characters
- [#725](https://github.com/estruyf/vscode-front-matter/issues/725): Fix for opening menu of pinned items
- [#730](https://github.com/estruyf/vscode-front-matter/issues/730): Add debounce to the input fields
## [9.4.0] - 2023-12-12 - [Release notes](https://beta.frontmatter.codes/updates/v9.4.0)
### ✨ New features
- Localization implemented for the whole extension
### 🎨 Enhancements
- [#273](https://github.com/estruyf/vscode-front-matter/issues/273): Allow single value arrays to be set as a string with the `singleValueAsString` field property
- [#686](https://github.com/estruyf/vscode-front-matter/issues/686): Allow script authors to ask questions during script execution
- [#688](https://github.com/estruyf/vscode-front-matter/issues/688): Allow to show the scheduled articles in the content dashboard (filter and group)
- [#690](https://github.com/estruyf/vscode-front-matter/issues/690): Added the ability to filter values in the `contentRelationship` field
- [#700](https://github.com/estruyf/vscode-front-matter/issues/700): Added the `{{pathToken.relPath}}` placeholder for the `previewPath` property
- [#706](https://github.com/estruyf/vscode-front-matter/issues/706): Show the error of scripts failing in the Front Matter output panel
- [#709](https://github.com/estruyf/vscode-front-matter/issues/709): Take "where clause" into account on content creation
- [#710](https://github.com/estruyf/vscode-front-matter/issues/710): Hide child field when parent field its "when clause" is not met, also remove the fields from the content
- [#713](https://github.com/estruyf/vscode-front-matter/issues/713): Add the ability to always use quotes around string values in front matter
- [#722](https://github.com/estruyf/vscode-front-matter/issues/722): Allow to create sub-content which shows a dialog to select the parent folder
### ⚡️ Optimizations
- Dashboard layout grid optimizations
- Added the content-type name to the metadata section in the panel
- New implementation of the combobox for the `contentRelationship` field
### 🐞 Fixes
@@ -22,6 +50,15 @@
- [#694](https://github.com/estruyf/vscode-front-matter/issues/694): Start terminal session from the folder where the `frontmatter.json` file is located
- [#696](https://github.com/estruyf/vscode-front-matter/issues/696): Close the local server terminal on restart
- [#699](https://github.com/estruyf/vscode-front-matter/issues/699): Changing border theme variable for the dashboard header
- [#703](https://github.com/estruyf/vscode-front-matter/issues/703): Fix retrieval of Astro Collections for `pnpm` projects
- [#704](https://github.com/estruyf/vscode-front-matter/issues/704): Fix `zod` schema script for optional fields
- [#707](https://github.com/estruyf/vscode-front-matter/issues/707): Fix `clearEmpty` issue with `draft` and `boolean` fields which are by default set to `true`
- [#711](https://github.com/estruyf/vscode-front-matter/issues/711): Fix in character mapping in the slug field
- [#712](https://github.com/estruyf/vscode-front-matter/issues/712): Keep the search context when deleting media files
- [#714](https://github.com/estruyf/vscode-front-matter/issues/714): Fix for taxonomy filtering from taxonomy view to content view
- [#717](https://github.com/estruyf/vscode-front-matter/issues/717): Fix in loading yaml data files
- [#718](https://github.com/estruyf/vscode-front-matter/issues/718): Fix JSON schema for the `frontMatter.panel.actions.disabled` setting
- [#719](https://github.com/estruyf/vscode-front-matter/issues/719): Fix styling on data view with objects views
## [9.3.1] - 2023-10-27
+2 -2
View File
@@ -25,9 +25,9 @@ Eager to start contributing? Great 🤩, you can contribute to the following pro
- Start by forking this project;
- Clone your fork to your local machine;
- Run `pnpm i`;
- Run `npm i`;
- Open the project in VS Code;
- To start developing, run `pnpm dev:ext` and press `f5` to start the debugging session.
- To start developing, run `npm run dev:ext` and press `f5` to start the debugging session.
### Tips
+1
View File
@@ -0,0 +1 @@
{}
+383 -36
View File
@@ -20,38 +20,83 @@
"common.slug": "スラッグ",
"common.support": "サポート",
"common.remove.value": "{0}を削除",
"common.filter.value": "{0}で絞り込み",
"common.error.message": "申し訳ありません。エラーが発生しました。",
"common.openOnWebsite": "ウェブサイトで開く",
"common.settings": "設定",
"common.refreshSettings": "設定の再読み込み",
"common.pin": "ピン留めする",
"common.unpin": "ピン留めを外す",
"common.noResults": "結果なし",
"common.error": "申し訳ありません。エラーが発生しました。",
"common.yes": "はい",
"common.no": "いいえ",
"common.openSettings": "設定を開く",
"notifications.outputChannel.link": "出力ウィンドウ",
"notifications.outputChannel.description": "詳細は{0}を確認してください。",
"settings.view.common": "一般",
"settings.view.contentFolders": "記事フォルダー",
"settings.view.astro": "Astro",
"settings.openOnStartup": "起動時にダッシュボードを開く",
"settings.contentTypes": "記事タイプ",
"settings.contentFolders": "記事フォルダー",
"settings.diagnostic": "診断",
"settings.diagnostic.description": "診断プログラムを実行して、Front Matter CMS構成全体を確認できます。",
"settings.diagnostic.link": "完全診断を実行する",
"settings.commonSettings.website.title": "ウェブサイトとSSGの設定",
"settings.commonSettings.previewUrl": "プレビュー用URL",
"settings.commonSettings.websiteUrl": "ウェブサイトのURL",
"settings.commonSettings.startCommand": "SSG/フレームワーク起動コマンド",
"developer.title": "開発モード",
"developer.reload.title": "ダッシュボードを再読み込み",
"developer.reload.label": "再読み込み",
"developer.devTools.title": "開発ツールを開く",
"developer.devTools.label": "開発ツール",
"field.required": "必須フィールド",
"field.unknown": "不明なフィールド",
"dashboard.chatbot.answer.answer": "回答",
"dashboard.chatbot.answer.resources": "参考",
"dashboard.chatbot.answer.warning": "回答が正しくない場合もあります。内容がおかしいと思われる場合には、公式ドキュメントを確認してください。",
"dashboard.chatbot.chatbot.loading": "アシスタントを起動中",
"dashboard.chatbot.chatbot.ready": "準備ができました。何について知りたいですか?",
"dashboard.chatbot.chatbox.placeholder": "Front Matterの設定方法は?",
"dashboard.chatbot.header.heading": "Front Matter AIに質問する",
"dashboard.chatbot.header.description": "このAIはmendable.aiをベースに公式ドキュメントがチューニングされており、Front Matter関連のクエリを理解してあなたをアシストします。何でも聞いてください!",
"dashboard.common.choiceButton.open": "オプションを開く",
"dashboard.contents.contentActions.actionMenuButton.title": "メニュー",
"dashboard.contents.contentActions.menuItem.view": "開く",
"dashboard.contents.contentActions.alert.title": "削除: {0}",
"dashboard.contents.contentActions.alert.description": "本当に\"{0}\"を削除しますか?",
"dashboard.contents.item.invalidTitle": "<無効なタイトル>",
"dashboard.contents.item.invalidDescription": "<無効なディスクリプション>",
"dashboard.contents.list.title": "タイトル",
"dashboard.contents.list.date": "日付",
"dashboard.contents.list.status": "ステータス",
"dashboard.contents.overview.noMarkdown": "Markdownファイルはありません",
"dashboard.contents.overview.noFolders": "プロジェクト内の記事用フォルダーを登録して、Front Matterが記事を見つけられるようにしてください。",
"dashboard.contents.overview.pinned": "ピン留めアイテム",
"dashboard.contents.status.draft": "下書き",
"dashboard.contents.status.published": "公開済み",
"dashboard.contents.status.scheduled": "予約済み",
"dashboard.dataView.dataForm.modify": "エントリーを編集",
"dashboard.dataView.dataForm.add": "エントリーを作成",
"dashboard.dataView.dataView.select": "データタイプを選択",
"dashboard.dataView.dataView.title": "\"{0}\"のエントリー",
"dashboard.dataView.dataView.add": "新規エントリーを追加",
@@ -60,34 +105,50 @@
"dashboard.dataView.dataView.getStarted": "データタイプを選択して開始する",
"dashboard.dataView.dataView.noDataFiles": "データファイルが見つかりませんでした",
"dashboard.dataView.dataView.getStarted.link": "データファイルの利用方法について確認する",
"dashboard.dataView.emptyView.heading": "最初にデータタイプを選んでください",
"dashboard.dataView.sortableItem.editButton.title": "\"{0}\"を編集する",
"dashboard.dataView.sortableItem.deleteButton.title": "\"{0}\"を削除する",
"dashboard.dataView.sortableItem.alert.title": "データアイテムを削除",
"dashboard.dataView.sortableItem.alert.description": "本当にこのデータアイテムを削除しますか?",
"dashboard.errorView.description": "ダッシュボードを一旦閉じてからやり直してください。",
"dashboard.header.breadcrumb.home": "ホーム",
"dashboard.header.clearFilters.title": "フィルター・グループ・並べ替えを解除",
"dashboard.header.filter.default": "なし",
"dashboard.header.folders.default": "全ての記事タイプ",
"dashboard.header.folders.menuButton.showing": "表示",
"dashboard.header.grouping.option.none": "なし",
"dashboard.header.grouping.option.year": "公開年",
"dashboard.header.grouping.option.draft": "下書き/公開済み",
"dashboard.header.grouping.menuButton.label": "グループ",
"dashboard.header.navigation.allArticles": "全ての記事",
"dashboard.header.navigation.published": "公開済み",
"dashboard.header.navigation.scheduled": "予約済み",
"dashboard.header.navigation.draft": "下書き",
"dashboard.header.header.createContent": "新しい記事を作成",
"dashboard.header.header.createByContentType": "記事タイプから作成",
"dashboard.header.header.createByTemplate": "テンプレートから作成",
"dashboard.header.pagination.first": "最初",
"dashboard.header.pagination.previous": "前へ",
"dashboard.header.pagination.next": "次へ",
"dashboard.header.pagination.last": "最後",
"dashboard.header.paginationStatus.text": "{0}{1}件目(全{2}件中)を表示中",
"dashboard.header.projectSwitcher.label": "プロジェクト",
"dashboard.header.refreshDashboard.label": "ダッシュボードを再読み込み",
"dashboard.header.sorting.lastModified.asc": "最終更新日(昇順)",
"dashboard.header.sorting.lastModified.desc": "最終更新日(降順)",
"dashboard.header.sorting.filename.asc": "ファイル名(昇順)",
@@ -101,21 +162,27 @@
"dashboard.header.sorting.alt.asc": "代替テキスト(昇順)",
"dashboard.header.sorting.alt.desc": "代替テキスト(降順)",
"dashboard.header.sorting.label": "並べ替え",
"dashboard.header.startup.label": "起動時に表示",
"dashboard.header.tabs.contents": "記事",
"dashboard.header.tabs.media": "メディア",
"dashboard.header.tabs.snippets": "スニペット",
"dashboard.header.tabs.data": "データ",
"dashboard.header.tabs.taxonomies": "タクソノミー",
"dashboard.header.viewSwitch.toGrid": "グリッド表示",
"dashboard.header.viewSwitch.toList": "リスト表示",
"dashboard.layout.sponsor.support.msg": "Front Matterをサポートする",
"dashboard.layout.sponsor.review.label": "評価する",
"dashboard.layout.sponsor.review.msg": "Front Matterを評価する",
"dashboard.media.common.title": "タイトル",
"dashboard.media.common.caption": "キャプション",
"dashboard.media.common.alt": "代替テキスト",
"dashboard.media.common.size": "サイズ",
"dashboard.media.dialog.title": "ファイルの詳細",
"dashboard.media.panel.close": "パネルを閉じる",
"dashboard.media.metadata.panel.title": "メタデータを編集",
@@ -127,8 +194,10 @@
"dashboard.media.metadata.panel.form.information.modifiedDate": "最終更新日",
"dashboard.media.metadata.panel.form.information.dimensions": "ディメンション",
"dashboard.media.metadata.panel.form.information.folder": "フォルダー",
"dashboard.media.folderCreation.hexo.create": "Assetフォルダーを作成",
"dashboard.media.folderCreation.folder.create": "新規フォルダーを作成",
"dashboard.media.item.quickAction.insert.field": "この画像を\"{0}\"フィールドに追加",
"dashboard.media.item.quickAction.insert.markdown": "画像をMarkdown記法で挿入",
"dashboard.media.item.quickAction.copy.path": "ファイルパスをコピー",
@@ -138,6 +207,7 @@
"dashboard.media.item.menuItem.reveal.media": "メディアの場所を表示",
"dashboard.media.item.infoDialog.snippet.description": "このメディアに適用するメディア用スニペットを選択してください。",
"dashboard.media.item.alert.delete.description": "本当にこのファイルを {0} から削除しますか?",
"dashboard.media.media.description": "記事に挿入するメディアファイルを選択してください。",
"dashboard.media.media.dragAndDrop": "デスクトップから画像をドラッグ&ドロップして、アップロード後に選択することもできます。",
"dashboard.media.media.folder.upload": "{0}にアップロードする",
@@ -145,13 +215,17 @@
"dashboard.media.media.placeholder": "メディアファイルはありません。Shiftキーを押しながら、新規ファイルをドラック&ドロップで追加することができます。",
"dashboard.media.media.contentFolder": "記事フォルダー",
"dashboard.media.media.publicFolder": "Publicフォルダー",
"dashboard.media.mediaHeaderTop.searchbox.placeholder": "フォルダー内を検索",
"dashboard.media.mediaSnippetForm.formDialog.title": "メディアを挿入: {0}",
"dashboard.media.mediaSnippetForm.formDialog.description": "メディアファイル\"{0}\"を現在の記事に挿入する",
"dashboard.preview.input.placeholder": "URLを入力",
"dashboard.preview.button.navigate.title": "ナビゲーション",
"dashboard.preview.button.refresh.title": "更新",
"dashboard.preview.button.open.title": "開く",
"dashboard.snippetsView.item.quickAction.editSnippet": "スニペットを編集",
"dashboard.snippetsView.item.quickAction.deleteSnippet": "スニペットを削除",
"dashboard.snippetsView.item.quickAction.viewSnippet": "スニペットファイルの表示",
@@ -161,6 +235,7 @@
"dashboard.snippetsView.item.edit.formDialog.description": "\"{0}\"スニペットの編集",
"dashboard.snippetsView.item.alert.title": "\"{0}\"スニペットを削除",
"dashboard.snippetsView.item.alert.description": "本当に\"{0}\"スニペットを削除しますか?",
"dashboard.snippetsView.newForm.snippetInput.title.placeholder": "スニペットのタイトル",
"dashboard.snippetsView.newForm.snippetInput.description.label": "概要",
"dashboard.snippetsView.newForm.snippetInput.description.placeholder": "スニペットの概要",
@@ -171,12 +246,14 @@
"dashboard.snippetsView.newForm.snippetInput.isMediaSnippet.checkbox.description": "このスニペットをメディアファイル挿入時に利用",
"dashboard.snippetsView.newForm.snippetInput.docsButton.title": "メディア用スニペットのプレースホルダーについて読む",
"dashboard.snippetsView.newForm.snippetInput.docsButton.description": "スニペットに設定可能なプレースホルダーをドキュメントで確認",
"dashboard.snippetsView.snippets.ariaLabel": "スニペット ヘッダー",
"dashboard.snippetsView.snippets.button.create": "新規スニペットを作成",
"dashboard.snippetsView.snippets.select.description": "挿入するスニペットを選択してください。",
"dashboard.snippetsView.snippets.empty.message": "スニペットはありません",
"dashboard.snippetsView.snippets.readMore": "スニペットの使い方を読む",
"dashboard.snippetsView.snippets.formDialog.title": "新規スニペットを作成",
"dashboard.steps.stepsToGetStarted.button.addFolder.title": "Front Matterに記事フォルダーとして登録",
"dashboard.steps.stepsToGetStarted.initializeProject.name": "プロジェクトの初期設定",
"dashboard.steps.stepsToGetStarted.initializeProject.description": "Front Matter CMSに必要な設定ファイルを作成します。クリックして開始してください。",
@@ -184,20 +261,32 @@
"dashboard.steps.stepsToGetStarted.framework.description": "静的サイトジェネレーターまたはフレームワークを選択して、必要なセッティングを追加します。",
"dashboard.steps.stepsToGetStarted.framework.select": "フレームワークを選択",
"dashboard.steps.stepsToGetStarted.framework.select.other": "その他",
"dashboard.steps.stepsToGetStarted.assetsFolder.name": "アセットフォルダーを登録",
"dashboard.steps.stepsToGetStarted.assetsFolder.description": "記事のメディアファイルを保存するためのフォルダーを選択してください。",
"dashboard.steps.stepsToGetStarted.assetsFolder.public.title": "'public'フォルダーを使用する",
"dashboard.steps.stepsToGetStarted.assetsFolder.assets.title": "Astroアセットフォルダー(src/assets)を使用する",
"dashboard.steps.stepsToGetStarted.assetsFolder.other.description": "別のフォルダーを指定する場合は、frontmatter.jsonファイルへ手動で設定可能です。",
"dashboard.steps.stepsToGetStarted.contentFolders.name": "記事ファイルのフォルダーを登録",
"dashboard.steps.stepsToGetStarted.contentFolders.description": "記事ファイルの保存フォルダーを追加してください。フォルダーが設定されると、フォルダー内の記事ファイルがFront Matterでリスト化され、新規記事ファイルを追加できるようになります。",
"dashboard.steps.stepsToGetStarted.contentFolders.description": "記事ファイルの保存フォルダーを追加してください。フォルダーが設定されると、フォルダー内の記事ファイルがFront Matterでリスト化され、新規記事ファイルを追加できるようになります。",
"dashboard.steps.stepsToGetStarted.contentFolders.label": "記事ファイルを含むフォルダー",
"dashboard.steps.stepsToGetStarted.contentFolders.information.description": "フォルダーの登録は、エクスプローラーでフォルダー名を右クリックして「フォルダーを登録」を選択することでも可能です。",
"dashboard.steps.stepsToGetStarted.contentFolders.information.description": "エクスプローラーでフォルダー名を右クリックして「フォルダーを登録」を選択する方法でも、フォルダーの登録が可能です。",
"dashboard.steps.stepsToGetStarted.tags.name": "全てのタグとカテゴリーをインポート(オプション)",
"dashboard.steps.stepsToGetStarted.tags.description": "Front Matterに記事用フォルダーが登録されました。記事から全てのタグとカテゴリーをインポートしますか?",
"dashboard.steps.stepsToGetStarted.showDashboard.name": "ダッシュボードを開く",
"dashboard.steps.stepsToGetStarted.showDashboard.description": "全ての設定が終わると、ダッシュボードが表示できるようになります。",
"dashboard.steps.stepsToGetStarted.template.name": "設定用のテンプレートを使用する",
"dashboard.steps.stepsToGetStarted.template.description": "おすすめの設定のテンプレートを選択して、frontmatter.jsonに反映させます。",
"dashboard.steps.stepsToGetStarted.template.warning": "選択によりプロジェクトの構成にテンプレートが適用され、この設定画面は終了します。",
"dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Astroコンテンツコレクションのコンテンツタイプを作成する",
"dashboard.taxonomyView.button.add.title": "\"{0}\"をタクソノミーに追加",
"dashboard.taxonomyView.button.edit.title": "\"{0}\"を編集",
"dashboard.taxonomyView.button.merge.title": "\"{0}\"をマージ",
"dashboard.taxonomyView.button.move.title": "他のタクソノミーへ移行",
"dashboard.taxonomyView.button.delete.title": "\"{0}\"を削除",
"dashboard.taxonomyView.taxonomyLookup.button.title": "{1}\"{0}\"の記事一覧を表示",
"dashboard.taxonomyView.taxonomyManager.description": "サイト内{0}の新規作成・編集・コマンド",
"dashboard.taxonomyView.taxonomyManager.button.create": "新規{0}を作成",
"dashboard.taxonomyView.taxonomyManager.table.heading.name": "名前",
@@ -205,17 +294,21 @@
"dashboard.taxonomyView.taxonomyManager.table.heading.action": "コマンド",
"dashboard.taxonomyView.taxonomyManager.table.row.empty": "{0}はありません",
"dashboard.taxonomyView.taxonomyManager.table.unmapped.title": "設定ファイルに見つかりません",
"dashboard.taxonomyView.taxonomyView.navigationBar.title": "タクソノミーを選択",
"dashboard.taxonomyView.taxonomyView.button.import": "タクソノミーをインポート",
"dashboard.taxonomyView.taxonomyView.navigationItem.tags": "タグ",
"dashboard.taxonomyView.taxonomyView.navigationItem.categories": "カテゴリー",
"dashboard.unkownView.title": "表示出来る画面がありません",
"dashboard.unkownView.description": "存在しない画面で終了してしまったようです。ダッシュボードを再度開きなおしてください。",
"dashboard.welcomeScreen.title": "Front Matterで静的サイトを管理しよう",
"dashboard.welcomeScreen.thanks": "Front Matterをお使いいただきありがとうございます!",
"dashboard.welcomeScreen.description": "私たちはFront Matterをより使いやすくするため、日々努力しています。ご質問やご提案など、GitHubまでお気軽にお問い合わせください。",
"dashboard.welcomeScreen.link.github.title": "GitHub",
"dashboard.welcomeScreen.link.github.label": "GitHub / ドキュメント",
"dashboard.welcomeScreen.link.github.label": "GitHub",
"dashboard.welcomeScreen.link.documentation.label": "ドキュメント",
"dashboard.welcomeScreen.link.sponsor.title": "スポンサーになる",
"dashboard.welcomeScreen.link.sponsor.label": "スポンサー",
"dashboard.welcomeScreen.link.review.title": "評価する",
@@ -223,41 +316,66 @@
"dashboard.welcomeScreen.actions.heading": "以下の手順に従って、この拡張機能をスタートさせてください。",
"dashboard.welcomeScreen.actions.description": "サイドパネルからもFront Matterを利用できます。サイドパネルでは、各コンテンツに合った具体的なコマンドが実行可能です。",
"dashboard.welcomeScreen.actions.thanks": "Front Matterをお楽しみください!",
"dashboard.media.detailsSlideOver.unmapped.description": "未割り当てのファイルのメタデータを再マップしますか?",
"dashboard.configuration.astro.astroContentTypes.empty": "Astroコンテンツコレクションが見つかりません。",
"dashboard.configuration.astro.astroContentTypes.description": "以下のAstroコンテンツコレクションは、コンテンツタイプを生成するために使用できます。",
"panel.contentType.contentTypeValidator.title": "記事タイプ",
"panel.contentType.contentTypeValidator.hint": "記事タイプのフィールドは設定と異なります。この記事の記事タイプを、作成・更新または設定しますか?",
"panel.contentType.contentTypeValidator.button.create": "新しい記事タイプを作成",
"panel.contentType.contentTypeValidator.button.add": "この記事タイプの設定にないフィールドを追加",
"panel.contentType.contentTypeValidator.button.change": "このファイルの記事タイプを変更",
"panel.dataBlock.dataBlockField.group.selected.edit": "編集: {0}",
"panel.dataBlock.dataBlockField.group.selected.create": "新規{0}を作成",
"panel.dataBlock.dataBlockField.group.select": "グループを選択",
"panel.dataBlock.dataBlockField.add": "{0}を追加",
"panel.dataBlock.dataBlockRecord.edit": "レコードを編集",
"panel.dataBlock.dataBlockRecord.delete": "レコードを削除",
"panel.dataBlock.dataBlockRecords.label": "レコード",
"panel.dataBlock.dataBlockSelector.label": "ブロックタイプ",
"panel.errorBoundary.fieldBoundary.label": "フィールドの表示に失敗しました",
"panel.fields.choiceField.select": "{0}を選択",
"panel.fields.choiceField.clear": "値をクリア",
"panel.fields.contentTypeRelationshipField.loading": "読み込み中...",
"panel.fields.dateTimeField.button.pick": "日付を選択",
"panel.fields.dateTimeField.time": "時刻",
"panel.fields.fieldMessage.required": "{0}は必須フィールドです",
"panel.fields.fileField.delete": "ファイルを削除",
"panel.fields.fileField.add": "{0}を追加",
"panel.fields.imageFallback.label": "画像を読み込めませんでした。",
"panel.fields.listField.edit": "レコードを編集",
"panel.fields.listField.delete": "レコードを削除",
"panel.fields.previewImage.remove": "画像を削除",
"panel.fields.previewImageField.add": "{0}を追加",
"panel.fields.slugField.update": "更新が可能",
"panel.fields.slugField.generate": "スラッグを生成",
"panel.fields.textField.ai.message": "Front Matter AIに{0}を提案してもらう",
"panel.fields.textField.ai.generate": "提案を生成中...",
"panel.fields.textField.loading": "読み込み中",
"panel.fields.textField.limit": "値が上限を超えています。{0}",
"panel.fields.wrapperField.unknown": "不明なフィールド: {0}",
"panel.actions.title": "コマンド",
"panel.articleDetails.title": "詳細",
"panel.articleDetails.type": "項目",
"panel.articleDetails.total": "数",
@@ -266,15 +384,18 @@
"panel.articleDetails.internalLinks": "内部リンク",
"panel.articleDetails.externalLinks": "外部リンク",
"panel.articleDetails.images": "画像",
"panel.baseView.initialize": "プロジェクトの初期設定",
"panel.baseView.actions.title": "コマンド",
"panel.baseView.action.openDashboard": "ダッシュボードを開く",
"panel.baseView.action.openPreview": "プレビューを開く",
"panel.baseView.action.createContent": "新しい記事を作成",
"panel.baseView.empty": "他の操作を見るには、ファイルを開いてください。",
"panel.fileList.label.singular": "ファイル",
"panel.fileList.label.plural": "ファイル",
"panel.folderAndFiles.title": "最近の更新",
"panel.globalSettings.title": "一般設定",
"panel.globalSettings.action.modifiedDate.label": "最終更新日",
"panel.globalSettings.action.modifiedDate.description": "最終更新日を自動で更新",
@@ -284,7 +405,9 @@
"panel.globalSettings.action.preview.placeholder": "例: {0}",
"panel.globalSettings.action.server.label": "ローカルサーバーのコマンド",
"panel.globalSettings.action.server.placeholder": "例: {0}",
"panel.metadata.title": "メタデータ",
"panel.otherActions.title": "他のコマンド",
"panel.otherActions.writingSettings.enabled": "ライティング設定が有効",
"panel.otherActions.writingSettings.disabled": "ライティング設定を有効化",
@@ -295,17 +418,23 @@
"panel.otherActions.documentation": "ドキュメントを開く",
"panel.otherActions.settings": "設定方法の概要",
"panel.otherActions.issue": "問題を報告",
"panel.preview.title": "プレビューを表示",
"panel.publishAction.publish": "公開",
"panel.publishAction.unpublish": "下書きに戻す",
"panel.seoDetails.recommended": "推奨",
"panel.seoKeywordInfo.density": "キーワード出現率 {0} *",
"panel.seoKeywordInfo.validInfo.label": "見出しへの利用",
"panel.seoKeywordInfo.validInfo.content": "本文",
"panel.seoKeywords.title": "キーワード",
"panel.seoKeywords.header.keyword": "キーワード",
"panel.seoKeywords.header.details": "詳細",
"panel.seoKeywords.density": "* キーワード出現率は通常1~1.5%で十分です。",
"panel.seoStatus.title": "推奨項目",
"panel.seoStatus.header.property": "項目",
"panel.seoStatus.header.length": "長さ",
@@ -315,50 +444,268 @@
"panel.seoStatus.seoFieldInfo.article": "記事の長さ",
"panel.seoStatus.collapsible.title": "SEO対策",
"panel.seoStatus.required": "{0}か{1}は必須です。",
"panel.slugAction.title": "スラッグを最適化",
"panel.spinner.loading": "読み込み中...",
"panel.startServerbutton.start": "サーバーを起動",
"panel.startServerbutton.stop": "サーバーを停止",
"panel.tag.add": "\"{0}\"を設定に追加",
"panel.tagPicker.inputPlaceholder.empty": "{0}を選択",
"panel.tagPicker.inputPlaceholder.disabled": "{0}の上限数に達しました",
"panel.tagPicker.ai.suggest": "Front Matter AIに{0}を提案してもらう",
"panel.tagPicker.ai.generating": "提案を生成中...",
"panel.tagPicker.limit": "上限数: {0}",
"panel.tagPicker.unkown": "不明なタグを追加",
"panel.tags.tag.warning": "\"{0}\"は設定に保存されていません。削除すると復元できませんのでご注意ください。",
"panel.viewPanel.mediaInsert": "ダッシュボードのメディア管理画面から、利用したい画像を選択してください。",
"dashboard.steps.stepsToGetStarted.assetsFolder.name": "アセットフォルダーの場所はどこですか?",
"dashboard.steps.stepsToGetStarted.assetsFolder.description": "記事のメディアファイルを保存するためのフォルダーを選択してください。",
"dashboard.steps.stepsToGetStarted.assetsFolder.public.title": "'public'フォルダーを使用する",
"dashboard.steps.stepsToGetStarted.assetsFolder.assets.title": "Astroアセットフォルダー(src/assets)を使用する",
"dashboard.steps.stepsToGetStarted.assetsFolder.other.description": "別のフォルダを設定する場合は、frontmatter.jsonファイルで手動で行うことができます。",
"dashboard.steps.stepsToGetStarted.template.name": "設定テンプレートを使用する",
"dashboard.steps.stepsToGetStarted.template.description": "おすすめの設定でfrontmatter.jsonファイルを事前に埋めるテンプレートを選択します。",
"commands.article.setDate.error": "日付の表示形式の解析中に何らかの問題が発生しました。\"{0}\"の設定を確認してください。",
"commands.article.updateSlug.error": "ファイル名を変更できませんでした。: {0}",
"commands.cache.cleared": "キャッシュがクリアされました。",
"commands.chatbot.title": "何でも聞いてください",
"commands.content.option.contentType.label": "記事タイプから記事を作成",
"commands.content.option.contentType.description": "設定済みの記事タイプを選択して記事を作成",
"commands.content.option.template.label": "テンプレートから記事を作成",
"commands.content.option.template.description": "設定済みのテンプレートを選択して記事を作成",
"commands.content.quickPick.title": "記事の作成",
"commands.content.quickPick.placeholder": "記事の作成方法を選択してください。",
"commands.dashboard.title": "ダッシュボード",
"commands.folders.addMediaFolder.inputBox.title": "メディアフォルダーの追加",
"commands.folders.addMediaFolder.inputBox.prompt": "新規作成するフォルダー名を入力してください。(\"/\"で多階層のフォルダーを作成可能です)",
"commands.folders.addMediaFolder.noFolder.warning": "フォルダー名が入力されていません。",
"commands.folders.create.folderExists.warning": "フォルダーは既に登録済です。",
"commands.folders.create.input.title": "フォルダーを登録する",
"commands.folders.create.input.prompt": "登録するフォルダー名を指定してください。",
"commands.folders.create.input.placeholder": "フォルダー名",
"commands.folders.create.success": "フォルダーが登録されました。",
"commands.folders.getWorkspaceFolder.workspaceFolderPick.placeholder": "Front Matterを利用するメインのワークスペースのフォルダーを選択してください。",
"commands.folders.get.notificationError.title": "\"{0}\"フォルダーが存在しません。このフォルダーを設定から削除してください。",
"commands.folders.get.notificationError.remove.action": "フォルダー設定を削除",
"commands.folders.get.notificationError.create.action": "フォルダーを作成",
"commands.preview.panel.title": "プレビュー: {0}",
"commands.preview.askUserToPickFolder.title": "プレビュー用の記事フォルダーを選択してください。",
"commands.project.initialize.success": "プロジェクトが初期化されました。",
"commands.project.switchProject.title": "どのプロジェクトに切り替えますか?",
"commands.project.createSampleTemplate.info": "テンプレートサンプルを作成しました。",
"commands.settings.create.input.prompt": "設定に追加したい{0}の値を入力してください。",
"commands.settings.create.input.placeholder": "{0}の名前",
"commands.settings.create.warning": "入力された {0} は既に存在しています。",
"commands.settings.create.quickPick.placeholder": "新規{0}をページに追加しますか?",
"commands.settings.export.progress.title": "{0}: タグとカテゴリーをエクスポートしています。",
"commands.settings.export.progress.success": "エクスポートが完了しました。タグ: {0} - カテゴリー: {1}",
"commands.settings.remap.quickpick.title": "再構成",
"commands.settings.remap.quickpick.placeholder": "何を再構成しますか?",
"commands.settings.remap.noTaxonomy.warning": "編集可能な{0}が存在しません。",
"commands.settings.remap.selectTaxonomy.placeholder": "編集したい{0}を選択してください。",
"commands.settings.remap.newOption.input.prompt": "\"{1}\"を再構成します。変更したい{0}値を入力してください。全ての記事から{0}を削除する場合は空欄にしてください。",
"commands.settings.remap.newOption.input.placeholder": "{0}名",
"commands.settings.remap.delete.placeholder": "{1} {0}を削除しますか?",
"commands.statusListener.verifyRequiredFields.diagnostic.emptyField": "フィールド {0} は必須です。値を入力してください。",
"commands.statusListener.verifyRequiredFields.notification.error": "以下の必須のフィールドに値が入力されていません。: {0}",
"commands.template.generate.input.title": "テンプレート名",
"commands.template.generate.input.prompt": "テンプレート名を入力してください。",
"commands.template.generate.input.placeholder": "article",
"commands.template.generate.noTitle.warning": "テンプレート名が入力されていません。",
"commands.template.generate.keepContents.title": "記事本文の反映",
"commands.template.generate.keepContents.placeholder": "記事本文をテンプレートにそのまま残しますか?",
"commands.template.generate.keepContents.noOption.warning": "記事本文を残すかどうかの選択がされませんでした。",
"commands.template.generate.keepContents.success": "{0}フォルダー内にテンプレートが作成されました。",
"commands.template.getTemplates.warning": "テンプレートがありません。",
"commands.template.create.folderPath.warning": "取得されたプロジェクトフォルダーのパスが不正です。",
"commands.template.create.noTemplates.warning": "テンプレートがありません。",
"commands.template.create.selectTemplate.title": "テンプレートの選択",
"commands.template.create.selectTemplate.placeholder": "記事テンプレートを選択してください。",
"commands.template.create.selectTemplate.noTemplate.warning": "テンプレートが選択されていません。",
"commands.template.create.selectTemplate.notFound.warning": "記事テンプレートが見つかりません。",
"commands.template.create.success": "新規記事が有効になりました。",
"commands.wysiwyg.command.unorderedList.label": "順序なしリスト",
"commands.wysiwyg.command.unorderedList.detail": "順序なしリストを追加",
"commands.wysiwyg.command.orderedList.label": "順序付きリスト",
"commands.wysiwyg.command.orderedList.detail": "順序付きリストを追加",
"commands.wysiwyg.command.taskList.label": "タスクリスト",
"commands.wysiwyg.command.taskList.detail": "タスクリストを追加",
"commands.wysiwyg.command.code.label": "コード",
"commands.wysiwyg.command.code.detail": "インラインコードスニペットを追加",
"commands.wysiwyg.command.codeblock.label": "コードブロック",
"commands.wysiwyg.command.codeblock.detail": "コードブロックを追加",
"commands.wysiwyg.command.blockquote.label": "ブロック引用要素",
"commands.wysiwyg.command.blockquote.detail": "ブロック引用要素を追加",
"commands.wysiwyg.command.strikethrough.label": "取り消し線",
"commands.wysiwyg.command.strikethrough.detail": "取り消し線付きテキストを追加",
"commands.wysiwyg.quickPick.title": "WYSIWYG オプション",
"commands.wysiwyg.quickPick.placeholder": "どのマークアップ要素を挿入しますか?",
"commands.wysiwyg.addHyperlink.hyperlinkInput.title": "WYSIWYG ハイパーリンク",
"commands.wysiwyg.addHyperlink.hyperlinkInput.prompt": "URLを入力",
"commands.wysiwyg.addHyperlink.textInput.title": "WYSIWYG テキスト",
"commands.wysiwyg.addHyperlink.textInput.prompt": "ハイパーリンクのテキストを入力",
"commands.wysiwyg.insertText.heading.input.title": "見出し",
"commands.wysiwyg.insertText.heading.input.placeholder": "見出しのレベルを選択",
"helpers.articleHelper.createContent.pageBundle.error": "{0}という名称のページバンドルは、既に {1} に存在しています。",
"helpers.articleHelper.createContent.contentExists.warning": "同タイトルの記事が存在します。別のタイトルを付けてください。",
"helpers.articleHelper.processCustomPlaceholders.placeholder.error": "プレースホルダー{0}の生成中にエラーが発生しました。",
"helpers.articleHelper.parseFile.diagnostic.error": "{0}のfront matterの解析中にエラーが発生しました。",
"helpers.contentType.generate.noFrontMatter.error": "記事タイプの生成に必要なfront matterデータがありません。",
"helpers.contentType.generate.override.quickPick.title": "デフォルトの記事タイプを上書き",
"helpers.contentType.generate.override.quickPick.placeholder": "この記事のフィールド設定を、デフォルトの記事タイプのフィールド設定に上書きしますか?",
"helpers.contentType.generate.contentTypeInput.title": "記事タイプを生成",
"helpers.contentType.generate.contentTypeInput.prompt": "新規作成したい記事タイプ名を入力してください。",
"helpers.contentType.generate.contentTypeInput.validation.enterName": "記事タイプ名を入力してください。",
"helpers.contentType.generate.contentTypeInput.validation.nameExists": "この記事タイプ名は既に存在しています。",
"helpers.contentType.generate.noContentTypeName.warning": "記事タイプが選択されませんでした。",
"helpers.contentType.generate.pageBundle.quickPick.title": "ページバンドルとして使用",
"helpers.contentType.generate.pageBundle.quickPick.placeHolder": "この記事タイプをページバンドルとして使用しますか?",
"helpers.contentType.generate.updated.success": "記事タイプ {0} を更新しました。",
"helpers.contentType.generate.generated.success": "記事タイプ {0} を生成しました。",
"helpers.contentType.addMissingFields.noFrontMatter.warning": "追加すべきfront matterデータはありません。",
"helpers.contentType.addMissingFields.updated.success": "記事タイプ {0} を更新しました。",
"helpers.contentType.setContentType.noFrontMatter.warning": "記事タイプの設定が必要なfront matterデータが見つかりません。",
"helpers.contentType.setContentType.quickPick.title": "記事タイプを選択",
"helpers.contentType.setContentType.quickPick.placeholder": "どの記事タイプを使用しますか?",
"helpers.contentType.create.allowSubContent.title": "サブコンテンツとしての要否",
"helpers.contentType.create.allowSubContent.placeHolder": "新規記事をサブコンテンツとして作成しますか?",
"helpers.contentType.create.allowSubContent.showOpenDialog.openLabel": "フォルダーを選択",
"helpers.contentType.create.allowSubContent.showOpenDialog.title": "新規記事用のフォルダーを選択してください。",
"helpers.contentType.create.pageBundle.title": "ページバンドルとして要否",
"helpers.contentType.create.pageBundle.placeHolder": "ページバンドルとして記事を作成しますか?",
"helpers.contentType.create.progress.title": "{0}: 記事ファイルを作成中...",
"helpers.contentType.create.success": "記事ファイルを作成しました。",
"helpers.contentType.verify.warning": "記事タイプ・コマンドは、このモードでは有効になっていません。",
"helpers.customScript.executing": "実行中: {0}",
"helpers.customScript.singleRun.article.warning": "{0}: Article couldn't be retrieved.",
"helpers.customScript.bulkRun.noFiles.warning": "{0}: ファイルが見つかりません。",
"helpers.customScript.runMediaScript.noFolder.warning": "{0}: フォルダーまたはメディアへのパスの指定がされていません。",
"helpers.customScript.showOutput.frontMatter.success": "{0}: front matter updated.",
"helpers.customScript.showOutput.copyOutput.action": "出力結果をコピー",
"helpers.customScript.showOutput.success": "{0}: カスタムスクリプトを実行しました。",
"helpers.customScript.validateCommand.error": "不正なコマンド: {0}",
"helpers.dataFileHelper.process.error": "データファイルの実行中に何らかの問題が発生しました。",
"helpers.extension.getVersion.changelog": "変更履歴を確認する",
"helpers.extension.getVersion.starIt": "⭐️を付ける",
"helpers.extension.getVersion.update.notification": "{0} が v{1} に更新されました!新機能をチェックしてください!",
"helpers.extension.migrateSettings.deprecated.warning": "\"{0}\"及び\"{1}\"の設定は非推奨になりました。代わりに\"isPublishDate\"と\"isModifiedDate\"の日付フィールドを使用してください。",
"helpers.extension.migrateSettings.deprecated.warning.hide": "非表示にする",
"helpers.extension.migrateSettings.deprecated.warning.seeGuide": "移行ガイドを読む",
"helpers.extension.migrateSettings.templates.quickPick.title": "{0} - テンプレート",
"helpers.extension.migrateSettings.templates.quickPick.placeholder": "テンプレート機能の使用を継続しますか?",
"helpers.extension.checkIfExtensionCanRun.warning": "Front MatterのBETA版は安定版がインストールされている場合は利用できません。BETA版のみがインストールされていることを確認してください。",
"helpers.mediaHelper.saveFile.folder.error": "選択されたフォルダーが見つかりません。",
"helpers.mediaHelper.saveFile.file.uploaded.success": "ファイル{0}が{1}へアップロードされました。",
"helpers.mediaHelper.saveFile.file.uploaded.failed": "申し訳ありません、{0}のアップロード中にエラーが発生しました。",
"helpers.mediaHelper.deleteFile.file.deletion.failed": "申し訳ありません、{0}の削除中にエラーが発生しました。",
"helpers.mediaLibrary.remove.warning": "その場所にはファイル\"{0}\"が既に存在しています。",
"helpers.mediaLibrary.remove.error": "申し訳ありません、\"{0}\"を\"{1}\"へのアップロード中にエラーが発生しました。",
"helpers.openFileInEditor.error": "ファイルを開けません。",
"helpers.questions.contentTitle.aiInput.title": "タイトルまたはディスクリプション",
"helpers.questions.contentTitle.aiInput.prompt": "どんな内容について書きたいですか?",
"helpers.questions.contentTitle.aiInput.placeholder": "どんな内容について書きたいですか?",
"helpers.questions.contentTitle.aiInput.quickPick.title.separator": "タイトル/ディスクリプション",
"helpers.questions.contentTitle.aiInput.quickPick.ai.separator": "AI生成によるタイトル",
"helpers.questions.contentTitle.aiInput.select.title": "タイトルを選択",
"helpers.questions.contentTitle.aiInput.select.placeholder": "記事に付けるタイトルを選択",
"helpers.questions.contentTitle.aiInput.failed": "AIタイトルの取得に失敗しました。自分で作成するか、後からもう一度試してください。",
"helpers.questions.contentTitle.aiInput.warning": "記事タイトルの入力がされていません。",
"helpers.questions.contentTitle.titleInput.title": "記事タイトル",
"helpers.questions.contentTitle.titleInput.prompt": "新しい記事のタイトルを入力してください。",
"helpers.questions.contentTitle.titleInput.placeholder": "タイトル",
"helpers.questions.contentTitle.titleInput.warning": "記事タイトルの入力がされていません。",
"helpers.questions.selectContentFolder.quickPick.title": "フォルダーを選択",
"helpers.questions.selectContentFolder.quickPick.placeholder": "記事の保存先を選択してください。",
"helpers.questions.selectContentFolder.quickPick.noSelection.warning": "記事の保存先が選択されていません。",
"helpers.questions.selectContentType.noContentType.warning": "記事タイプが見つかりません。先に記事タイプを作成してから記事を作成してください。",
"helpers.questions.selectContentType.quickPick.title": "記事タイプ",
"helpers.questions.selectContentType.quickPick.placeholder": "新規作成する記事の記事タイプを選択してください。",
"helpers.questions.selectContentType.noSelection.warning": "記事タイプが選択されていません。",
"helpers.seoHelper.checkLength.diagnostic.message": "記事{0}の文字数が{1}文字を超えています(現在の文字数: {2})。SEOの観点上、{1}文字以内に収めることが推奨されます。",
"helpers.settingsHelper.checkToPromote.message": "ローカル設定が存在します。この設定をグローバル設定(\"frontmatter.json\")に昇格させますか?",
"helpers.settingsHelper.promote.success": "全ての設定をチームレベルに昇格しました。",
"helpers.settingsHelper.readConfig.progress.title": "{0}: 動的な設定ファイルを読み込んでいます...",
"helpers.settingsHelper.readConfig.error": "設定の読み込みでエラーが発生しました。",
"helpers.settingsHelper.refreshConfig.success": "設定を再読み込みしました。",
"helpers.taxonomyHelper.rename.input.title": "タクソノミー名を変更 {0}",
"helpers.taxonomyHelper.rename.validate.equalValue": "現在のファイル名とは別のファイル名を入力してください。",
"helpers.taxonomyHelper.rename.validate.noValue": "新しいファイル名を入力してください。",
"helpers.taxonomyHelper.merge.quickPick.title": "\"{0}\"を別の{1}にマージ",
"helpers.taxonomyHelper.merge.quickPick.placeholder": "マージする{0}を選択してください。",
"helpers.taxonomyHelper.delete.quickPick.title": "\"{0}\"を{1}から削除",
"helpers.taxonomyHelper.delete.quickPick.placeholder": "本当に\"{0}\"を{1}から削除しますか?",
"helpers.taxonomyHelper.createNew.input.title": "{0}に新規タクソノミーを作成",
"helpers.taxonomyHelper.createNew.input.placeholder": "作成したいタクソノミー名を入力してください。",
"helpers.taxonomyHelper.createNew.input.validate.noValue": "タクソノミー名は必須です。",
"helpers.taxonomyHelper.createNew.input.validate.exists": "このタクソノミー名は既に存在しています。",
"helpers.taxonomyHelper.process.edit": "{0}: {2}内の\"{1}\"を{3}に変更しています。",
"helpers.taxonomyHelper.process.merge": "{0}: {2}内の\"{1}\"を{3}にマージしています。",
"helpers.taxonomyHelper.process.delete": "{0}: \"{1}\"を{2}から削除しています。",
"helpers.taxonomyHelper.process.edit.success": "変更しました。",
"helpers.taxonomyHelper.process.merge.success": "マージしました。",
"helpers.taxonomyHelper.process.delete.success": "削除しました。",
"helpers.taxonomyHelper.move.quickPick.title": "\"{0}\"を別のタクソノミータイプに移行",
"helpers.taxonomyHelper.move.quickPick.placeholder": "移行先のタクソノミータイプを選択してください。",
"helpers.taxonomyHelper.move.progress.title": "{0}: \"{1}\"を{2}から\"${3}\"へ移行しています。",
"helpers.taxonomyHelper.move.success": "移行しました。",
"listeners.dashboard.dashboardListener.openConfig.notification": "設定内容を確認するには\"frontmatter.json\"を開いてください。",
"listeners.dashboard.dashboardListener.pinItem.noPath.error": "パスが指定されていません。",
"listeners.dashboard.dashboardListener.pinItem.coundNotPin.error": "ピン留めができませんでした。",
"listeners.dashboard.dashboardListener.pinItem.coundNotUnPin.error": "ピン留めの解除ができませんでした。",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "テンプレートファイルがコピーされました。",
"common.openOnWebsite": "ウェブサイトで開く",
"common.filter.value": "{0} でフィルタリング",
"dashboard.media.detailsSlideOver.unmapped.description": "未割り当てのファイルのメタデータを再マップしますか",
"common.settings": "設定",
"common.refreshSettings": "設定の更新",
"common.pin": "ピン",
"common.unpin": "解除",
"settings.view.common": "コモン",
"settings.view.contentFolders": "コンテンツ フォルダー",
"settings.view.astro": "アストロ",
"settings.openOnStartup": "起動時にダッシュボードを開く",
"settings.contentTypes": "コンテンツ タイプ",
"settings.contentFolders": "コンテンツ フォルダー",
"settings.diagnostic": "診断",
"settings.diagnostic.description": "診断プログラムを実行して、フロントマター CMS 構成全体を確認できます。",
"settings.diagnostic.link": "完全診断を実行する",
"settings.commonSettings.website.title": "ウェブサイトとSSGの設定",
"settings.commonSettings.previewUrl": "URL のプレビュー",
"settings.commonSettings.websiteUrl": "ウェブサイトの URL",
"settings.commonSettings.startCommand": "SSG/フレームワーク起動コマンド",
"dashboard.contents.overview.pinned": "固定",
"dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Astroコンテンツコレクションのコンテンツタイプを作成する",
"dashboard.welcomeScreen.link.documentation.label": "ドキュメンテーション",
"dashboard.configuration.astro.astroContentTypes.empty": "Astroコンテンツコレクションが見つかりません。",
"dashboard.configuration.astro.astroContentTypes.description": "以下のAstroコンテンツコレクションは、コンテンツタイプを生成するために使用できます。"
"listeners.dashboard.settingsListener.triggerTemplate.progress.title": "テンプレートをダウンロードして初期化しています...",
"listeners.dashboard.settingsListener.triggerTemplate.download.error": "テンプレートのダウンロードに失敗しました。",
"listeners.dashboard.settingsListener.triggerTemplate.init.error": "テンプレートの初期化に失敗しました。",
"listeners.dashboard.snippetListener.addSnippet.missingFields.warning": "スニペットのタイトルまたはbodyが空です。",
"listeners.dashboard.snippetListener.addSnippet.exists.warning": "同じタイトルのスニペットが既に存在しています。",
"listeners.dashboard.snippetListener.updateSnippet.noSnippets.warning": "更新が必要なスニペットはありません。",
"listeners.general.gitListener.push.error": "submoduleのpushに失敗しました。",
"listeners.panel.dataListener.aiSuggestTaxonomy.noEditor.error": "アクティブなエディターがありません。",
"listeners.panel.dataListener.aiSuggestTaxonomy.noData.error": "記事データがありません。",
"listeners.panel.dataListener.getDataFileEntries.noDataFiles.error": "データファイルのエントリーが見つかりませんでした。",
"listeners.panel.taxonomyListener.aiSuggestTaxonomy.noEditor.error": "アクティブなエディターがありません。",
"listeners.panel.taxonomyListener.aiSuggestTaxonomy.noData.error": "記事データがありません。",
"services.modeSwitch.switchMode.quickPick.placeholder": "モードを選択してください。",
"services.modeSwitch.switchMode.quickPick.title": "{0}: モードの選択",
"services.modeSwitch.setText.mode": "モード: {0}",
"services.pagesParser.parsePages.statusBar.text": "読み込み中...",
"services.pagesParser.parsePages.file.error": "ファイルエラー: {0}",
"services.sponsorAi.getTitles.warning": "AIによるタイトル生成に時間がかかりすぎています。後でもう一度試してください。",
"services.sponsorAi.getDescription.warning": "AIによるディスクリプション生成に時間がかかりすぎています。後でもう一度試してください。",
"services.sponsorAi.getTaxonomySuggestions.warning": "AIによるタクソノミー生成に時間がかかりすぎています。後でもう一度試してください。",
"services.terminal.openLocalServerTerminal.terminalOption.message": "ローカルサーバーを起動"
}
+261 -2
View File
@@ -3,6 +3,7 @@
"common.edit": "Edit",
"common.delete": "Delete",
"common.cancel": "Cancel",
"common.apply": "Apply",
"common.clear": "Clear",
"common.clear.value": "Clear value",
"common.search": "Search",
@@ -20,6 +21,7 @@
"common.slug": "Slug",
"common.support": "Support",
"common.remove.value": "Remove {0}",
"common.filter": "Back",
"common.filter.value": "Filter by {0}",
"common.error.message": "Sorry, something went wrong.",
"common.openOnWebsite": "Open on website",
@@ -28,6 +30,14 @@
"common.pin": "Pin",
"common.unpin": "Unpin",
"common.noResults": "No results",
"common.error": "Sorry, something went wrong.",
"common.yes": "yes",
"common.no": "no",
"common.openSettings": "Open settings",
"common.back": "Back",
"notifications.outputChannel.link": "output window",
"notifications.outputChannel.description": "Check the {0} for more details.",
"settings.view.common": "Common",
"settings.view.contentFolders": "Content folders",
@@ -269,6 +279,7 @@
"dashboard.steps.stepsToGetStarted.showDashboard.description": "Once all actions are completed, the dashboard can be loaded.",
"dashboard.steps.stepsToGetStarted.template.name": "Use a configuration template",
"dashboard.steps.stepsToGetStarted.template.description": "Select a template to prefill the frontmatter.json file with the recommended settings.",
"dashboard.steps.stepsToGetStarted.template.warning": "Selecting a template applies a whole configuration to your project and closes this configuration view.",
"dashboard.steps.stepsToGetStarted.astroContentTypes.name": "Create Content-Types for your Astro Content Collections",
"dashboard.taxonomyView.button.add.title": "Add {0} to taxonomy settings",
@@ -286,6 +297,10 @@
"dashboard.taxonomyView.taxonomyManager.table.heading.action": "Action",
"dashboard.taxonomyView.taxonomyManager.table.row.empty": "No {0} found",
"dashboard.taxonomyView.taxonomyManager.table.unmapped.title": "Missing in your settings",
"dashboard.taxonomyView.taxonomyManager.filterInput.placeholder": "Filter",
"dashboard.taxonomyView.taxonomyTagging.pageTitle": "Map your content with: {0}",
"dashboard.taxonomyView.taxonomyTagging.checkbox": "Tag page with {0}",
"dashboard.taxonomyView.taxonomyView.navigationBar.title": "Select the taxonomy",
"dashboard.taxonomyView.taxonomyView.button.import": "Import taxonomy",
@@ -312,7 +327,7 @@
"dashboard.media.detailsSlideOver.unmapped.description": "Do you want to remap the metadata of unmapped files?",
"dashboard.configuration.astro.astroContentTypes.empty": "No Astro Content Collections found.",
"dashboard.configuration.astro.astroContentTypes.description": "The following Astro Content Collections and can be used to generate a content-type.",
"dashboard.configuration.astro.astroContentTypes.description": "The following Astro Content Collections can be used to generate a content-type.",
"panel.contentType.contentTypeValidator.title": "Content-type",
"panel.contentType.contentTypeValidator.hint": "We noticed field differences between the content-type and the front matter data. \n Would you like to create, update, or set the content-type for this content?",
@@ -457,5 +472,249 @@
"panel.viewPanel.mediaInsert": "Continue in the media dashboard to select the image you want to insert.",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "Template files copied."
"commands.article.setDate.error": "Something failed while parsing the date format. Check your \"{0}\" setting.",
"commands.article.updateSlug.error": "Failed to rename file: {0}",
"commands.cache.cleared": "Cache cleared",
"commands.chatbot.title": "Ask me anything",
"commands.content.option.contentType.label": "Create content by content type",
"commands.content.option.contentType.description": "Select if you want to create new content by the available content type(s)",
"commands.content.option.template.label": "Create content by template",
"commands.content.option.template.description": "Select if you want to create new content by the available template(s)",
"commands.content.quickPick.title": "Create content",
"commands.content.quickPick.placeholder": "Select how you want to create your new content",
"commands.dashboard.title": "Dashboard",
"commands.folders.addMediaFolder.inputBox.title": "Add media folder",
"commands.folders.addMediaFolder.inputBox.prompt": "Which name would you like to give to your folder (use \"/\" to create multi-level folders)?",
"commands.folders.addMediaFolder.noFolder.warning": "No folder name was specified.",
"commands.folders.create.folderExists.warning": "Folder is already registered",
"commands.folders.create.input.title": "Register folder",
"commands.folders.create.input.prompt": "Which name would you like to specify for this folder?",
"commands.folders.create.input.placeholder": "Folder name",
"commands.folders.create.success": "Folder registered",
"commands.folders.getWorkspaceFolder.workspaceFolderPick.placeholder": "Please select the main workspace folder for Front Matter to use.",
"commands.folders.get.notificationError.title": "Folder \"{0}\" does not exist. Please remove it from the settings.",
"commands.folders.get.notificationError.remove.action": "Remove folder",
"commands.folders.get.notificationError.create.action": "Create folder",
"commands.preview.panel.title": "Preview: {0}",
"commands.preview.askUserToPickFolder.title": "Select the folder of the article to preview",
"commands.project.initialize.success": "Project initialized successfully.",
"commands.project.switchProject.title": "To which project do you want to switch?",
"commands.project.createSampleTemplate.info": "Sample template created.",
"commands.settings.create.input.prompt": "Insert the value of the {0} that you want to add to your configuration.",
"commands.settings.create.input.placeholder": "Name of the {0}",
"commands.settings.create.warning": "The provided {0} already exists.",
"commands.settings.create.quickPick.placeholder": "Do you want to add the new {0} to the page?",
"commands.settings.export.progress.title": "{0}: exporting tags and categories",
"commands.settings.export.progress.success": "Export completed. Tags: {0} - Categories: {1}.",
"commands.settings.remap.quickpick.title": "Remap",
"commands.settings.remap.quickpick.placeholder": "What do you want to remap?",
"commands.settings.remap.noTaxonomy.warning": "No {0} configured.",
"commands.settings.remap.selectTaxonomy.placeholder": "Select your {0} to insert.",
"commands.settings.remap.newOption.input.prompt": "Specify the value of the {0} with which you want to remap \"{1}\". Leave the input <blank> if you want to remove the {0} from all articles.",
"commands.settings.remap.newOption.input.placeholder": "Name of the {0}",
"commands.settings.remap.delete.placeholder": "Delete {0} {1}?",
"commands.statusListener.verifyRequiredFields.diagnostic.emptyField": "The {0} field is required. Please define a value for the field.",
"commands.statusListener.verifyRequiredFields.notification.error": "The following fields are required to contain a value: {0}",
"commands.template.generate.input.title": "Template title",
"commands.template.generate.input.prompt": "Which name would you like to give your template?",
"commands.template.generate.input.placeholder": "article",
"commands.template.generate.noTitle.warning": "You did not specify a template title.",
"commands.template.generate.keepContents.title": "Keep content",
"commands.template.generate.keepContents.placeholder": "Do you want to keep the contents for the template?",
"commands.template.generate.keepContents.noOption.warning": "You did not pick any of the options for keeping the template its content.",
"commands.template.generate.keepContents.success": "Template created and is now available in your {0} folder.",
"commands.template.getTemplates.warning": "No templates found.",
"commands.template.create.folderPath.warning": "Incorrect project folder path retrieved.",
"commands.template.create.noTemplates.warning": "No templates found.",
"commands.template.create.selectTemplate.title": "Select a template",
"commands.template.create.selectTemplate.placeholder": "Select the content template to use",
"commands.template.create.selectTemplate.noTemplate.warning": "No template selected.",
"commands.template.create.selectTemplate.notFound.warning": "Content template could not be found.",
"commands.template.create.success": "Your new content is now available.",
"commands.wysiwyg.command.unorderedList.label": "Unordered list",
"commands.wysiwyg.command.unorderedList.detail": "Add an unordered list",
"commands.wysiwyg.command.orderedList.label": "Ordered list",
"commands.wysiwyg.command.orderedList.detail": "Add an ordered list",
"commands.wysiwyg.command.taskList.label": "Task list",
"commands.wysiwyg.command.taskList.detail": "Add a task list",
"commands.wysiwyg.command.code.label": "Code",
"commands.wysiwyg.command.code.detail": "Add inline code snippet",
"commands.wysiwyg.command.codeblock.label": "Code block",
"commands.wysiwyg.command.codeblock.detail": "Add a code block",
"commands.wysiwyg.command.blockquote.label": "Blockquote",
"commands.wysiwyg.command.blockquote.detail": "Add a blockquote",
"commands.wysiwyg.command.strikethrough.label": "Strikethrough",
"commands.wysiwyg.command.strikethrough.detail": "Add strikethrough text",
"commands.wysiwyg.quickPick.title": "WYSIWYG Options",
"commands.wysiwyg.quickPick.placeholder": "Which type of markup would you like to insert?",
"commands.wysiwyg.addHyperlink.hyperlinkInput.title": "WYSIWYG Hyperlink",
"commands.wysiwyg.addHyperlink.hyperlinkInput.prompt": "Enter the URL",
"commands.wysiwyg.addHyperlink.textInput.title": "WYSIWYG Text",
"commands.wysiwyg.addHyperlink.textInput.prompt": "Enter the text for the hyperlink",
"commands.wysiwyg.insertText.heading.input.title": "Heading level",
"commands.wysiwyg.insertText.heading.input.placeholder": "Which heading level do you want to insert?",
"helpers.articleHelper.createContent.pageBundle.error": "A page bundle with the name {0} already exists in {1}.",
"helpers.articleHelper.createContent.contentExists.warning": "Content with the title already exists. Please specify a new title.",
"helpers.articleHelper.processCustomPlaceholders.placeholder.error": "Error while processing the {0} placeholder.",
"helpers.articleHelper.parseFile.diagnostic.error": "Error parsing the front matter of {0}.",
"helpers.contentType.generate.noFrontMatter.error": "No front matter data found to generate a content type.",
"helpers.contentType.generate.override.quickPick.title": "Override the default content type",
"helpers.contentType.generate.override.quickPick.placeholder": "Do you want to overwrite the default content type configuration with the fields used in the current field?",
"helpers.contentType.generate.contentTypeInput.title": "Generate Content Type",
"helpers.contentType.generate.contentTypeInput.prompt": "Enter the name of the content type to generate",
"helpers.contentType.generate.contentTypeInput.validation.enterName": "Please enter a name for the content type.",
"helpers.contentType.generate.contentTypeInput.validation.nameExists": "A content type with this name already exists.",
"helpers.contentType.generate.noContentTypeName.warning": "You didn't specify a name for the content type.",
"helpers.contentType.generate.pageBundle.quickPick.title": "Use as a page bundle",
"helpers.contentType.generate.pageBundle.quickPick.placeHolder": "Do you want to use this content type as a page bundle?",
"helpers.contentType.generate.updated.success": "Content type {0} has been updated.",
"helpers.contentType.generate.generated.success": "Content type {0} has been generated.",
"helpers.contentType.addMissingFields.noFrontMatter.warning": "No front matter data found to add missing fields.",
"helpers.contentType.addMissingFields.updated.success": "Content type {0} has been updated.",
"helpers.contentType.setContentType.noFrontMatter.warning": "No front matter data found to set the content type.",
"helpers.contentType.setContentType.quickPick.title": "Select the content type",
"helpers.contentType.setContentType.quickPick.placeholder": "Which content type would you like to use?",
"helpers.contentType.create.allowSubContent.title": "Do you want to create it as sub-content?",
"helpers.contentType.create.allowSubContent.placeHolder": "Do you want to create it as sub-content?",
"helpers.contentType.create.allowSubContent.showOpenDialog.openLabel": "Select folder",
"helpers.contentType.create.allowSubContent.showOpenDialog.title": "Select folder to create the content",
"helpers.contentType.create.pageBundle.title": "Create as a page bundle?",
"helpers.contentType.create.pageBundle.placeHolder": "Do you want to create the sub-content as a page bundle?",
"helpers.contentType.create.progress.title": "{0}: Creating content...",
"helpers.contentType.create.success": "Your new content has been created.",
"helpers.contentType.verify.warning": "The content type actions are not available in this mode.",
"helpers.customScript.executing": "Executing: {0}",
"helpers.customScript.singleRun.article.warning": "{0}: Article couldn't be retrieved.",
"helpers.customScript.bulkRun.noFiles.warning": "{0}: No files found",
"helpers.customScript.runMediaScript.noFolder.warning": "{0}: There was no folder or media path specified.",
"helpers.customScript.showOutput.frontMatter.success": "{0}: front matter updated.",
"helpers.customScript.showOutput.copyOutput.action": "Copy output",
"helpers.customScript.showOutput.success": "{0}: Executed your custom script.",
"helpers.customScript.validateCommand.error": "Invalid command: {0}",
"helpers.dataFileHelper.process.error": "Something went wrong while processing the data file.",
"helpers.extension.getVersion.changelog": "Check the changelog",
"helpers.extension.getVersion.starIt": "Give it a ⭐️",
"helpers.extension.getVersion.update.notification": "{0} has been updated to v{1} — check out what's new!",
"helpers.extension.migrateSettings.deprecated.warning": "The \"{0}\" and \"{1}\" settings have been deprecated. Please use the \"isPublishDate\" and \"isModifiedDate\" datetime field properties instead.",
"helpers.extension.migrateSettings.deprecated.warning.hide": "Hide",
"helpers.extension.migrateSettings.deprecated.warning.seeGuide": "See migration guide",
"helpers.extension.migrateSettings.templates.quickPick.title": "{0} - Templates",
"helpers.extension.migrateSettings.templates.quickPick.placeholder": "Do you want to keep on using the template functionality?",
"helpers.extension.checkIfExtensionCanRun.warning": "Front Matter BETA cannot be used while the stable version is installed. Please ensure that you have only over version installed.",
"helpers.mediaHelper.saveFile.folder.error": "We couldn't find your selected folder.",
"helpers.mediaHelper.saveFile.file.uploaded.success": "File {0} uploaded to: {1}",
"helpers.mediaHelper.saveFile.file.uploaded.failed": "Sorry, something went wrong uploading {0}",
"helpers.mediaHelper.deleteFile.file.deletion.failed": "Sorry, something went wrong deleting {0}",
"helpers.mediaLibrary.remove.warning": "The name \"{0}\" already exists at the file location.",
"helpers.mediaLibrary.remove.error": "Sorry, something went wrong updating \"{0}\" to \"{1}\".",
"helpers.openFileInEditor.error": "Couldn't open the file.",
"helpers.questions.contentTitle.aiInput.title": "Title or description",
"helpers.questions.contentTitle.aiInput.prompt": "What would you like to write about?",
"helpers.questions.contentTitle.aiInput.placeholder": "What would you like to write about?",
"helpers.questions.contentTitle.aiInput.quickPick.title.separator": "your title/description",
"helpers.questions.contentTitle.aiInput.quickPick.ai.separator": "AI generated title",
"helpers.questions.contentTitle.aiInput.select.title": "Select a title",
"helpers.questions.contentTitle.aiInput.select.placeholder": "Select a title for your content",
"helpers.questions.contentTitle.aiInput.failed": "Failed fetching the AI title. Please try to use your own title or try again later.",
"helpers.questions.contentTitle.aiInput.warning": "You did not specify a title for your content.",
"helpers.questions.contentTitle.titleInput.title": "Content title",
"helpers.questions.contentTitle.titleInput.prompt": "What would you like to use as a title for the content to create?",
"helpers.questions.contentTitle.titleInput.placeholder": "Content title",
"helpers.questions.contentTitle.titleInput.warning": "You did not specify a title for your content.",
"helpers.questions.selectContentFolder.quickPick.title": "Select a folder",
"helpers.questions.selectContentFolder.quickPick.placeholder": "Select where you want to create your content",
"helpers.questions.selectContentFolder.quickPick.noSelection.warning": "You didn't select a place where you wanted to create your content.",
"helpers.questions.selectContentType.noContentType.warning": "No content types found. Please create a content type first.",
"helpers.questions.selectContentType.quickPick.title": "Content type",
"helpers.questions.selectContentType.quickPick.placeholder": "Select the content type to create your new content",
"helpers.questions.selectContentType.noSelection.warning": "No content type was selected.",
"helpers.seoHelper.checkLength.diagnostic.message": "Article {0} is longer than {1} characters (current length: {2}). For SEO reasons, it would be better to make it less than {1} characters.",
"helpers.settingsHelper.checkToPromote.message": "You have local settings. Would you like to promote them to the global settings (\"frontmatter.json\")?",
"helpers.settingsHelper.promote.success": "All settings promoted to team level.",
"helpers.settingsHelper.readConfig.progress.title": "{0}: Reading dynamic config file...",
"helpers.settingsHelper.readConfig.error": "Error reading your configuration.",
"helpers.settingsHelper.refreshConfig.success": "Settings have been refreshed.",
"helpers.taxonomyHelper.rename.input.title": "Rename the {0}",
"helpers.taxonomyHelper.rename.validate.equalValue": "The new value must be different from the old one.",
"helpers.taxonomyHelper.rename.validate.noValue": "A new value must be provided.",
"helpers.taxonomyHelper.merge.quickPick.title": "Merge the \"{0}\" with another {1} value",
"helpers.taxonomyHelper.merge.quickPick.placeholder": "Select the {0} value to merge with",
"helpers.taxonomyHelper.delete.quickPick.title": "Delete the \"{0}\" {1} value",
"helpers.taxonomyHelper.delete.quickPick.placeholder": "Are you sure you want to delete the \"{0}\" {1} value?",
"helpers.taxonomyHelper.createNew.input.title": "Create a new {0} value",
"helpers.taxonomyHelper.createNew.input.placeholder": "Enter the value you want to add",
"helpers.taxonomyHelper.createNew.input.validate.noValue": "A value must be provided.",
"helpers.taxonomyHelper.createNew.input.validate.exists": "The value already exists.",
"helpers.taxonomyHelper.process.insert": "{0}: Inserting \"{1}\" to your selected pages.",
"helpers.taxonomyHelper.process.edit": "{0}: Renaming \"{1}\" from {2} to {3}.",
"helpers.taxonomyHelper.process.merge": "{0}: Merging \"{1}\" from {2} to {3}.",
"helpers.taxonomyHelper.process.delete": "{0}: Deleting \"{1}\" from {2}.",
"helpers.taxonomyHelper.process.insert.success": "Insert completed.",
"helpers.taxonomyHelper.process.edit.success": "Edit completed.",
"helpers.taxonomyHelper.process.merge.success": "Merge completed.",
"helpers.taxonomyHelper.process.delete.success": "Deletion completed.",
"helpers.taxonomyHelper.move.quickPick.title": "Move the \"{0}\" to another type",
"helpers.taxonomyHelper.move.quickPick.placeholder": "Select the type to move to",
"helpers.taxonomyHelper.move.progress.title": "{0}: Moving \"{1}\" from {2} to \"${3}\".",
"helpers.taxonomyHelper.move.success": "Move completed.",
"listeners.dashboard.dashboardListener.openConfig.notification": "Open the \"frontmatter.json\" file if you want to review the configuration.",
"listeners.dashboard.dashboardListener.pinItem.noPath.error": "No path provided.",
"listeners.dashboard.dashboardListener.pinItem.coundNotPin.error": "Could not pin item.",
"listeners.dashboard.dashboardListener.pinItem.coundNotUnPin.error": "Could not unpin item.",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "Template files copied.",
"listeners.dashboard.settingsListener.triggerTemplate.progress.title": "Downloading and initializing the template...",
"listeners.dashboard.settingsListener.triggerTemplate.download.error": "Failed to download the template.",
"listeners.dashboard.settingsListener.triggerTemplate.init.error": "Failed to initialize the template.",
"listeners.dashboard.snippetListener.addSnippet.missingFields.warning": "Snippet missing title or body",
"listeners.dashboard.snippetListener.addSnippet.exists.warning": "Snippet with the same title already exists",
"listeners.dashboard.snippetListener.updateSnippet.noSnippets.warning": "No snippets to update",
"listeners.general.gitListener.push.error": "Failed to push submodules.",
"listeners.panel.dataListener.aiSuggestTaxonomy.noEditor.error": "No active editor",
"listeners.panel.dataListener.aiSuggestTaxonomy.noData.error": "No article data",
"listeners.panel.dataListener.getDataFileEntries.noDataFiles.error": "Couldn't find data file entries",
"listeners.panel.taxonomyListener.aiSuggestTaxonomy.noEditor.error": "No active editor",
"listeners.panel.taxonomyListener.aiSuggestTaxonomy.noData.error": "No article data",
"services.modeSwitch.switchMode.quickPick.placeholder": "Select the mode you want to use",
"services.modeSwitch.switchMode.quickPick.title": "{0}: Mode selection",
"services.modeSwitch.setText.mode": "Mode: {0}",
"services.pagesParser.parsePages.statusBar.text": "Processing...",
"services.pagesParser.parsePages.file.error": "File error: {0}",
"services.sponsorAi.getTitles.warning": "The AI title generation took too long. Please try again later.",
"services.sponsorAi.getDescription.warning": "The AI description generation took too long. Please try again later.",
"services.sponsorAi.getTaxonomySuggestions.warning": "The AI taxonomy generation took too long. Please try again later.",
"services.terminal.openLocalServerTerminal.terminalOption.message": "Starting local server"
}
+1
View File
@@ -0,0 +1 @@
{}
+1
View File
@@ -0,0 +1 @@
{}
+9 -5
View File
@@ -1,19 +1,19 @@
{
"name": "vscode-front-matter-beta",
"version": "9.4.0",
"version": "9.5.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "vscode-front-matter-beta",
"version": "9.4.0",
"version": "9.5.0",
"license": "MIT",
"devDependencies": {
"@actions/core": "^1.10.0",
"@bendera/vscode-webview-elements": "0.6.2",
"@estruyf/vscode": "^1.1.0",
"@headlessui/react": "^1.7.17",
"@heroicons/react": "1.0.4",
"@heroicons/react": "^2.1.1",
"@iarna/toml": "2.2.3",
"@octokit/rest": "^18.12.0",
"@popperjs/core": "^2.11.6",
@@ -364,7 +364,9 @@
}
},
"node_modules/@heroicons/react": {
"version": "1.0.4",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.1.tgz",
"integrity": "sha512-JyyN9Lo66kirbCMuMMRPtJxtKJoIsXKS569ebHGGRKbl8s4CtUfLnyKJxteA+vIKySocO4s1SkTkGS4xtG/yEA==",
"dev": true,
"peerDependencies": {
"react": ">= 16"
@@ -13333,7 +13335,9 @@
}
},
"@heroicons/react": {
"version": "1.0.4",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.1.tgz",
"integrity": "sha512-JyyN9Lo66kirbCMuMMRPtJxtKJoIsXKS569ebHGGRKbl8s4CtUfLnyKJxteA+vIKySocO4s1SkTkGS4xtG/yEA==",
"dev": true,
"requires": {}
},
+42 -13
View File
@@ -3,7 +3,7 @@
"displayName": "Front Matter CMS",
"description": "Front Matter is a CMS that runs within Visual Studio Code. It gives you the power and control of a full-blown CMS while also providing you the flexibility and speed of the static site generator of your choice like: Hugo, Jekyll, Docusaurus, NextJs, Gatsby, and many more...",
"icon": "assets/frontmatter-teal-128x128.png",
"version": "9.4.0",
"version": "9.5.0",
"preview": false,
"publisher": "eliostruyf",
"galleryBanner": {
@@ -1005,15 +1005,18 @@
"type": "array",
"default": [],
"markdownDescription": "%setting.frontMatter.panel.actions.disabled.markdownDescription%",
"enum": [
"openDashboard",
"createContent",
"optimizeSlug",
"preview",
"openOnWebsite",
"startStopServer",
"customActions"
]
"items": {
"type": "string",
"enum": [
"openDashboard",
"createContent",
"optimizeSlug",
"preview",
"openOnWebsite",
"startStopServer",
"customActions"
]
}
},
"frontMatter.preview.host": {
"type": "string",
@@ -1082,7 +1085,17 @@
"clearEmpty": {
"type": "boolean",
"default": false,
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description%"
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.clearEmpty.description%"
},
"allowAsSubContent": {
"type": "boolean",
"default": false,
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.allowAsSubContent.description%"
},
"isSubContent": {
"type": "boolean",
"default": false,
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.isSubContent.description%"
},
"fields": {
"$id": "#contenttypefield",
@@ -1743,6 +1756,12 @@
"markdownDescription": "%setting.frontMatter.taxonomy.modifiedField.markdownDescription%",
"deprecationMessage": "%setting.frontMatter.taxonomy.modifiedField.deprecationMessage%"
},
"frontMatter.taxonomy.quoteStringValues": {
"type": "boolean",
"default": false,
"markdownDescription": "%setting.frontMatter.taxonomy.quoteStringValues.markdownDescription%",
"scope": "Taxonomy"
},
"frontMatter.taxonomy.noPropertyValueQuotes": {
"type": "array",
"default": [],
@@ -2161,6 +2180,12 @@
}
],
"menus": {
"webview/context": [
{
"command": "workbench.action.webview.openDeveloperTools",
"when": "frontMatter:isDevelopment"
}
],
"editor/title": [
{
"command": "frontMatter.markup.heading",
@@ -2359,6 +2384,10 @@
"command": "frontMatter.markup.options",
"when": "false"
},
{
"command": "frontMatter.config.reload",
"when": "false"
},
{
"command": "frontMatter.insertSnippet",
"when": "frontMatter:file:isValid == true && frontMatter:dashboard:snippets:enabled"
@@ -2514,7 +2543,7 @@
"clean": "rimraf dist",
"start:site": "cd ./docs && npm run dev",
"clean:test": "rm ./e2e/sample/frontmatter.json || exit 0 && rm -rf ./e2e/sample/.frontmatter || exit 0",
"test": "pnpm lint; tsc -p tsconfig.e2e.json && npm run clean:test && pnpm i -g @vscode/vsce && node ./e2e/out/runTests.js",
"test": "npm run lint; tsc -p tsconfig.e2e.json && npm run clean:test && npm run i -g @vscode/vsce && node ./e2e/out/runTests.js",
"lint": "eslint --max-warnings=0 ./src/{commands,components}",
"prettier": "prettier --write ./src",
"localization:watch": "node ./scripts/watch-localization.js",
@@ -2527,7 +2556,7 @@
"@bendera/vscode-webview-elements": "0.6.2",
"@estruyf/vscode": "^1.1.0",
"@headlessui/react": "^1.7.17",
"@heroicons/react": "1.0.4",
"@heroicons/react": "^2.1.1",
"@iarna/toml": "2.2.3",
"@octokit/rest": "^18.12.0",
"@popperjs/core": "^2.11.6",
+46 -42
View File
@@ -40,7 +40,7 @@
"command.frontMatter.preview": "記事のプレビューを開く",
"command.frontMatter.chatbot": "Front Matter AIに質問する",
"command.frontMatter.promoteSettings": "ローカル設定をチームレベルへ昇格させる",
"command.frontMatter.remap": "全ての記事のタグまたはカテゴリーを再配置または削除する",
"command.frontMatter.remap": "全ての記事のタグまたはカテゴリーを再構成または削除する",
"command.frontMatter.setLastModifiedDate": "最終更新日を設定する",
"command.frontMatter.markup.strikethrough": "取り消し線",
"command.frontMatter.mode.switch": "モードの切り替え",
@@ -53,7 +53,7 @@
"setting.frontMatter.projects.items.properties.name.markdownDescription": "プロジェクトの名前を指定します。",
"setting.frontMatter.projects.items.properties.default.markdownDescription": "このプロジェクトを読み込む既定のプロジェクトにするかどうかを指定します。",
"setting.frontMatter.sponsors.ai.enabled.markdownDescription": "AIによる提案を利用します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.sponsors.ai.enabled)",
"setting.frontMatter.extensibility.scripts.markdownDescription": "Front Matter CMSで読み込むスクリプトのリストを指定します。. [ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.extensibility.scripts)",
"setting.frontMatter.extensibility.scripts.markdownDescription": "Front Matter CMSで読み込むスクリプトのリストを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.extensibility.scripts)",
"setting.frontMatter.experimental.markdownDescription": "実験的な機能をオンにします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.experimental)",
"setting.frontMatter.extends.markdownDescription": "Front Matter CMSの構成を拡張するパス/URLのリストを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.extends)",
"setting.frontMatter.content.autoUpdateDate.markdownDescription": "記事やページの最終編集日を自動で更新します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.autoupdatedate)",
@@ -62,25 +62,26 @@
"setting.frontMatter.content.draftField.markdownDescription": "記事の下書きステータスを管理するフィールドを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.draftfield)",
"setting.frontMatter.content.draftField.properties.type.description": "使用する下書きフィールドの種類",
"setting.frontMatter.content.draftField.properties.name.description": "使用するフィールドの名前",
"setting.frontMatter.content.draftField.properties.invert.description": "既定では、コンテンツが下書きの場合、下書きフィールドは true に設定されます。これを true に設定すると、false に設定されます。",
"setting.frontMatter.content.draftField.properties.invert.description": "既定では、記事が下書きの場合、下書きフィールドは true に設定されます。これを true に設定すると、false に設定されます。",
"setting.frontMatter.content.draftField.properties.choices.description": "フィールドの選択肢のリスト",
"setting.frontMatter.content.fmHighlight.markdownDescription": "Markdownファイル内のfront matterをハイライトします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.fmhighlight)",
"setting.frontMatter.content.hideFm.markdownDescription": "Markdownファイル内のfront matterを非表示にします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.hidefm)",
"setting.frontMatter.content.hideFmMessage.markdownDescription": "front matterが非表示の際に、編集画面に表示するメッセージを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.hidefmmessage)",
"setting.frontMatter.content.pageFolders.markdownDescription": "フォルダーを配列で定義して、この拡張機能が記事を取得したり新しい記事を作成できるようにします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.pagefolders)",
"setting.frontMatter.content.pageFolders.items.properties.title.description": "フォルダの名前",
"setting.frontMatter.content.pageFolders.items.properties.path.description": "フォルダのパス",
"setting.frontMatter.content.pageFolders.items.properties.title.description": "フォルダの名前",
"setting.frontMatter.content.pageFolders.items.properties.path.description": "フォルダのパス",
"setting.frontMatter.content.pageFolders.items.properties.excludeSubdir.description": "サブディレクトリを除外する",
"setting.frontMatter.content.pageFolders.items.properties.previewPath.description": "フォルダーのカスタム プレビュー パスを定義します。",
"setting.frontMatter.content.pageFolders.items.properties.filePrefix.description": "ファイル名のプレフィックスを定義します。",
"setting.frontMatter.content.pageFolders.items.properties.contentTypes.description": "現在の場所に使用できるコンテンツ タイプを定義します。定義しない場合は、すべてのコンテンツ タイプを使用できます。",
"setting.frontMatter.content.pageFolders.items.properties.filePrefix.description": "ファイル名の接頭辞を定義します。",
"setting.frontMatter.content.pageFolders.items.properties.contentTypes.description": "現在の場所に使用できる記事タイプを定義します。定義しない場合は、全ての記事タイプを使用できます。",
"setting.frontMatter.content.pageFolders.items.properties.disableCreation.description": "フォルダー内の新しい記事の作成を無効にします。",
"setting.frontMatter.content.placeholders.markdownDescription": "記事タイプとテンプレートで使用するプレースホルダーを配列で定義して、記事のfront matterを自動で入力できるようにします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.placeholders)",
"setting.frontMatter.content.placeholders.items.properties.id.description": "プレースホルダーの ID をコンテンツ タイプまたはテンプレートで、次のように使用します: {{placeholder}}",
"setting.frontMatter.content.placeholders.items.properties.id.description": "プレースホルダーのIDを記事タイプまたはテンプレートで、次のように使用します: {{placeholder}}",
"setting.frontMatter.content.placeholders.items.properties.value.description": "プレースホルダーの値",
"setting.frontMatter.content.placeholders.items.properties.script.description": "プレースホルダーの値を取得するために実行するスクリプト",
"setting.frontMatter.content.publicFolder.markdownDescription": "アセットが保存されているフォルダーを設定します。例えば、Hugoでは`static`フォルダーです。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.publicfolder)",
"setting.frontMatter.content.publicFolder.properties.path.description": "アセットフォルダーのパスを指定します。",
"setting.frontMatter.content.publicFolder.properties.relative.description": "メディアファイルへのパスがコンテンツファイルに対して相対的であるかを定義します。",
"setting.frontMatter.content.publicFolder.properties.relative.description": "メディアファイルへのパスが記事ファイルに対して相対的であるかを定義します。",
"setting.frontMatter.snippets.wrapper.enabled.markdownDescription": "スニペット挿入時にコメントでラップします。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.snippets.wrapper.enabled)",
"setting.frontMatter.content.snippets.markdownDescription": "記事中に使用するスニペットを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.snippets)",
"setting.frontMatter.content.sorting.markdownDescription": "ダッシュボード上での記事の並べ替えオプションを追加します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.content.sorting)",
@@ -95,22 +96,23 @@
"setting.frontMatter.custom.scripts.items.properties.id.description": "スクリプトの ID。",
"setting.frontMatter.custom.scripts.items.properties.title.description": "スクリプトに付けるタイトル。ボタンのタイトルとして表示されます。",
"setting.frontMatter.custom.scripts.items.properties.script.description": "実行するスクリプトへのパス",
"setting.frontMatter.custom.scripts.items.properties.nodeBin.description": "ノード実行可能ファイルへのパス。これは、使用するノードのバージョンが混同されないように、NVM を使用するときに必要です。(非推奨: 代わりにコマンド プロパティを使用してください)",
"setting.frontMatter.custom.scripts.items.properties.bulk.description": "すべてのコンテンツ ファイルに対してスクリプトを実行する",
"setting.frontMatter.custom.scripts.items.properties.output.description": "スクリプト出力を出力する場所を定義します。デフォルトは通知ですが、エディターパネルに表示するように指定できます。",
"setting.frontMatter.custom.scripts.items.properties.nodeBin.description": "実行可能なNode.jsへのパス。これは、NVMを使用する際に、Node.jsのバージョンが混同されないようにするために必要です。(非推奨: 代わりにコマンドプロパティを使用してください)",
"setting.frontMatter.custom.scripts.items.properties.bulk.description": "全ての記事ファイルに対してスクリプトを実行する",
"setting.frontMatter.custom.scripts.items.properties.output.description": "スクリプト出力を出力する場所を定義します。デフォルトは通知表示ですが、エディターパネルに表示するように指定できます。",
"setting.frontMatter.custom.scripts.items.properties.outputType.description": "エディター・パネルの出力のタイプ。たとえば、「マークダウン」に変更するために使用できます",
"setting.frontMatter.custom.scripts.items.properties.type.description": "スクリプトが使用される型。",
"setting.frontMatter.custom.scripts.items.properties.command.description": "実行するスクリプトの種類。",
"setting.frontMatter.custom.scripts.items.properties.hidden.description": "UI からアクションを非表示にする",
"setting.frontMatter.custom.scripts.items.properties.environments.items.properties.type.description": "スクリプトを使用する必要がある環境タイプ",
"setting.frontMatter.custom.scripts.items.properties.environments.items.properties.script.description": "実行するスクリプトへのパス",
"setting.frontMatter.custom.scripts.items.properties.contentTypes.description": "スクリプトを使用する記事タイプを定義します。何も定義されていない場合は、全ての型で使用できます。",
"setting.frontMatter.dashboard.content.pagination.markdownDescription": "ページネーションの有効/無効を設定します。ページ数は最大52まで設定できます。規定値は`16`です。ページ分割を無効にするには`false`を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.content.pagination)",
"setting.frontMatter.dashboard.content.cardTags.markdownDescription": "記事一覧をカード型で表示する際、どのメタデータフィールドをタグとして使うかを指定します。空欄またはnull値の場合、タグは表示されなくなります。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.content.cardtags)",
"setting.frontMatter.dashboard.content.card.fields.state.markdownDescription": "記事一覧をカード型で表示する際、下書き・公開済みのステータスを表示します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.state)",
"setting.frontMatter.dashboard.content.card.fields.date.markdownDescription": "記事一覧をカード型で表示する際、日付を表示します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.date)",
"setting.frontMatter.dashboard.content.card.fields.description.markdownDescription": "記事一覧をカード型で表示する際、どのメタデータフィールドをディスクリプションとして使うかを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.description)",
"setting.frontMatter.dashboard.content.card.fields.title.markdownDescription": "記事一覧をカード型で表示する際、どのメタデータフィールドをタイトルとして使うかを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontMatter.dashboard.content.card.fields.title)",
"setting.frontMatter.dashboard.mediaSnippet.markdownDescription": "カスタムメディア挿入マークアップのスニペットを指定します。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.mediasnippet)",
"setting.frontMatter.dashboard.mediaSnippet.markdownDescription": "カスタムメディア挿入マークアップのスニペットを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.mediasnippet)",
"setting.frontMatter.dashboard.mediaSnippet.items.description": "スニペット内で `{mediaUrl}`, `{caption}`, `{alt}`, `{filename}`, `{mediaHeight}`, `{mediaWidth}` のプレースホルダーを使用して、メディア情報を自動的に挿入します。",
"setting.frontMatter.dashboard.openOnStart.markdownDescription": "VS Codeの起動時にダッシュボードを表示します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.dashboard.openonstart)",
"setting.frontMatter.data.files.markdownDescription": "ウェブサイトに使用するデータのファイルを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.data.files)",
@@ -148,23 +150,24 @@
"setting.frontMatter.global.modes.items.properties.id.description": "モードの ID。",
"setting.frontMatter.global.modes.items.properties.features.description": "モードに使用する機能。",
"setting.frontMatter.global.notifications.markdownDescription": "表示したい通知を設定します。既定では全ての通知が表示されます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.global.notifications)",
"setting.frontMatter.global.disabledNotificaitons.markdownDescription": "表示しない通知を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.global.disablednotifications)",
"setting.frontMatter.global.disabledNotifications.markdownDescription": "これは、Front Matter CMSで無効にできる通知タイプの配列です。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.global.disablednotifications)",
"setting.frontMatter.media.defaultSorting.markdownDescription": "ダッシュボードのメディア一覧での既定の並び順を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.media.defaultsorting)",
"setting.frontMatter.media.supportedMimeTypes.markdownDescription": "メディアファイルでサポートされるMIMEタイプを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.media.supportedmimetypes)",
"setting.frontMatter.panel.freeform.markdownDescription": "未登録のタグ/カテゴリーをタグピッカーに入力することを許可するかどうかを設定します(有効にすると、後で保存するオプションが使えます)。規定値はtrue。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.panel.freeform)",
"setting.frontMatter.panel.freeform.markdownDescription": "未登録のタグ/カテゴリーをタグピッカーに入力可能にするかどうかを設定します(有効にすると、後で保存するオプションが使えます)。規定値はtrue。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.panel.freeform)",
"setting.frontMatter.panel.actions.disabled.markdownDescription": "パネル内で非表示にしたいコマンドを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.panel.actions.disabled)",
"setting.frontMatter.preview.host.markdownDescription": "プレビュー表示に使用するホストのURLを設定します(例:`http://localhost:1313`)。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.preview.host)",
"setting.frontMatter.preview.pathName.markdownDescription": "ホストパスとスラッグの間に追加したいパスを設定します。例えば、パスに`yyyy/MM`などの日付を含めたい場合等に使えます。日付は記事の日付フィールドの値に基づいて生成されます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.preview.pathname)",
"setting.frontMatter.site.baseURL.markdownDescription": "ベースURLを設定します。これはSEOチェックに利用されます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.site.baseurl)",
"setting.frontMatter.taxonomy.alignFilename.markdownDescription": "ファイル生成時にファイル名をスラッグに合わせ[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.alignfilename)",
"setting.frontMatter.taxonomy.alignFilename.markdownDescription": "ファイル生成時にファイル名をスラッグに合わせます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.alignfilename)",
"setting.frontMatter.taxonomy.categories.markdownDescription": "Front Matterで利用するカテゴリーを管理します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.categories)",
"setting.frontMatter.taxonomy.commaSeparatedFields.markdownDescription": "カンマ区切りで配列を管理するフィールド名を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.commaseparatedfields)",
"setting.frontMatter.taxonomy.commaSeparatedFields.items.description": "コンマ区切りの配列として使用するフィールドの名前。",
"setting.frontMatter.taxonomy.contentTypes.markdownDescription": "記事・ページ・その他で利用したい記事タイプを設定します。front matterで正しく`type`が設定されていることを確認してください。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.contenttypes)",
"setting.frontMatter.taxonomy.contentTypes.items.description": "Front Matterで使用するコンテンツタイプを定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.description": "Front Matterで使用する記事タイプを定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.name.description": "フィールドの種類を定義する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fileType.description": "作成するコンテンツの種類を指定します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.description": "コンテンツ タイプのフィールドを定義する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.description": "Front Matterで使用するコンテンツタイプを定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fileType.description": "作成する記事タイプを指定します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.description": "記事タイプのフィールドを定義する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.description": "Front Matterで使用する記事タイプを定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.type.description": "フィールドの種類を定義する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.name.description": "使用するフィールドの名前",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.title.description": "UI に表示するタイトル",
@@ -176,10 +179,10 @@
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.single.description": "単一行フィールドである",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.wysiwyg.description": "WYSIWYG フィールド (HTML 出力) である",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.multiple.description": "複数の値を選択できますか?",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isPreviewImage.description": "画像フィールドをプレビューとして使用できるかどうかを指定します。コンテンツ タイプごとに使用できるプレビュー画像は 1 つだけです。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isPreviewImage.description": "画像フィールドをプレビューとして使用できるかどうかを指定します。記事タイプごとに使用できるプレビュー画像は1つだけです。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.hidden.description": "メタデータ セクションからフィールドを非表示にしますか?",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description": "分類フィールドの ID。「タグ」または「カテゴリ」の値を含めることはできません。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.fileExtensions.description": "ファイル ピッカーで許可するファイル拡張子を指定する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description": "分類フィールドのID。「タグ」または「カテゴリ」の値を含めることはできません。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.fileExtensions.description": "ファイルピッカーで許可するファイル拡張子を指定する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.fieldGroup.description": "'frontMatter.taxonomy.fieldGroups' 設定で定義されているフィールドグループの ID",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataType.description": "'frontMatter.data.types' 設定で定義されているデータ型の ID",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.description": "数値フィールドのオプションを指定する",
@@ -188,6 +191,7 @@
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.max.description": "最大値",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.numberOptions.properties.step.description": "ステップ値",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyLimit.description": "選択する分類の数を制限します。無制限を許可するには 0 に設定します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.singleValueAsString.description": "配列内の要素が1つだけの時、配列ではなく文字列として扱います。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isPublishDate.description": "フィールドが公開日フィールドであるかどうかを指定します",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.isModifiedDate.description": "フィールドが変更日フィールドであるかどうかを指定します",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dataFileId.description": "このフィールドに使用するデータファイルのIDを指定します",
@@ -197,30 +201,31 @@
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.encodeEmoji.description": "フィールドが絵文字をエンコードするかどうかを指定します",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.dateFormat.description": "使用する日付形式を指定する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.required.description": "フィールドが必須かどうかを指定します",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.contentTypeName.description": "コンテンツ タイプを指定して、contentRelationship フィールドのコンテンツをフィルター処理します",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.contentTypeName.description": "記事タイプを指定して、contentRelationship フィールドのコンテンツをフィルター処理します",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.contentTypeValue.description": "コンテンツリレーションシップフィールドに挿入する値を指定します",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.description": "フィールドを表示する条件を指定する",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.fieldRef.description": "使用するフィールド ID",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.operator.description": "使用する演算子",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.value.description": "比較する値",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.caseSensitive.description": "比較で大文字と小文字を区別するかどうかを指定します。デフォルト: ",
"setting.frontMatter.taxonomy.contentTypes.items.properties.pageBundle.description": "新しいコンテンツを作成するときにフォルダーを作成するかどうかを指定します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.previewPath.description": "コンテンツ タイプのカスタム プレビュー パスを定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.template.description": "新しいコンテンツの作成に使用できるオプションのテンプレート。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.postScript.description": "新しいコンテンツの作成後に使用できるオプションのポストスクリプト。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.filePrefix.description": "ファイル名のプレフィックスを定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.defaultFileName.description": "新しいコンテンツを作成するときに使用する既定のファイル名。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.caseSensitive.description": "比較で大文字と小文字を区別するかどうかを指定します。デフォルト: true",
"setting.frontMatter.taxonomy.contentTypes.items.properties.pageBundle.description": "新しい記事を作成するときにフォルダーを作成するかどうかを指定します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.previewPath.description": "記事タイプのカスタム プレビュー パスを定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.template.description": "新しい記事の作成に使用できるオプションのテンプレート。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.postScript.description": "新しい記事の作成後に使用できるオプションのポストスクリプト。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.filePrefix.description": "ファイル名の接頭辞を定義します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.defaultFileName.description": "新しい記事の作成時に使用する既定のファイル名。",
"setting.frontMatter.taxonomy.customTaxonomy.markdownDescription": "カスタムタクソノミーのフィールドデータを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.tags)",
"setting.frontMatter.taxonomy.customTaxonomy.items.properties.id.description": "分類フィールドの ID。「タグ」または「カテゴリ」の値を含めることはできません。",
"setting.frontMatter.taxonomy.customTaxonomy.items.properties.options.description": "選択できるオプション。",
"setting.frontMatter.taxonomy.dateField.markdownDescription": "この設定は、記事の公開日フィールドを定義するために使用されます。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.datefield)",
"setting.frontMatter.taxonomy.dateField.markdownDescription": "この設定は、記事の公開日フィールドを定義するために使用されます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.datefield)",
"setting.frontMatter.taxonomy.dateFormat.markdownDescription": "記事の日付フォーマットを指定します。詳しくは[date-fns formatting](https://date-fns.org/v2.0.1/docs/format)を確認してください。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.dateformat)",
"setting.frontMatter.taxonomy.fieldGroups.markdownDescription": "ブロックフィールドで使用したいフィールドグループを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.fieldgroups)",
"setting.frontMatter.taxonomy.fieldGroups.items.properties.id.description": "フィールドグループの名前",
"setting.frontMatter.taxonomy.fieldGroups.items.properties.labelField.description": "表示値として使用するフィールドの名前",
"setting.frontMatter.taxonomy.frontMatterType.markdownDescription": "front matterの形式を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.frontmattertype)",
"setting.frontMatter.taxonomy.indentArrays.markdownDescription": "front matterメタデータが配列の場合はインデント(字下げ)させます。規定値はtrueです。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.indentarrays)",
"setting.frontMatter.taxonomy.modifiedField.markdownDescription": "この設定は、記事の変更日フィールドを定義するために使用されます。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.modifiedfield)",
"setting.frontMatter.taxonomy.modifiedField.markdownDescription": "この設定は、記事の変更日フィールドを定義するために使用されます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.modifiedfield)",
"setting.frontMatter.taxonomy.quoteStringValues.markdownDescription": "front matterの文字列の値をクォーテーションで囲みます。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.quotestringvalues)",
"setting.frontMatter.taxonomy.noPropertyValueQuotes.markdownDescription": "引用符を付与しないメタデータを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.nopropertyvaluequotes)",
"setting.frontMatter.taxonomy.noPropertyValueQuotes.items.description": "引用符を削除したいプロパティの名前。",
"setting.frontMatter.taxonomy.seoContentLengh.markdownDescription": "最適な記事の長さを指定します。2021年のSEOでは、1,760語から2,400語の間が最も理想的とされています。(-1に設定するとオフになります。)[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.seocontentlengh)",
@@ -237,14 +242,13 @@
"setting.frontMatter.templates.folder.markdownDescription": "テンプレートを保存するフォルダーを設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.templates.folder)",
"setting.frontMatter.templates.prefix.markdownDescription": "新しい記事の作成時、ファイル名に付与する接頭辞を設定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.templates.prefix)",
"setting.frontMatter.dashboard.mediaSnippet.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。メディア スニペットは 'frontMatter.content.snippet' 設定で定義してください。",
"setting.frontMatter.taxonomy.dateField.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。代わりに、コンテンツ タイプの日付フィールドで新しい 'isPublishDate' 設定を使用してください。",
"setting.frontMatter.taxonomy.modifiedField.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。代わりに、コンテンツ タイプの日付フィールドで新しい 'isModifiedDate' 設定を使用してください。",
"setting.frontMatter.global.disabledNotifications.markdownDescription": "これは、Front Matter CMS で無効にできる通知タイプの配列です。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.global.disablednotifications)",
"setting.frontMatter.taxonomy.dateField.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。代わりに、記事タイプの日付フィールドで新しい 'isPublishDate' 設定を使用してください。",
"setting.frontMatter.taxonomy.modifiedField.deprecationMessage": "この設定は非推奨であり、次のメジャーバージョンで削除される予定です。代わりに、記事タイプの日付フィールドで新しい 'isModifiedDate' 設定を使用してください。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "使用するユーザー設定フィールド型の名前を指定します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description": "空の値をクリアするかどうかを指定します。",
"setting.frontMatter.website.host.markdownDescription": "ウェブサイトのホスト URL を指定します。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
"command.frontMatter.settings.refresh": "フロントマター設定の更新",
"setting.frontMatter.config.dynamicFilePath.markdownDescription": "動的構成ファイルへのパスを指定します (例: [[ワークスペース]]/config.js)。[ドキュメントをチェックイン](https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)",
"setting.frontMatter.content.pageFolders.items.properties.disableCreation.description": "フォルダー内の新しいコンテンツの作成を無効にします。",
"setting.frontMatter.custom.scripts.items.properties.contentTypes.description": "スクリプトを使用するコンテンツ タイプを定義します。何も定義されていない場合は、すべての型で使用できます。"
"setting.frontMatter.taxonomy.contentTypes.items.properties.clearEmpty.description": "空の値をクリアするかどうかを指定します。",
"setting.frontMatter.website.host.markdownDescription": "ウェブサイトのホストURLを指定します。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
"command.frontMatter.settings.refresh": "Front Matterの設定の再読み込み",
"setting.frontMatter.config.dynamicFilePath.markdownDescription": "動的構成ファイルへのパスを指定します (例: [[ワークスペース]]/config.js)。[ドキュメントを確認](https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)",
"setting.frontMatter.taxonomy.contentTypes.items.properties.allowAsSubContent.description": "記事をサブコンテンツとして作成可能かどうかを設定します。",
"setting.frontMatter.taxonomy.contentTypes.items.properties.isSubContent.description": "記事をサブコンテンツとして作成するかどうかを設定します。"
}
+5 -2
View File
@@ -225,6 +225,7 @@
"setting.frontMatter.taxonomy.frontMatterType.markdownDescription": "Specify the type of Front Matter to use. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.frontmattertype)",
"setting.frontMatter.taxonomy.indentArrays.markdownDescription": "Specify if arrays in front matter are indented. Default: true. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.indentarrays)",
"setting.frontMatter.taxonomy.modifiedField.markdownDescription": "This setting is used to define the modified date field of your articles. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.modifiedfield)",
"setting.frontMatter.taxonomy.quoteStringValues.markdownDescription": "Specify if you want to quote string values in the front matter. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.quotestringvalues)",
"setting.frontMatter.taxonomy.noPropertyValueQuotes.markdownDescription": "Specify the properties from which quotes need to be removed. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.nopropertyvaluequotes)",
"setting.frontMatter.taxonomy.noPropertyValueQuotes.items.description": "Name of the properties you want to remove quotes from.",
"setting.frontMatter.taxonomy.seoContentLengh.markdownDescription": "Specifies the optimal minimum length for your articles. Between 1,760 words 2,400 is the absolute ideal article length for SEO in 2021. (set to `-1` to turn it off). [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.taxonomy.seocontentlengh)",
@@ -244,8 +245,10 @@
"setting.frontMatter.taxonomy.dateField.deprecationMessage": "This setting is deprecated and will be removed in the next major version. Please use the new `isPublishDate` settings instead in your content types date fields.",
"setting.frontMatter.taxonomy.modifiedField.deprecationMessage": "This setting is deprecated and will be removed in the next major version. Please use the new `isModifiedDate` settings instead in your content types date fields.",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.customType.description": "Specify the name of the custom field type to use.",
"setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description": "Specify if the empty values should be cleared.",
"setting.frontMatter.taxonomy.contentTypes.items.properties.clearEmpty.description": "Specify if the empty values should be cleared.",
"setting.frontMatter.website.host.markdownDescription": "Specify the host URL of your website. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.website.url)",
"command.frontMatter.settings.refresh": "Refresh Front Matter Settings",
"setting.frontMatter.config.dynamicFilePath.markdownDescription": "Specify the path to the dynamic config file (ex: [[workspace]]/config.js). [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)"
"setting.frontMatter.config.dynamicFilePath.markdownDescription": "Specify the path to the dynamic config file (ex: [[workspace]]/config.js). [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.config.dynamicfilepath)",
"setting.frontMatter.taxonomy.contentTypes.items.properties.allowAsSubContent.description": "Specify if the content type can be used as sub content.",
"setting.frontMatter.taxonomy.contentTypes.items.properties.isSubContent.description": "Specify if the content type is sub content."
}
-8237
View File
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -1,5 +1,6 @@
const fs = require('fs');
const path = require('path');
const jsoncParser = require('jsonc-parser');
const camlCase = (str) => {
const words = str.split('.');
@@ -15,12 +16,14 @@ const camlCase = (str) => {
const enFile = fs.readFileSync(path.join(__dirname, '../l10n/bundle.l10n.json'), 'utf8');
// Parse the EN file
const en = JSON.parse(enFile);
const en = jsoncParser.parse(enFile);
const keys = Object.keys(en);
// Create an enum file
const enumFile = fs.createWriteStream(path.join(__dirname, '../src/localization/localization.enum.ts'));
const enumFile = fs.createWriteStream(
path.join(__dirname, '../src/localization/localization.enum.ts')
);
// Write the enum file header
enumFile.write(`export enum LocalizationKey {\n`);
@@ -38,4 +41,4 @@ const camlCase = (str) => {
// Close the enum file
enumFile.close();
})();
})();
+10 -69
View File
@@ -29,74 +29,10 @@ import { NavigationType } from '../dashboardWebView/models';
import { processKnownPlaceholders } from '../helpers/PlaceholderHelper';
import { Position } from 'vscode';
import { SNIPPET } from '../constants/Snippet';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Article {
/**
* Insert taxonomy
*
* @param type
*/
public static async insert(type: TaxonomyType) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
const article = ArticleHelper.getCurrent();
if (!article) {
return;
}
let options: vscode.QuickPickItem[] = [];
const matterProp: string = type === TaxonomyType.Tag ? 'tags' : 'categories';
// Add the selected options to the options array
if (article.data[matterProp]) {
const propData = article.data[matterProp];
if (propData && propData.length > 0) {
options = [...propData]
.filter((p) => p)
.map(
(p) =>
({
label: p,
picked: true
} as vscode.QuickPickItem)
);
}
}
// Add all the known options to the selection list
const crntOptions = (await TaxonomyHelper.get(type)) || [];
if (crntOptions && crntOptions.length > 0) {
for (const crntOpt of crntOptions) {
if (!options.find((o) => o.label === crntOpt)) {
options.push({
label: crntOpt
});
}
}
}
if (options.length === 0) {
Notifications.info(`No ${type === TaxonomyType.Tag ? 'tags' : 'categories'} configured.`);
return;
}
const selectedOptions = await vscode.window.showQuickPick(options, {
placeHolder: `Select your ${type === TaxonomyType.Tag ? 'tags' : 'categories'} to insert`,
canPickMany: true,
ignoreFocusOut: true
});
if (selectedOptions) {
article.data[matterProp] = selectedOptions.map((o) => o.label);
}
ArticleHelper.update(editor, article);
}
/**
* Sets the article date
*/
@@ -117,7 +53,7 @@ export class Article {
ArticleHelper.update(editor, article);
} catch (e) {
Notifications.error(
`Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`
l10n.t(LocalizationKey.commandsArticleSetDateError, `${CONFIG_KEY}${SETTING_DATE_FORMAT}`)
);
}
}
@@ -180,7 +116,7 @@ export class Article {
return cloneArticle;
} catch (e: unknown) {
Notifications.error(
`Something failed while parsing the date format. Check your "${CONFIG_KEY}${SETTING_DATE_FORMAT}" setting.`
l10n.t(LocalizationKey.commandsArticleSetDateError, `${CONFIG_KEY}${SETTING_DATE_FORMAT}`)
);
}
}
@@ -292,7 +228,12 @@ export class Article {
overwrite: false
});
} catch (e: unknown) {
Notifications.error(`Failed to rename file: ${(e as Error).message || e}`);
Notifications.error(
l10n.t(
LocalizationKey.commandsArticleUpdateSlugError,
((e as Error).message || e) as string
)
);
}
}
}
+40 -52
View File
@@ -1,77 +1,65 @@
import { commands, ExtensionContext } from 'vscode';
import { authentication, commands, ExtensionContext } from 'vscode';
import { COMMAND_NAME, CONTEXT } from '../constants';
import { Extension } from '../helpers';
import { Credentials } from '../services/Credentials';
import { Extension, Logger } from '../helpers';
import fetch from 'node-fetch';
import { Dashboard } from './Dashboard';
import { SettingsListener } from '../listeners/panel';
import { PanelProvider } from '../panelWebView/PanelProvider';
export class Backers {
private static creds: Credentials | null = null;
public static async init(context: ExtensionContext) {
Backers.creds = new Credentials();
await Backers.creds.initialize(context, Backers.tryUsernameCheck);
Backers.tryUsernameCheck();
Backers.checkSponsor();
context.subscriptions.push(
commands.registerCommand(COMMAND_NAME.authenticate, async () => {
Backers.tryUsernameCheck();
await authentication.getSession('github', ['read:user'], { createIfNone: true });
Backers.checkSponsor();
})
);
}
public static async tryUsernameCheck() {
try {
const username = await Backers.getUsername();
Backers.validate(username || '');
} catch (e) {
Backers.validate('');
}
}
public static async getUsername() {
const octokit = await Backers.creds?.getOctokit();
const user = await octokit?.users.getAuthenticated();
if (user?.data?.login) {
return user?.data?.login;
}
return;
}
public static async validate(username: string) {
public static async checkSponsor() {
const ext = Extension.getInstance();
const githubAuth = await authentication.getSession('github', ['read:user'], { silent: true });
if (githubAuth && githubAuth.accessToken) {
try {
const isBeta = ext.isBetaVersion();
const response = await fetch(
`https://${isBeta ? `beta.` : ``}frontmatter.codes/api/v2/backers`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
accept: 'application/json'
},
body: JSON.stringify({
token: githubAuth.accessToken
})
}
);
if (!username) {
ext.setState(CONTEXT.backer, undefined, 'global');
}
if (response.ok) {
const prevData = await ext.getState<boolean>(CONTEXT.backer, 'global');
await ext.setState(CONTEXT.backer, true, 'global');
const isBeta = ext.isBetaVersion();
if (!prevData) {
const PanelView = PanelProvider.getInstance();
if (PanelView.visible) {
SettingsListener.getSettings();
}
const response = await fetch(
`https://${isBeta ? `beta.` : ``}frontmatter.codes/api/backers?backer=${username}`
);
if (response.ok) {
const prevData = await ext.getState<boolean>(CONTEXT.backer, 'global');
await ext.setState(CONTEXT.backer, true, 'global');
if (!prevData) {
const PanelView = PanelProvider.getInstance();
if (PanelView.visible) {
SettingsListener.getSettings();
}
if (Dashboard.isOpen) {
Dashboard.reload();
if (Dashboard.isOpen) {
Dashboard.reload();
}
}
} else {
ext.setState(CONTEXT.backer, false, 'global');
}
} catch (e) {
Logger.error(`Failed to check if user is a sponsor: ${(e as Error).message}`);
}
} else {
ext.setState(CONTEXT.backer, false, 'global');
ext.setState(CONTEXT.backer, undefined, 'global');
}
}
}
+4 -2
View File
@@ -1,6 +1,8 @@
import { commands } from 'vscode';
import { COMMAND_NAME, ExtensionState } from '../constants';
import { Extension, Logger, Notifications } from '../helpers';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Cache {
public static async registerCommands() {
@@ -28,9 +30,9 @@ export class Cache {
await ext.setState(ExtensionState.Settings.Extends, undefined, 'workspace', true);
if (showNotification) {
Notifications.info('Cache cleared');
Notifications.info(l10n.t(LocalizationKey.commandsCacheCleared));
} else {
Logger.info('Cache cleared');
Logger.info(l10n.t(LocalizationKey.commandsCacheCleared));
}
}
}
+4 -2
View File
@@ -2,9 +2,11 @@ import { Telemetry } from './../helpers/Telemetry';
import { TelemetryEvent, PreviewCommands, GeneralCommands } from './../constants';
import { join } from 'path';
import { commands, Uri, ViewColumn, window } from 'vscode';
import { Extension, Settings } from '../helpers';
import { Extension } from '../helpers';
import { WebviewHelper } from '@estruyf/vscode';
import { getLocalizationFile } from '../utils/getLocalizationFile';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Chatbot {
/**
@@ -14,7 +16,7 @@ export class Chatbot {
// Create the preview webview
const webView = window.createWebviewPanel(
'frontMatterChatbot',
'Front Matter AI - Ask me anything',
`Front Matter AI - ${l10n.t(LocalizationKey.commandsChatbotTitle)}`,
{
viewColumn: ViewColumn.Beside,
preserveFocus: true
+8 -6
View File
@@ -1,6 +1,8 @@
import { commands, QuickPickItem, window } from 'vscode';
import { COMMAND_NAME, SETTING_TEMPLATES_ENABLED } from '../constants';
import { Settings } from '../helpers';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Content {
public static async create() {
@@ -12,18 +14,18 @@ export class Content {
const options: QuickPickItem[] = [
{
label: 'Create content by content type',
description: 'Select if you want to create new content by the available content type(s)'
label: l10n.t(LocalizationKey.commandsContentOptionContentTypeLabel),
description: l10n.t(LocalizationKey.commandsContentOptionContentTypeDescription)
},
{
label: 'Create content by template',
description: 'Select if you want to create new content by the available template(s)'
label: l10n.t(LocalizationKey.commandsContentOptionTemplateLabel),
description: l10n.t(LocalizationKey.commandsContentOptionTemplateDescription)
} as QuickPickItem
];
const selectedOption = await window.showQuickPick(options, {
title: 'Create content',
placeHolder: `Select how you want to create your new content`,
title: l10n.t(LocalizationKey.commandsContentQuickPickTitle),
placeHolder: l10n.t(LocalizationKey.commandsContentQuickPickPlaceholder),
canPickMany: false,
ignoreFocusOut: true
});
+5 -2
View File
@@ -7,7 +7,7 @@ import {
} from '../constants';
import { join } from 'path';
import { commands, Uri, ViewColumn, Webview, WebviewPanel, window } from 'vscode';
import { Logger, Settings as SettingsHelper } from '../helpers';
import { DashboardSettings, Logger, Settings as SettingsHelper } from '../helpers';
import { DashboardCommand } from '../dashboardWebView/DashboardCommand';
import { Extension } from '../helpers/Extension';
import { WebviewHelper } from '@estruyf/vscode';
@@ -29,6 +29,8 @@ import {
import { MediaListener as PanelMediaListener } from '../listeners/panel';
import { GitListener, ModeListener } from '../listeners/general';
import { Folders } from './Folders';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Dashboard {
private static webview: WebviewPanel | null = null;
@@ -119,7 +121,7 @@ export class Dashboard {
// Create the preview webview
Dashboard.webview = window.createWebviewPanel(
'frontMatterDashboard',
'FrontMatter Dashboard',
`Front Matter ${l10n.t(LocalizationKey.commandsDashboardTitle)}`,
ViewColumn.One,
{
enableScripts: true,
@@ -158,6 +160,7 @@ export class Dashboard {
Dashboard.isDisposed = true;
Dashboard._viewData = undefined;
PanelMediaListener.getMediaSelection();
DashboardSettings.updateAfterClose();
await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, false);
});
+25 -14
View File
@@ -25,6 +25,8 @@ import { Telemetry } from '../helpers/Telemetry';
import { glob } from 'glob';
import { mkdirAsync } from '../utils/mkdirAsync';
import { existsAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export const WORKSPACE_PLACEHOLDER = `[[workspace]]`;
@@ -57,15 +59,15 @@ export class Folders {
}
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)?`,
title: l10n.t(LocalizationKey.commandsFoldersAddMediaFolderInputBoxTitle),
prompt: l10n.t(LocalizationKey.commandsFoldersAddMediaFolderInputBoxPrompt),
value: startPath,
ignoreFocusOut: true,
placeHolder: `${format(new Date(), `yyyy/MM`)}`
});
if (!folderName) {
Notifications.warning(`No folder name was specified.`);
Notifications.warning(l10n.t(LocalizationKey.commandsFoldersAddMediaFolderNoFolderWarning));
return;
}
@@ -126,15 +128,15 @@ export class Folders {
);
if (exists) {
Notifications.warning(`Folder is already registered`);
Notifications.warning(l10n.t(LocalizationKey.commandsFoldersCreateFolderExistsWarning));
return;
}
if (!folderName) {
folderName = await window.showInputBox({
title: `Register folder`,
prompt: `Which name would you like to specify for this folder?`,
placeHolder: `Folder name`,
title: l10n.t(LocalizationKey.commandsFoldersCreateInputTitle),
prompt: l10n.t(LocalizationKey.commandsFoldersCreateInputPrompt),
placeHolder: l10n.t(LocalizationKey.commandsFoldersCreateInputPlaceholder),
value: basename(folder.fsPath),
ignoreFocusOut: true
});
@@ -154,7 +156,7 @@ export class Folders {
folders = uniqBy(folders, (f) => f.path);
await Folders.update(folders);
Notifications.info(`Folder registered`);
Notifications.info(l10n.t(LocalizationKey.commandsFoldersCreateSuccess));
Telemetry.send(TelemetryEvent.registerFolder);
@@ -245,7 +247,9 @@ export class Folders {
if (!projectFolder) {
window
.showWorkspaceFolderPick({
placeHolder: `Please select the main workspace folder for Front Matter to use.`
placeHolder: l10n.t(
LocalizationKey.commandsFoldersGetWorkspaceFolderWorkspaceFolderPickPlaceholder
)
})
.then(async (selectedFolder) => {
if (selectedFolder) {
@@ -378,14 +382,21 @@ export class Folders {
} else {
if (folderPath && !existsSync(folderPath)) {
Notifications.errorShowOnce(
`Folder "${folder.title} (${folder.path})" does not exist. Please remove it from the settings.`,
'Remove folder',
'Create folder'
l10n.t(
LocalizationKey.commandsFoldersGetNotificationErrorTitle,
`${folder.title} (${folder.path})`
),
l10n.t(LocalizationKey.commandsFoldersGetNotificationErrorRemoveAction),
l10n.t(LocalizationKey.commandsFoldersGetNotificationErrorCreateAction)
).then((answer) => {
if (answer === 'Remove folder') {
if (
answer === l10n.t(LocalizationKey.commandsFoldersGetNotificationErrorRemoveAction)
) {
const folders = Folders.get();
Folders.update(folders.filter((f) => f.path !== folder.path));
} else if (answer === 'Create folder') {
} else if (
answer === l10n.t(LocalizationKey.commandsFoldersGetNotificationErrorCreateAction)
) {
mkdirAsync(folderPath as string, { recursive: true });
}
});
+6 -2
View File
@@ -24,6 +24,8 @@ import { WebviewHelper } from '@estruyf/vscode';
import { Folders } from './Folders';
import { ParsedFrontMatter } from '../parsers';
import { getLocalizationFile } from '../utils/getLocalizationFile';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Preview {
public static filePath: string | undefined = undefined;
@@ -71,7 +73,9 @@ export class Preview {
// Create the preview webview
const webView = window.createWebviewPanel(
'frontMatterPreview',
article?.data?.title ? `Preview: ${article?.data?.title}` : 'FrontMatter Preview',
article?.data?.title
? l10n.t(LocalizationKey.commandsPreviewPanelTitle, article?.data.title)
: 'Front Matter Preview',
{
viewColumn: ViewColumn.Beside,
preserveFocus: true
@@ -393,7 +397,7 @@ export class Preview {
const folderNames = crntFolders.map((folder) => folder.title);
const selectedFolderName = await window.showQuickPick(folderNames, {
canPickMany: false,
title: 'Select the folder of the article to preview'
title: l10n.t(LocalizationKey.commandsPreviewAskUserToPickFolderTitle)
});
if (selectedFolderName) {
+10 -4
View File
@@ -21,6 +21,8 @@ import {
} from '../constants';
import { SettingsListener } from '../listeners/dashboard';
import { existsAsync, writeFileAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Project {
private static content = `---
@@ -66,7 +68,7 @@ categories: []
if (sampleTemplate !== undefined) {
await Project.createSampleTemplate();
} else {
Notifications.info('Project initialized successfully.');
Notifications.info(l10n.t(LocalizationKey.commandsProjectInitializeSuccess));
}
// Initialize the media library
@@ -89,10 +91,14 @@ categories: []
} catch (error: unknown) {
const err = error as Error;
Logger.error(`Project::init: ${err?.message || err}`);
Notifications.error(`Sorry, something went wrong - ${err?.message || err}`);
Notifications.errorWithOutput(l10n.t(LocalizationKey.commonError));
}
}
/**
* Project switcher
* @returns
*/
public static async switchProject() {
const projects = Settings.getProjects();
const project = await window.showQuickPick(
@@ -100,7 +106,7 @@ categories: []
{
canPickMany: false,
ignoreFocusOut: true,
title: 'Select a project to switch to'
title: l10n.t(LocalizationKey.commandsProjectSwitchProjectTitle)
}
);
@@ -136,7 +142,7 @@ categories: []
await writeFileAsync(article.fsPath, Project.content, {
encoding: 'utf-8'
});
Notifications.info('Sample template created.');
Notifications.info(l10n.t(LocalizationKey.commandsProjectCreateSampleTemplateInfo));
}
}
+41 -29
View File
@@ -5,6 +5,8 @@ import { EXTENSION_NAME } from '../constants';
import { ArticleHelper, FilesHelper } from '../helpers';
import { FrontMatterParser } from '../parsers';
import { Notifications } from '../helpers/Notifications';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Settings {
/**
@@ -13,11 +15,11 @@ export class Settings {
* @param type
*/
public static async create(type: TaxonomyType) {
const taxonomy = type === TaxonomyType.Tag ? 'tag' : 'category';
const newOption = await vscode.window.showInputBox({
prompt: `Insert the value of the ${
type === TaxonomyType.Tag ? 'tag' : 'category'
} that you want to add to your configuration.`,
placeHolder: `Name of the ${type === TaxonomyType.Tag ? 'tag' : 'category'}`,
prompt: l10n.t(LocalizationKey.commandsFoldersCreateInputPrompt, taxonomy),
placeHolder: l10n.t(LocalizationKey.commandsFoldersCreateInputPlaceholder, taxonomy),
ignoreFocusOut: true
});
@@ -25,9 +27,7 @@ export class Settings {
let options = (await TaxonomyHelper.get(type)) || [];
if (options.find((o) => o === newOption)) {
Notifications.info(
`The provided ${type === TaxonomyType.Tag ? 'tag' : 'category'} already exists.`
);
Notifications.warning(l10n.t(LocalizationKey.commandsSettingsCreateWarning, taxonomy));
return;
}
@@ -35,15 +35,16 @@ export class Settings {
TaxonomyHelper.update(type, options);
// Ask if the new term needs to be added to the page
const addToPage = await vscode.window.showQuickPick(['yes', 'no'], {
canPickMany: false,
placeHolder: `Do you want to add the new ${
type === TaxonomyType.Tag ? 'tag' : 'category'
} to the page?`,
ignoreFocusOut: true
});
const addToPage = await vscode.window.showQuickPick(
[l10n.t(LocalizationKey.commonYes), l10n.t(LocalizationKey.commonNo)],
{
canPickMany: false,
placeHolder: l10n.t(LocalizationKey.commandsSettingsCreateQuickPickPlaceholder, taxonomy),
ignoreFocusOut: true
}
);
if (addToPage && addToPage === 'yes') {
if (addToPage && addToPage === l10n.t(LocalizationKey.commonYes)) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
@@ -54,7 +55,7 @@ export class Settings {
return;
}
const matterProp: string = type === TaxonomyType.Tag ? 'tags' : 'categories';
const matterProp: string = taxonomy;
// Add the selected options to the options array
if (article.data[matterProp]) {
const propData: string[] = article.data[matterProp];
@@ -83,7 +84,7 @@ export class Settings {
vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: `${EXTENSION_NAME}: exporting tags and categories`,
title: l10n.t(LocalizationKey.commandsSettingsExportProgressTitle, EXTENSION_NAME),
cancellable: false
},
async (progress) => {
@@ -146,7 +147,11 @@ export class Settings {
// Done
Notifications.info(
`Export completed. Tags: ${crntTags.length} - Categories: ${crntCategories.length}.`
l10n.t(
LocalizationKey.commandsSettingsExportProgressSuccess,
crntTags.length,
crntCategories.length
)
);
}
);
@@ -157,8 +162,8 @@ export class Settings {
*/
public static async remap() {
const taxType = await vscode.window.showQuickPick(['Tag', 'Category'], {
title: `Remap`,
placeHolder: `What do you want to remap?`,
title: l10n.t(LocalizationKey.commandsSettingsRemapQuickpickTitle),
placeHolder: l10n.t(LocalizationKey.commandsSettingsRemapQuickpickPlaceholder),
canPickMany: false,
ignoreFocusOut: true
});
@@ -168,15 +173,18 @@ export class Settings {
}
const type = taxType === 'Tag' ? TaxonomyType.Tag : TaxonomyType.Category;
const taxonomy = type === TaxonomyType.Tag ? 'tags' : 'categories';
const options = (await TaxonomyHelper.get(type)) || [];
if (!options || options.length === 0) {
Notifications.info(`No ${type === TaxonomyType.Tag ? 'tags' : 'categories'} configured.`);
Notifications.warning(
l10n.t(LocalizationKey.commandsSettingsRemapNoTaxonomyWarning, taxonomy)
);
return;
}
const selectedOption = await vscode.window.showQuickPick(options, {
placeHolder: `Select your ${type === TaxonomyType.Tag ? 'tags' : 'categories'} to insert`,
placeHolder: l10n.t(LocalizationKey.commandsSettingsRemapSelectTaxonomyPlaceholder, taxonomy),
canPickMany: false,
ignoreFocusOut: true
});
@@ -186,19 +194,23 @@ export class Settings {
}
const newOptionValue = await vscode.window.showInputBox({
prompt: `Specify the value of the ${
type === TaxonomyType.Tag ? 'tag' : 'category'
} with which you want to remap "${selectedOption}". Leave the input <blank> if you want to remove the ${
type === TaxonomyType.Tag ? 'tag' : 'category'
} from all articles.`,
placeHolder: `Name of the ${type === TaxonomyType.Tag ? 'tag' : 'category'}`,
prompt: l10n.t(
LocalizationKey.commandsSettingsRemapNewOptionInputPrompt,
taxonomy,
selectedOption
),
placeHolder: l10n.t(LocalizationKey.commandsSettingsRemapNewOptionInputPlaceholder, taxonomy),
ignoreFocusOut: true
});
if (!newOptionValue) {
const deleteAnswer = await vscode.window.showQuickPick(['yes', 'no'], {
canPickMany: false,
placeHolder: `Delete ${selectedOption} ${type === TaxonomyType.Tag ? 'tag' : 'category'}?`,
placeHolder: l10n.t(
LocalizationKey.commandsSettingsRemapDeletePlaceholder,
selectedOption,
taxonomy
),
ignoreFocusOut: true
});
if (deleteAnswer === 'no') {
+12 -5
View File
@@ -1,6 +1,7 @@
import { ParsedFrontMatter } from './../parsers/FrontMatterParser';
import {
CONTEXT,
EXTENSION_NAME,
NOTIFICATION_TYPE,
SETTING_SEO_DESCRIPTION_FIELD,
SETTING_SEO_DESCRIPTION_LENGTH,
@@ -16,6 +17,8 @@ import { DataListener } from '../listeners/panel';
import { commands } from 'vscode';
import { Field } from '../models';
import { Preview } from './Preview';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class StatusListener {
/**
@@ -135,12 +138,13 @@ export class StatusListener {
const diagnostic: vscode.Diagnostic = {
code: '',
message: `This ${fields
.map((f) => f.name)
.join('/')} field is required to contain a value.`,
message: l10n.t(
LocalizationKey.commandsStatusListenerVerifyRequiredFieldsDiagnosticEmptyField,
fields.map((f) => f.name).join('/')
),
range: new vscode.Range(posStart, posEnd),
severity: vscode.DiagnosticSeverity.Error,
source: 'Front Matter'
source: EXTENSION_NAME
};
requiredDiagnostics.push(diagnostic);
@@ -158,7 +162,10 @@ export class StatusListener {
Notifications.showIfNotDisabled(
NOTIFICATION_TYPE.requiredFieldValidation,
'ERROR_ONCE',
`The following fields are required to contain a value: ${fieldsToReport.join(', ')}`
l10n.t(
LocalizationKey.commandsStatusListenerVerifyRequiredFieldsNotificationError,
fieldsToReport.join(', ')
)
);
}
}
+33 -22
View File
@@ -16,6 +16,8 @@ import { PagesListener } from '../listeners/dashboard';
import { extname } from 'path';
import { Telemetry } from '../helpers/Telemetry';
import { writeFileAsync, copyFileAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Template {
/**
@@ -31,27 +33,30 @@ export class Template {
const clonedArticle = Object.assign({}, article);
const titleValue = await vscode.window.showInputBox({
title: `Template title`,
prompt: `What name would you like to give your template?`,
placeHolder: `article`,
title: l10n.t(LocalizationKey.commandsTemplateGenerateInputTitle),
prompt: l10n.t(LocalizationKey.commandsTemplateGenerateInputPrompt),
placeHolder: l10n.t(LocalizationKey.commandsTemplateGenerateInputPlaceholder),
ignoreFocusOut: true
});
if (!titleValue) {
Notifications.warning(`You did not specify a template title.`);
Notifications.warning(l10n.t(LocalizationKey.commandsTemplateGenerateNoTitleWarning));
return;
}
const keepContents = await vscode.window.showQuickPick(['yes', 'no'], {
title: `Keep contents`,
canPickMany: false,
placeHolder: `Do you want to keep the contents for the template?`,
ignoreFocusOut: true
});
const keepContents = await vscode.window.showQuickPick(
[l10n.t(LocalizationKey.commonYes), l10n.t(LocalizationKey.commonNo)],
{
title: l10n.t(LocalizationKey.commandsTemplateGenerateKeepContentsTitle),
placeHolder: l10n.t(LocalizationKey.commandsTemplateGenerateKeepContentsPlaceholder),
canPickMany: false,
ignoreFocusOut: true
}
);
if (!keepContents) {
Notifications.warning(
`You did not pick any of the options for keeping the template its content.`
l10n.t(LocalizationKey.commandsTemplateGenerateKeepContentsNoOptionWarning)
);
return;
}
@@ -60,14 +65,16 @@ export class Template {
const templatePath = Project.templatePath();
if (templatePath) {
const fileContents = ArticleHelper.stringifyFrontMatter(
keepContents === 'no' ? '' : clonedArticle.content,
keepContents === l10n.t(LocalizationKey.commonNo) ? '' : clonedArticle.content,
clonedArticle.data
);
const templateFile = path.join(templatePath.fsPath, `${titleValue}.${fileType}`);
await writeFileAsync(templateFile, fileContents, { encoding: 'utf-8' });
Notifications.info(`Template created and is now available in your ${folder} folder.`);
Notifications.info(
l10n.t(LocalizationKey.commandsTemplateGenerateKeepContentsSuccess, folder)
);
}
}
}
@@ -79,7 +86,7 @@ export class Template {
const folder = Settings.get<string>(SETTING_TEMPLATES_FOLDER);
if (!folder) {
Notifications.warning(`No templates found.`);
Notifications.warning(l10n.t(LocalizationKey.commandsTemplateGetTemplatesWarning));
return;
}
@@ -96,26 +103,28 @@ export class Template {
const contentTypes = ContentType.getAll();
if (!folderPath) {
Notifications.warning(`Incorrect project folder path retrieved.`);
Notifications.warning(l10n.t(LocalizationKey.commandsTemplateCreateFolderPathWarning));
return;
}
const templates = await Template.getTemplates();
if (!templates || templates.length === 0) {
Notifications.warning(`No templates found.`);
Notifications.warning(l10n.t(LocalizationKey.commandsTemplateCreateNoTemplatesWarning));
return;
}
const selectedTemplate = await vscode.window.showQuickPick(
templates.map((t) => path.basename(t.fsPath)),
{
title: `Select a template`,
placeHolder: `Select the content template to use`,
title: l10n.t(LocalizationKey.commandsTemplateCreateSelectTemplateTitle),
placeHolder: l10n.t(LocalizationKey.commandsTemplateCreateSelectTemplatePlaceholder),
ignoreFocusOut: true
}
);
if (!selectedTemplate) {
Notifications.warning(`No template selected.`);
Notifications.warning(
l10n.t(LocalizationKey.commandsTemplateCreateSelectTemplateNoTemplateWarning)
);
return;
}
@@ -127,7 +136,9 @@ export class Template {
// Start the template read
const template = templates.find((t) => t.fsPath.endsWith(selectedTemplate));
if (!template) {
Notifications.warning(`Content template could not be found.`);
Notifications.warning(
l10n.t(LocalizationKey.commandsTemplateCreateSelectTemplateNotFoundWarning)
);
return;
}
@@ -154,7 +165,7 @@ export class Template {
// Update the properties inside the template
let frontMatter = await ArticleHelper.getFrontMatterByPath(newFilePath);
if (!frontMatter) {
Notifications.warning(`Something failed when retrieving the newly created file.`);
Notifications.warning(l10n.t(LocalizationKey.commonError));
return;
}
@@ -185,7 +196,7 @@ export class Template {
vscode.window.showTextDocument(txtDoc);
}
Notifications.info(`Your new content has been created.`);
Notifications.info(l10n.t(LocalizationKey.commandsTemplateCreateSuccess));
Telemetry.send(TelemetryEvent.createContentFromTemplate);
+26 -24
View File
@@ -1,6 +1,8 @@
import { commands, window, Selection, QuickPickItem, TextEditor } from 'vscode';
import { COMMAND_NAME, CONTEXT, SETTING_CONTENT_WYSIWYG } from '../constants';
import { Settings } from '../helpers';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
enum MarkupType {
bold = 1,
@@ -81,45 +83,45 @@ export class Wysiwyg {
commands.registerCommand(COMMAND_NAME.options, async () => {
const qpItems: QuickPickItem[] = [
{
label: '$(list-unordered) Unordered list',
detail: 'Add an unordered list',
label: `$(list-unordered) ${LocalizationKey.commandsWysiwygCommandUnorderedListLabel}`,
detail: LocalizationKey.commandsWysiwygCommandUnorderedListDetail,
alwaysShow: true
},
{
label: '$(list-ordered) Ordered list',
detail: 'Add an ordered list',
label: `$(list-ordered) ${LocalizationKey.commandsWysiwygCommandOrderedListLabel}`,
detail: LocalizationKey.commandsWysiwygCommandOrderedListDetail,
alwaysShow: true
},
{
label: '$(tasklist) Task list',
detail: 'Add a task list',
label: `$(tasklist) ${LocalizationKey.commandsWysiwygCommandTaskListLabel}`,
detail: LocalizationKey.commandsWysiwygCommandTaskListDetail,
alwaysShow: true
},
{
label: '$(code) Code',
detail: 'Add inline code snippet',
label: `$(code) ${LocalizationKey.commandsWysiwygCommandCodeLabel}`,
detail: LocalizationKey.commandsWysiwygCommandCodeDetail,
alwaysShow: true
},
{
label: '$(symbol-namespace) Code block',
detail: 'Add a code block',
label: `$(symbol-namespace) ${LocalizationKey.commandsWysiwygCommandCodeblockLabel}`,
detail: LocalizationKey.commandsWysiwygCommandCodeblockDetail,
alwaysShow: true
},
{
label: '$(quote) Blockquote',
detail: 'Add a blockquote',
label: `$(quote) ${LocalizationKey.commandsWysiwygCommandBlockquoteLabel}`,
detail: LocalizationKey.commandsWysiwygCommandBlockquoteDetail,
alwaysShow: true
},
{
label: '$(symbol-text) Strikethrough',
detail: 'Add a strikethrough',
label: `$(symbol-text) ${LocalizationKey.commandsWysiwygCommandStrikethroughLabel}`,
detail: LocalizationKey.commandsWysiwygCommandStrikethroughDetail,
alwaysShow: true
}
];
const option = await window.showQuickPick([...qpItems], {
title: 'WYSIWYG Options',
placeHolder: 'Which type of markup would you like to insert?',
title: l10n.t(LocalizationKey.commandsWysiwygQuickPickTitle),
placeHolder: l10n.t(LocalizationKey.commandsWysiwygQuickPickPlaceholder),
canPickMany: false,
ignoreFocusOut: true
});
@@ -209,17 +211,17 @@ export class Wysiwyg {
const linkText = hasTextSelection ? editor.document.getText(selection) : '';
const link = await window.showInputBox({
title: 'WYSIWYG Hyperlink',
placeHolder: 'Enter the URL',
prompt: 'Enter the URL',
title: l10n.t(LocalizationKey.commandsWysiwygAddHyperlinkHyperlinkInputTitle),
placeHolder: l10n.t(LocalizationKey.commandsWysiwygAddHyperlinkHyperlinkInputPrompt),
prompt: l10n.t(LocalizationKey.commandsWysiwygAddHyperlinkHyperlinkInputPrompt),
value: linkText,
ignoreFocusOut: true
});
const text = await window.showInputBox({
title: 'WYSIWYG Text',
prompt: 'Enter the text for the hyperlink',
placeHolder: 'Enter the text for the hyperlink',
title: l10n.t(LocalizationKey.commandsWysiwygAddHyperlinkTextInputTitle),
prompt: l10n.t(LocalizationKey.commandsWysiwygAddHyperlinkTextInputPrompt),
placeHolder: l10n.t(LocalizationKey.commandsWysiwygAddHyperlinkTextInputPrompt),
value: linkText,
ignoreFocusOut: true
});
@@ -278,9 +280,9 @@ export class Wysiwyg {
const headingLvl = await window.showQuickPick(
['Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6'],
{
title: 'Heading Level',
title: l10n.t(LocalizationKey.commandsWysiwygInsertTextHeadingInputTitle),
placeHolder: l10n.t(LocalizationKey.commandsWysiwygInsertTextHeadingInputPlaceholder),
canPickMany: false,
placeHolder: 'Which heading level do you want to insert?',
ignoreFocusOut: true
}
);
@@ -1,4 +1,4 @@
import { PlusIcon } from '@heroicons/react/outline';
import { PlusIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { HTMLFieldProps, connectField, filterDOMProps, joinName, useField } from 'uniforms';
import './ListAddField.css';
@@ -1,4 +1,4 @@
import { TrashIcon } from '@heroicons/react/outline';
import { TrashIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { HTMLFieldProps, connectField, filterDOMProps, joinName, useField } from 'uniforms';
import './ListDelField.css';
+1 -1
View File
@@ -3,7 +3,7 @@ import { ContentType } from './../models/PanelSettings';
export const DEFAULT_CONTENT_TYPE_NAME = 'default';
export const DEFAULT_CONTENT_TYPE: ContentType = {
name: 'default',
name: DEFAULT_CONTENT_TYPE_NAME,
pageBundle: false,
previewPath: null,
fields: [
+2 -1
View File
@@ -6,6 +6,7 @@ export const CONTEXT = {
wysiwyg: 'frontMatter:markdown:wysiwyg',
backer: 'frontMatter:backers:supporter',
isValidFile: 'frontMatter:file:isValid',
isDevelopment: 'frontMatter:isDevelopment',
hasViewModes: 'frontMatter:has:modes',
@@ -14,5 +15,5 @@ export const CONTEXT = {
isGitEnabled: 'frontMatter:git:enabled',
projectSwitchEnabled: 'frontMatter:project:switch:enabled',
projectSwitchEnabled: 'frontMatter:project:switch:enabled'
};
+2 -1
View File
@@ -1,4 +1,4 @@
export const EXTENSION_NAME = '𝖥𝗋𝗈𝗇𝗍 𝖬𝖺𝗍𝗍𝖾𝗋 𝖢𝖬𝖲';
export const EXTENSION_NAME = 'Front Matter CMS';
export const CONFIG_KEY = 'frontMatter';
@@ -29,6 +29,7 @@ export const SETTING_SLUG_UPDATE_FILE_NAME = 'taxonomy.alignFilename';
export const SETTING_INDENT_ARRAY = 'taxonomy.indentArrays';
export const SETTING_REMOVE_QUOTES = 'taxonomy.noPropertyValueQuotes';
export const SETTING_QUOTE_STRINGS = 'taxonomy.quoteStringValues';
export const SETTING_FRONTMATTER_TYPE = 'taxonomy.frontMatterType';
+3
View File
@@ -4,6 +4,7 @@ export enum DashboardMessage {
setPageViewType = 'setPageViewType',
getMode = 'getMode',
showWarning = 'showWarning',
openConfig = 'openConfig',
// Project switching
switchProject = 'switchProject',
@@ -63,11 +64,13 @@ export enum DashboardMessage {
createTaxonomy = 'createTaxonomy',
importTaxonomy = 'importTaxonomy',
moveTaxonomy = 'moveTaxonomy',
mapTaxonomy = 'mapTaxonomy',
// Other
getTheme = 'getTheme',
updateSetting = 'updateSetting',
setState = 'setState',
getState = 'getState',
runCustomScript = 'runCustomScript',
sendTelemetry = 'sendTelemetry',
logError = 'logError',
@@ -1,4 +1,4 @@
import { PaperAirplaneIcon } from '@heroicons/react/outline';
import { PaperAirplaneIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useCallback } from 'react';
import useThemeColors from '../../hooks/useThemeColors';
@@ -1,6 +1,6 @@
import * as React from 'react';
import { ThumbDownIcon, ThumbUpIcon } from '@heroicons/react/outline';
import { ThumbDownIcon as ThumbDownSolidIcon, ThumbUpIcon as ThumbUpSolidIcon } from '@heroicons/react/solid';
import { HandThumbDownIcon, HandThumbUpIcon } from '@heroicons/react/24/outline';
import { HandThumbDownIcon as ThumbDownSolidIcon, HandThumbUpIcon as ThumbUpSolidIcon } from '@heroicons/react/24/solid';
import { useCallback } from 'react';
import { useSettingsContext } from '../../providers/SettingsProvider';
@@ -53,7 +53,7 @@ export const Feedback: React.FunctionComponent<IFeedbackProps> = ({
isUpVoted ? (
<ThumbUpSolidIcon className='h-4 w-4 text-[var(--vscode-textLink-foreground)]' />
) : (
<ThumbUpIcon className='h-4 w-4' />
<HandThumbUpIcon className='h-4 w-4' />
)
}
</button>
@@ -64,7 +64,7 @@ export const Feedback: React.FunctionComponent<IFeedbackProps> = ({
isDownVoted ? (
<ThumbDownSolidIcon className='h-4 w-4 text-[var(--vscode-textLink-foreground)]' />
) : (
<ThumbDownIcon className='h-4 w-4' />
<HandThumbDownIcon className='h-4 w-4' />
)
}
</button>
@@ -1,5 +1,4 @@
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
export interface IButtonProps {
secondary?: boolean;
@@ -15,19 +14,14 @@ export const Button: React.FunctionComponent<IButtonProps> = ({
secondary,
children
}: React.PropsWithChildren<IButtonProps>) => {
const { getColors } = useThemeColors();
return (
<button
type="button"
className={`${className || ''
} inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium focus:outline-none rounded ${getColors(
'text-white dark:text-vulcan-500 disabled:bg-gray-500',
'disabled:opacity-50'
)
} ${secondary ?
getColors(`bg-red-300 hover:bg-red-400`, `bg-[var(--vscode-button-secondaryBackground)] text-[--vscode-button-secondaryForeground] hover:bg-[var(--vscode-button-secondaryHoverBackground)]`) :
getColors(`bg-teal-600 hover:bg-teal-700`, `bg-[var(--frontmatter-button-background)] text-[var(--vscode-button-foreground)] hover:bg-[var(--frontmatter-button-hoverBackground)]`)
} inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium focus:outline-none rounded disabled:opacity-50 ${secondary ?
`bg-[var(--vscode-button-secondaryBackground)] text-[--vscode-button-secondaryForeground] hover:bg-[var(--vscode-button-secondaryHoverBackground)]` :
`bg-[var(--frontmatter-button-background)] text-[var(--vscode-button-foreground)] hover:bg-[var(--frontmatter-button-hoverBackground)]`
}
`}
onClick={onClick}
@@ -1,5 +1,5 @@
import { Menu } from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/outline';
import { ChevronDownIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
import { MenuItem, MenuItems } from '../Menu';
@@ -3,18 +3,20 @@ import * as l10n from '@vscode/l10n';
import { messageHandler } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../../../DashboardMessage';
import { AstroCollection } from '../../../../models';
import { Settings } from '../../../models';
import { Settings, Status } from '../../../models';
import { SelectItem } from '../../Steps/SelectItem';
import { LocalizationKey } from '../../../../localization';
export interface IAstroContentTypesProps {
settings: Settings
triggerLoading: (isLoading: boolean) => void;
setStatus: (status: Status) => void;
}
export const AstroContentTypes: React.FunctionComponent<IAstroContentTypesProps> = ({
settings,
triggerLoading
triggerLoading,
setStatus
}: React.PropsWithChildren<IAstroContentTypesProps>) => {
const [collections, setCollections] = React.useState<AstroCollection[]>([]);
@@ -26,12 +28,25 @@ export const AstroContentTypes: React.FunctionComponent<IAstroContentTypesProps>
});
}, []);
React.useEffect(() => {
if (collections.length > 0 && settings?.contentTypes?.length > 0) {
// Find created content types from the collections
const astroCollection = collections.find(c => settings.contentTypes.find((ct) => ct.name === c.name));
if (astroCollection) {
setStatus(Status.Completed);
} else {
setStatus(Status.Active);
}
}
}, [collections, settings.contentTypes])
const generateContentType = (collection: AstroCollection) => {
triggerLoading(true);
messageHandler.request(DashboardMessage.ssgSetAstroContentTypes, {
collection
}).then((result) => {
triggerLoading(false);
setStatus(Status.Completed);
});
}
@@ -1,6 +1,6 @@
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { Menu } from '@headlessui/react';
import { EyeIcon, GlobeIcon, TerminalIcon, TrashIcon } from '@heroicons/react/outline';
import { EyeIcon, GlobeEuropeAfricaIcon, CommandLineIcon, TrashIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { CustomScript, ScriptType } from '../../../models';
import { DashboardMessage } from '../../DashboardMessage';
@@ -112,7 +112,7 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
key={script.title}
title={
<div className="flex items-center">
<TerminalIcon className="mr-2 h-5 w-5 flex-shrink-0" aria-hidden={true} />{' '}
<CommandLineIcon className="mr-2 h-5 w-5 flex-shrink-0" aria-hidden={true} />{' '}
<span>{script.title}</span>
</div>
}
@@ -145,7 +145,7 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
{
settings?.websiteUrl && (
<QuickAction title={l10n.t(LocalizationKey.commonOpenOnWebsite)} onClick={openOnWebsite}>
<GlobeIcon className={`w-4 h-4`} aria-hidden="true" />
<GlobeEuropeAfricaIcon className={`w-4 h-4`} aria-hidden="true" />
</QuickAction>
)
}
@@ -195,7 +195,7 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
<MenuItem
title={
<div className="flex items-center">
<GlobeIcon className="mr-2 h-5 w-5 flex-shrink-0" aria-hidden={true} />{' '}
<GlobeEuropeAfricaIcon className="mr-2 h-5 w-5 flex-shrink-0" aria-hidden={true} />{' '}
<span>{l10n.t(LocalizationKey.commonOpenOnWebsite)}</span>
</div>
}
@@ -1,7 +1,7 @@
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { NavigationType, Page } from '../../models';
import { DashboardViewAtom, SettingsSelector } from '../../state';
import { useRecoilValue } from 'recoil';
import { Page } from '../../models';
import { SettingsSelector } from '../../state';
import { Overview } from './Overview';
import { Spinner } from '../Common/Spinner';
import { SponsorMsg } from '../Layout/SponsorMsg';
@@ -23,13 +23,10 @@ export const Contents: React.FunctionComponent<IContentsProps> = ({
}: React.PropsWithChildren<IContentsProps>) => {
const settings = useRecoilValue(SettingsSelector);
const { pageItems } = usePages(pages);
const [, setView] = useRecoilState(DashboardViewAtom);
const pageFolders = [...new Set(pageItems.map((page) => page.fmFolder))];
useEffect(() => {
setView(NavigationType.Contents);
Messenger.send(DashboardMessage.sendTelemetry, {
event: TelemetryEvent.webviewContentsView
});
@@ -1,5 +1,5 @@
import { Disclosure } from '@headlessui/react';
import { ChevronRightIcon } from '@heroicons/react/solid';
import { ChevronRightIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
import { useCallback, useMemo } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
@@ -1,10 +1,9 @@
import * as React from 'react';
import { useForm } from 'uniforms';
import { SubmitField } from 'uniforms-unstyled';
import useThemeColors from '../../hooks/useThemeColors';
import { Button } from '../Common/Button';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { SubmitField } from '../../../components/uniforms-frontmatter';
export interface IDataFormControlsProps {
model: any | null;
@@ -16,10 +15,9 @@ export const DataFormControls: React.FunctionComponent<IDataFormControlsProps> =
onClear
}: React.PropsWithChildren<IDataFormControlsProps>) => {
const { formRef } = useForm();
const { getColors } = useThemeColors();
return (
<div className={`text-right ${getColors(`border-gray-200 dark:border-vulcan-300`, `border-[var(--frontmatter-border)]`)}`}>
<div className={`text-right border-[var(--frontmatter-border)]`}>
<SubmitField value={model ? `Update` : `Add`} />
<Button
@@ -1,7 +1,7 @@
import * as React from 'react';
import { Header } from '../Header';
import { useRecoilState, useRecoilValue } from 'recoil';
import { DashboardViewAtom, SettingsSelector } from '../../state';
import { useRecoilValue } from 'recoil';
import { SettingsSelector } from '../../state';
import { DataForm } from './DataForm';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { DataFile } from '../../../models/DataFile';
@@ -15,7 +15,7 @@ import { arrayMoveImmutable } from 'array-move';
import { EmptyView } from './EmptyView';
import { Container } from './SortableContainer';
import { SortableItem } from './SortableItem';
import { ChevronRightIcon, DatabaseIcon } from '@heroicons/react/outline';
import { ChevronRightIcon, CircleStackIcon } from '@heroicons/react/24/outline';
import { ToastContainer, toast, Slide } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { DataType } from '../../../models/DataType';
@@ -36,7 +36,6 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
const [dataEntries, setDataEntries] = useState<any | any[] | null>(null);
const settings = useRecoilValue(SettingsSelector);
const { getColors } = useThemeColors();
const [, setView] = useRecoilState(DashboardViewAtom);
const setSchema = (dataFile: DataFile) => {
setSelectedData(dataFile);
@@ -137,7 +136,6 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
}, [selectedData, , dataEntries, selectedIndex]);
useEffect(() => {
setView(NavigationType.Data);
Messenger.listen(messageListener);
Messenger.send(DashboardMessage.sendTelemetry, {
@@ -299,7 +297,7 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
'text-[var(--frontmatter-text)]'
)
}`}>
<DatabaseIcon className="w-32 h-32" />
<CircleStackIcon className="w-32 h-32" />
<p className="text-3xl mt-2">{l10n.t(LocalizationKey.dashboardDataViewDataViewNoDataFiles)}</p>
<p className="text-xl mt-4">
<a
@@ -1,4 +1,4 @@
import { ExclamationCircleIcon } from '@heroicons/react/outline';
import { ExclamationCircleIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
@@ -1,4 +1,4 @@
import { PencilIcon, SelectorIcon, TrashIcon } from '@heroicons/react/outline';
import { PencilIcon, ChevronDownIcon, TrashIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { SortableHandle, SortableElement } from 'react-sortable-hoc';
import useThemeColors from '../../hooks/useThemeColors';
@@ -16,7 +16,7 @@ export interface ISortableItemProps {
onDeleteItem: (index: number) => void;
}
const DragHandle = SortableHandle(() => <SelectorIcon className={`w-6 h-6 cursor-move hover:text-[var(--frontmatter-link-hover)]`} />);
const DragHandle = SortableHandle(() => <ChevronDownIcon className={`w-6 h-6 cursor-move hover:text-[var(--frontmatter-link-hover)]`} />);
export const SortableItem = SortableElement(
({
@@ -1,4 +1,4 @@
import { ExclamationIcon } from '@heroicons/react/solid';
import { ExclamationTriangleIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
@@ -13,7 +13,7 @@ export const ErrorView: React.FunctionComponent<IErrorViewProps> = (
return (
<main className={`h-full w-full flex flex-col justify-center items-center space-y-2`}>
<ExclamationIcon className={`w-24 h-24 ${getColors(`text-red-500`, `text-[var(--vscode-editorError-foreground)]`)}`} />
<ExclamationTriangleIcon className={`w-24 h-24 ${getColors(`text-red-500`, `text-[var(--vscode-editorError-foreground)]`)}`} />
<p className="text-xl">{l10n.t(LocalizationKey.commonErrorMessage)}</p>
<p className="text-base">{l10n.t(LocalizationKey.dashboardErrorViewDescription)}</p>
</main>
@@ -1,4 +1,4 @@
import { CollectionIcon } from '@heroicons/react/outline';
import { HomeModernIcon } from '@heroicons/react/24/outline';
import { basename, join } from 'path';
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
@@ -91,7 +91,7 @@ export const Breadcrumb: React.FunctionComponent<IBreadcrumbProps> = (
`text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]`
)}
>
<CollectionIcon className="flex-shrink-0 h-5 w-5" aria-hidden="true" />
<HomeModernIcon className="flex-shrink-0 h-5 w-5" aria-hidden="true" />
<span className="sr-only">{l10n.t(LocalizationKey.dashboardHeaderBreadcrumbHome)}</span>
</button>
</div>
@@ -1,4 +1,4 @@
import { XCircleIcon } from '@heroicons/react/solid';
import { XCircleIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
import { useRecoilValue, useResetRecoilState } from 'recoil';
import {
@@ -1,5 +1,5 @@
import { Menu } from '@headlessui/react';
import { FilterIcon } from '@heroicons/react/solid';
import { FunnelIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
import { MenuButton, MenuItem, MenuItems } from '../Menu';
import * as l10n from '@vscode/l10n';
@@ -30,7 +30,7 @@ export const Filter: React.FunctionComponent<IFilterProps> = ({
<MenuButton
label={
<>
<FilterIcon className={`inline-block w-5 h-5 mr-1`} />
<FunnelIcon className={`inline-block w-5 h-5 mr-1`} />
<span>{label}</span>
</>
}
@@ -1,4 +1,4 @@
import { SearchIcon, XCircleIcon } from '@heroicons/react/solid';
import { MagnifyingGlassIcon, XCircleIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
@@ -31,7 +31,7 @@ export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({
</label>
<div className="relative flex justify-center">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<SearchIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
<MagnifyingGlassIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
</div>
<input
@@ -16,7 +16,7 @@ import { ChoiceButton } from '../Common/ChoiceButton';
import { MediaHeaderBottom } from '../Media/MediaHeaderBottom';
import { Tabs } from './Tabs';
import { CustomScript } from '../../../models';
import { LightningBoltIcon, PlusIcon } from '@heroicons/react/outline';
import { BoltIcon, PlusIcon } from '@heroicons/react/24/outline';
import { useLocation, useNavigate } from 'react-router-dom';
import { routePaths } from '../..';
import { useEffect, useMemo } from 'react';
@@ -81,7 +81,7 @@ export const Header: React.FunctionComponent<IHeaderProps> = ({
.map((s, idx) => ({
title: (
<div key={idx} className="flex items-center">
<LightningBoltIcon className="w-4 h-4 mr-2" />
<BoltIcon className="w-4 h-4 mr-2" />
<span>{s.title}</span>
</div>
),
@@ -1,6 +1,6 @@
import { messageHandler } from '@estruyf/vscode/dist/client';
import { Menu } from '@headlessui/react';
import { SwitchHorizontalIcon } from '@heroicons/react/outline';
import { ArrowsRightLeftIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useRecoilValue } from 'recoil';
import { DashboardMessage } from '../../DashboardMessage';
@@ -37,7 +37,7 @@ export const ProjectSwitcher: React.FunctionComponent<IProjectSwitcherProps> = (
<MenuButton
label={(
<div className="inline-flex items-center">
<SwitchHorizontalIcon className="h-4 w-4 mr-2" />
<ArrowsRightLeftIcon className="h-4 w-4 mr-2" />
<span>{l10n.t(LocalizationKey.dashboardHeaderProjectSwitcherLabel)}</span>
</div>
)}
@@ -1,5 +1,5 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { RefreshIcon } from '@heroicons/react/outline';
import { ArrowPathIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useCallback } from 'react';
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil';
@@ -67,7 +67,7 @@ export const RefreshDashboardData: React.FunctionComponent<IRefreshDashboardData
title={l10n.t(LocalizationKey.dashboardHeaderRefreshDashboardLabel)}
onClick={refresh}
>
<RefreshIcon className={`h-5 w-5`} />
<ArrowPathIcon className={`h-5 w-5`} />
<span className="sr-only">{l10n.t(LocalizationKey.dashboardHeaderRefreshDashboardLabel)}</span>
</button>
);
@@ -1,4 +1,4 @@
import { SearchIcon, XCircleIcon } from '@heroicons/react/solid';
import { MagnifyingGlassIcon, XCircleIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useDebounce } from '../../../hooks/useDebounce';
@@ -48,7 +48,7 @@ export const Searchbox: React.FunctionComponent<ISearchboxProps> = ({
</label>
<div className="relative flex justify-center">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<SearchIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
<MagnifyingGlassIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
</div>
<input
@@ -1,4 +1,4 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { Menu } from '@headlessui/react';
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
@@ -26,6 +26,7 @@ export const Sorting: React.FunctionComponent<ISortingProps> = ({
const [crntSorting, setCrntSorting] = useRecoilState(SortingAtom);
const searchValue = useRecoilValue(SearchSelector);
const settings = useRecoilValue(SettingsSelector);
const [crntSort, setCrntSort] = React.useState<SortingOption | null>(null);
const sortOptions: SortingOption[] = [
{
@@ -143,29 +144,37 @@ export const Sorting: React.FunctionComponent<ISortingProps> = ({
];
}
let crntSortingOption = crntSorting;
if (!crntSortingOption) {
if (view === NavigationType.Contents) {
crntSortingOption = settings?.dashboardState?.contents?.sorting || null;
} else if (view === NavigationType.Media) {
crntSortingOption = settings?.dashboardState?.media?.sorting || null;
}
React.useEffect(() => {
const getSorting = async () => {
let crntSortingOption = crntSorting;
if (!crntSortingOption) {
const sortingState = await messageHandler.request<{ key: string; value: SortingOption; }>(DashboardMessage.getState, { key: view === NavigationType.Media ? ExtensionState.Dashboard.Media.Sorting : ExtensionState.Dashboard.Contents.Sorting });
crntSortingOption = sortingState?.value || null;
if (crntSortingOption === null) {
if (view === NavigationType.Contents && settings?.dashboardState.contents.defaultSorting) {
crntSortingOption =
allOptions.find((f) => f.id === settings?.dashboardState.contents.defaultSorting) || null;
} else if (
view === NavigationType.Media &&
settings?.dashboardState.contents.defaultSorting
) {
crntSortingOption =
allOptions.find((f) => f.id === settings?.dashboardState.contents.defaultSorting) || null;
if (crntSortingOption === null) {
if (view === NavigationType.Contents && settings?.dashboardState.contents.defaultSorting) {
crntSortingOption =
allOptions.find((f) => f.id === settings?.dashboardState.contents.defaultSorting) || null;
} else if (
view === NavigationType.Media &&
settings?.dashboardState.media.defaultSorting
) {
crntSortingOption =
allOptions.find((f) => f.id === settings?.dashboardState.media.defaultSorting) || null;
}
}
}
}
}
let crntSort = allOptions.find((x) => x.id === crntSortingOption?.id) || sortOptions[0];
let sort = allOptions.find((x) => x.id === crntSortingOption?.id) || sortOptions[0];
setCrntSort(sort);
};
getSorting();
}, [crntSorting]);
if (crntSort === null) {
return null;
}
return (
<div className="flex items-center">
@@ -1,6 +1,6 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { EventData } from '@estruyf/vscode/dist/models';
import { RefreshIcon } from '@heroicons/react/outline';
import { ArrowPathIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useEffect, useState } from 'react';
import { useRecoilValue } from 'recoil';
@@ -57,7 +57,7 @@ export const SyncButton: React.FunctionComponent<ISyncButtonProps> = (
onClick={pull}
disabled={isSyncing}
>
<RefreshIcon
<ArrowPathIcon
className={`w-4 h-4 mr-2 ${isSyncing ? 'animate-reverse-spin' : ''}`}
aria-hidden="true"
/>
@@ -1,4 +1,4 @@
import { DatabaseIcon, PhotographIcon, ScissorsIcon, TagIcon } from '@heroicons/react/outline';
import { CircleStackIcon, PhotoIcon, ScissorsIcon, TagIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useRecoilValue } from 'recoil';
import { FeatureFlag } from '../../../components/features/FeatureFlag';
@@ -33,7 +33,7 @@ export const Tabs: React.FunctionComponent<ITabsProps> = ({
</li>
<li className="mr-2" role="presentation">
<Tab navigationType={NavigationType.Media} onNavigate={onNavigate}>
<PhotographIcon className={`h-6 w-auto mr-2`} />
<PhotoIcon className={`h-6 w-auto mr-2`} />
<span>{l10n.t(LocalizationKey.dashboardHeaderTabsMedia)}</span>
</Tab>
</li>
@@ -48,7 +48,7 @@ export const Tabs: React.FunctionComponent<ITabsProps> = ({
<FeatureFlag features={mode?.features || []} flag={FEATURE_FLAG.dashboard.data.view}>
<li className="mr-2" role="presentation">
<Tab navigationType={NavigationType.Data} onNavigate={onNavigate}>
<DatabaseIcon className={`h-6 w-auto mr-2`} />
<CircleStackIcon className={`h-6 w-auto mr-2`} />
<span>{l10n.t(LocalizationKey.dashboardHeaderTabsData)}</span>
</Tab>
</li>
@@ -1,7 +1,7 @@
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { ViewAtom, SettingsSelector } from '../../state';
import { ViewListIcon, ViewGridIcon } from '@heroicons/react/solid';
import { Bars4Icon, Squares2X2Icon } from '@heroicons/react/24/solid';
import { Messenger } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../../DashboardMessage';
import { DashboardViewType } from '../../models';
@@ -40,7 +40,7 @@ export const ViewSwitch: React.FunctionComponent<IViewSwitchProps> = (
type={`button`}
onClick={toggleView}
>
<ViewGridIcon className={`w-4 h-4`} />
<Squares2X2Icon className={`w-4 h-4`} />
<span className={`sr-only`}>
{l10n.t(LocalizationKey.dashboardHeaderViewSwitchToGrid)}
</span>
@@ -52,7 +52,7 @@ export const ViewSwitch: React.FunctionComponent<IViewSwitchProps> = (
type={`button`}
onClick={toggleView}
>
<ViewListIcon className={`w-4 h-4`} />
<Bars4Icon className={`w-4 h-4`} />
<span className={`sr-only`}>
{l10n.t(LocalizationKey.dashboardHeaderViewSwitchToList)}
</span>
@@ -1,4 +1,4 @@
import { HeartIcon, StarIcon } from '@heroicons/react/outline';
import { HeartIcon, StarIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { REVIEW_LINK, SPONSOR_LINK } from '../../../constants';
import { VersionInfo } from '../../../models';
@@ -1,5 +1,5 @@
import { Dialog, Transition } from '@headlessui/react';
import { PencilAltIcon, XIcon } from '@heroicons/react/outline';
import { PencilSquareIcon, XMarkIcon } from '@heroicons/react/24/outline';
import { format } from 'date-fns';
import { basename } from 'path';
import * as React from 'react';
@@ -129,7 +129,7 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
onClick={onDismiss}
>
<span className="sr-only">{l10n.t(LocalizationKey.dashboardMediaPanelClose)}</span>
<XIcon className="h-6 w-6" aria-hidden="true" />
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
</div>
@@ -270,7 +270,7 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
<h3 className={`text-base flex items-center text-[var(--vscode-foreground)]`}>
<span>{l10n.t(LocalizationKey.dashboardMediaMetadataPanelFormMetadataTitle)}</span>
<button onClick={onEdit}>
<PencilAltIcon className="w-4 h-4 ml-2" aria-hidden="true" />
<PencilSquareIcon className="w-4 h-4 ml-2" aria-hidden="true" />
<span className="sr-only">{l10n.t(LocalizationKey.commonEdit)}</span>
</button>
</h3>
@@ -1,5 +1,5 @@
import * as React from 'react';
import { FolderAddIcon, LightningBoltIcon } from '@heroicons/react/outline';
import { FolderPlusIcon, BoltIcon } from '@heroicons/react/24/outline';
import { useRecoilValue } from 'recoil';
import { DashboardMessage } from '../../DashboardMessage';
import {
@@ -86,7 +86,7 @@ export const FolderCreation: React.FunctionComponent<IFolderCreationProps> = (
title={l10n.t(LocalizationKey.dashboardMediaFolderCreationHexoCreate)}
onClick={onAssetFolderCreation}
>
<FolderAddIcon className={`mr-2 h-6 w-6`} />
<FolderPlusIcon className={`mr-2 h-6 w-6`} />
<span className={``}>{l10n.t(LocalizationKey.dashboardMediaFolderCreationHexoCreate)}</span>
</button>
);
@@ -102,7 +102,7 @@ export const FolderCreation: React.FunctionComponent<IFolderCreationProps> = (
title={l10n.t(LocalizationKey.dashboardMediaFolderCreationFolderCreate)}
choices={scripts.map((s) => ({
title: s.title,
icon: <LightningBoltIcon className="w-4 h-4 mr-2" />,
icon: <BoltIcon className="w-4 h-4 mr-2" />,
onClick: () => runCustomScript(s)
}))}
onClick={onFolderCreation}
@@ -124,7 +124,7 @@ export const FolderCreation: React.FunctionComponent<IFolderCreationProps> = (
title={l10n.t(LocalizationKey.dashboardMediaFolderCreationFolderCreate)}
onClick={onFolderCreation}
>
<FolderAddIcon className={`mr-2 h-6 w-6`} />
<FolderPlusIcon className={`mr-2 h-6 w-6`} />
<span className={``}>{l10n.t(LocalizationKey.dashboardMediaFolderCreationFolderCreate)}</span>
</button>
</div>
@@ -1,4 +1,4 @@
import { FolderIcon } from '@heroicons/react/solid';
import { FolderIcon } from '@heroicons/react/24/solid';
import { basename, join } from 'path';
import * as React from 'react';
import { useRecoilState } from 'recoil';
+12 -12
View File
@@ -2,17 +2,17 @@ import { Messenger } from '@estruyf/vscode/dist/client';
import { Menu } from '@headlessui/react';
import {
ClipboardIcon,
CodeIcon,
CodeBracketIcon,
DocumentIcon,
EyeIcon,
MusicNoteIcon,
MusicalNoteIcon,
PencilIcon,
PhotographIcon,
PhotoIcon,
PlusIcon,
TerminalIcon,
CommandLineIcon,
TrashIcon,
VideoCameraIcon
} from '@heroicons/react/outline';
} from '@heroicons/react/24/outline';
import { basename, dirname } from 'path';
import * as React from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
@@ -315,7 +315,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
key={script.title}
title={
<div className="flex items-center">
<TerminalIcon className="mr-2 h-5 w-5 flex-shrink-0" aria-hidden={true} />{' '}
<CommandLineIcon className="mr-2 h-5 w-5 flex-shrink-0" aria-hidden={true} />{' '}
<span>{script.title}</span>
</div>
}
@@ -361,7 +361,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
}
if (isImageFile) {
return <PhotographIcon className={`h-1/2 ${colors}`} />;
return <PhotoIcon className={`h-1/2 ${colors}`} />;
}
if (isVideoFile) {
@@ -369,7 +369,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
}
if (isAudioFile) {
icon = <MusicNoteIcon className={`h-4/6 ${colors}`} />;
icon = <MusicalNoteIcon className={`h-4/6 ${colors}`} />;
}
return (
@@ -471,7 +471,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
className={`h-1/3 text-white hover:text-[var(--vscode-button-background)]`}
onClick={insertSnippet}
>
<CodeIcon
<CodeBracketIcon
className={`w-full h-full hover:drop-shadow-md `}
aria-hidden="true"
/>
@@ -513,7 +513,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
{viewData?.data?.position && mediaSnippets.length > 0 && (
<QuickAction title={l10n.t(LocalizationKey.commonInsertSnippet)} onClick={insertSnippet}>
<CodeIcon className={`w-4 h-4`} aria-hidden="true" />
<CodeBracketIcon className={`w-4 h-4`} aria-hidden="true" />
</QuickAction>
)}
</>
@@ -570,7 +570,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
key={idx}
title={
<div className="flex items-center">
<CodeIcon
<CodeBracketIcon
className="mr-2 h-5 w-5 flex-shrink-0"
aria-hidden={true}
/>{' '}
@@ -668,7 +668,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
{showSnippetSelection && (
<InfoDialog
icon={<CodeIcon className="h-6 w-6" aria-hidden="true" />}
icon={<CodeBracketIcon className="h-6 w-6" aria-hidden="true" />}
title={l10n.t(LocalizationKey.commonInsertSnippet)}
description={l10n.t(LocalizationKey.dashboardMediaItemInfoDialogSnippetDescription)}
dismiss={() => setShowSnippetSelection(false)}
@@ -1,9 +1,8 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { UploadIcon } from '@heroicons/react/outline';
import { ArrowUpTrayIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useRecoilValue } from 'recoil';
import {
DashboardViewAtom,
LoadingAtom,
MediaFoldersAtom,
SelectedMediaFolderAtom,
@@ -43,7 +42,6 @@ export const Media: React.FunctionComponent<IMediaProps> = (
const folders = useRecoilValue(MediaFoldersAtom);
const loading = useRecoilValue(LoadingAtom);
const { getColors } = useThemeColors();
const [, setView] = useRecoilState(DashboardViewAtom);
const currentStaticFolder = useMemo(() => {
if (settings?.staticFolder) {
@@ -153,7 +151,6 @@ export const Media: React.FunctionComponent<IMediaProps> = (
);
useEffect(() => {
setView(NavigationType.Media);
Messenger.send(DashboardMessage.sendTelemetry, {
event: TelemetryEvent.webviewMediaView
});
@@ -185,7 +182,7 @@ export const Media: React.FunctionComponent<IMediaProps> = (
'text-[var(--vscode-foreground)] bg-[var(--vscode-editor-background)] opacity-75'
)
}`}>
<UploadIcon className={`h-32`} />
<ArrowUpTrayIcon className={`h-32`} />
<p className={`text-xl max-w-md text-center`}>
{selectedFolder
? l10n.t(LocalizationKey.dashboardMediaMediaFolderUpload, selectedFolder)
@@ -1,5 +1,5 @@
import { Dialog, Transition } from '@headlessui/react';
import { XIcon } from '@heroicons/react/outline';
import { XMarkIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { Fragment, useRef } from 'react';
import * as l10n from '@vscode/l10n';
@@ -58,7 +58,7 @@ export const SnippetSlideOver: React.FunctionComponent<ISnippetSlideOverProps> =
onClick={dismiss}
>
<span className="sr-only">{l10n.t(LocalizationKey.dashboardMediaPanelClose)}</span>
<XIcon className="h-6 w-6" aria-hidden="true" />
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
</div>
@@ -1,5 +1,5 @@
import { Menu } from '@headlessui/react';
import { DotsVerticalIcon } from '@heroicons/react/outline';
import { EllipsisVerticalIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
@@ -19,18 +19,17 @@ export const ActionMenuButton: React.FunctionComponent<IActionMenuButtonProps> =
return (
<Menu.Button
ref={ref || null}
onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.stopPropagation()}
disabled={disabled}
className={`group inline-flex justify-center text-sm font-medium ${
getColors(
'text-vulcan-400 hover:text-vulcan-600 dark:text-gray-400 dark:hover:text-whisper-600',
'text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]'
)
} ${
disabled ? 'opacity-50' : ''
}`}
className={`group inline-flex justify-center text-sm font-medium ${getColors(
'text-vulcan-400 hover:text-vulcan-600 dark:text-gray-400 dark:hover:text-whisper-600',
'text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]'
)
} ${disabled ? 'opacity-50' : ''
}`}
>
<span className="sr-only">{title}</span>
<DotsVerticalIcon className="w-4 h-4" aria-hidden="true" />
<EllipsisVerticalIcon className="w-4 h-4" aria-hidden="true" />
</Menu.Button>
);
};
@@ -1,5 +1,5 @@
import { Menu } from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/solid';
import { ChevronDownIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
@@ -1,5 +1,5 @@
import { Dialog, Transition } from '@headlessui/react';
import { ExclamationIcon } from '@heroicons/react/outline';
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { Fragment, useRef } from 'react';
import useThemeColors from '../../hooks/useThemeColors';
@@ -74,7 +74,7 @@ export const Alert: React.FunctionComponent<IAlertProps> = ({
'bg-[var(--vscode-sidebar-background)]'
)
}`}>
<ExclamationIcon
<ExclamationTriangleIcon
className={`h-6 w-6 ${getColors(`text-red-500 dark:text-red-50`, `text-[var(--vscode-errorForeground)]`)}`}
aria-hidden="true"
/>
@@ -1,7 +1,6 @@
import { Dialog, Transition } from '@headlessui/react';
import * as React from 'react';
import { Fragment } from 'react';
import useThemeColors from '../../hooks/useThemeColors';
export interface IInfoDialogProps {
icon?: JSX.Element;
@@ -17,7 +16,6 @@ export const InfoDialog: React.FunctionComponent<IInfoDialogProps> = ({
description,
children
}: React.PropsWithChildren<IInfoDialogProps>) => {
const { getColors } = useThemeColors();
return (
<Transition.Root show={true} as={Fragment}>
@@ -32,11 +30,7 @@ export const InfoDialog: React.FunctionComponent<IInfoDialogProps> = ({
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className={`fixed inset-0 transition-opacity ${getColors(
`bg-vulcan-500 bg-opacity-75`,
`bg-[var(--vscode-editor-background)] opacity-75`
)
}`} />
<Dialog.Overlay className={`fixed inset-0 transition-opacity bg-[var(--vscode-editor-background)] opacity-75`} />
</Transition.Child>
{/* This element is to trick the browser into centering the modal contents. */}
@@ -53,31 +47,22 @@ export const InfoDialog: React.FunctionComponent<IInfoDialogProps> = ({
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div className={`inline-block align-bottom rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6 border-2 ${getColors(
`bg-white dark:bg-vulcan-500 border-whisper-900`,
`bg-[var(--vscode-editor-background)] border-[var(--frontmatter-border)]`
)
}`}>
<div className={`inline-block align-bottom rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6 border-2 bg-[var(--vscode-editor-background)] border-[var(--frontmatter-border)]`}>
<div className="sm:flex sm:items-start">
{icon && (
<div className={`mt-3 sm:mr-4 mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full sm:mx-0 sm:h-10 sm:w-10 ${getColors(
`bg-gray-50 dark:bg-vulcan-400`,
`bg-[var(--vscode-sidebar-background)]'`
)
}`}>
<div className={`mt-3 sm:mr-4 mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full sm:mx-0 sm:h-10 sm:w-10 bg-[var(--vscode-sidebar-background)]`}>
{icon}
</div>
)}
<div className="mt-3 text-center sm:mt-0 sm:text-left">
<Dialog.Title
as="h3"
className={`text-lg leading-6 font-medium ${getColors(`text-vulcan-300 dark:text-whisper-900`, `text-[var(--vscode-editor-foreground)]`)
}`}
className={`text-lg leading-6 font-medium text-[var(--vscode-editor-foreground)]`}
>
{title}
</Dialog.Title>
<div className="mt-2">
<p className={`text-sm ${getColors(`text-vulcan-500 dark:text-whisper-500`, `text-[var(--vscode-editor-foreground)]`)}`}>{description}</p>
<p className={`text-sm text-[var(--vscode-editor-foreground)]`}>{description}</p>
</div>
</div>
</div>
@@ -1,5 +1,5 @@
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { ArrowRightIcon, ExternalLinkIcon, RefreshIcon } from '@heroicons/react/outline';
import { ArrowRightIcon, ArrowTopRightOnSquareIcon, ArrowPathIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
import { GeneralCommands, PreviewCommands } from '../../../constants';
@@ -101,14 +101,14 @@ export const Preview: React.FunctionComponent<IPreviewProps> = ({
title={l10n.t(LocalizationKey.dashboardPreviewButtonRefreshTitle)}
onClick={onRefresh}
className={`mr-2 ${getColors(`hover:text-vulcan-500 dark:hover:text-whisper-100`, `hover:text-[var(--vscode-textLink-activeForeground)]`)}`}>
<RefreshIcon className="w-4 h-4" aria-hidden="true" />
<ArrowPathIcon className="w-4 h-4" aria-hidden="true" />
</button>
<button
title={l10n.t(LocalizationKey.dashboardPreviewButtonOpenTitle)}
onClick={openInBrowser}
className={`mr-2 ${getColors(`hover:text-vulcan-500 dark:hover:text-whisper-100`, `hover:text-[var(--vscode-textLink-activeForeground)]`)}`}>
<ExternalLinkIcon className="w-4 h-4" aria-hidden="true" />
<ArrowTopRightOnSquareIcon className="w-4 h-4" aria-hidden="true" />
</button>
</div>
)
@@ -1,7 +1,7 @@
import * as React from 'react';
import { useRecoilValue } from 'recoil';
import { SettingsSelector } from '../../state';
import { CogIcon } from '@heroicons/react/solid';
import { CogIcon } from '@heroicons/react/24/solid';
import { NavigationType } from '../../models';
export interface ISettingsLinkProps {
@@ -9,7 +9,7 @@ import { ContentFolders } from '../Configuration/Common/ContentFolders';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { COMMAND_NAME } from '../../../constants';
import { RefreshIcon } from '@heroicons/react/outline';
import { ArrowPathIcon } from '@heroicons/react/24/outline';
import { VSCodePanelTab, VSCodePanelView, VSCodePanels } from '@vscode/webview-ui-toolkit/react';
import { CommonSettings } from './CommonSettings';
@@ -36,7 +36,7 @@ export const SettingsView: React.FunctionComponent<ISettingsViewProps> = (_: Rea
className={`inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium focus:outline-none rounded text-[var(--vscode-button-foreground)] hover:text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`}
href={`command:${COMMAND_NAME.settingsRefresh}`}
>
<RefreshIcon
<ArrowPathIcon
className={`w-4 h-4 mr-2`}
aria-hidden="true"
/>
@@ -76,7 +76,8 @@ export const SettingsView: React.FunctionComponent<ISettingsViewProps> = (_: Rea
<AstroContentTypes
settings={settings}
triggerLoading={(isLoading) => setLoading(isLoading)} />
triggerLoading={(isLoading) => setLoading(isLoading)}
setStatus={_ => null} />
</div>
</VSCodePanelView>
)
@@ -1,14 +1,14 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import {
CodeIcon,
CodeBracketIcon,
DocumentTextIcon,
DotsHorizontalIcon,
EllipsisHorizontalIcon,
EyeIcon,
PencilIcon,
PhotographIcon,
PhotoIcon,
PlusIcon,
TrashIcon
} from '@heroicons/react/outline';
} from '@heroicons/react/24/outline';
import * as React from 'react';
import { useCallback, useMemo, useRef, useState } from 'react';
import { useRecoilValue } from 'recoil';
@@ -169,7 +169,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
)
}`}>
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
<CodeIcon className={`w-64 h-64 opacity-5 ${getColors(
<CodeBracketIcon className={`w-64 h-64 opacity-5 ${getColors(
'text-vulcan-200 dark:text-gray-400',
'text-[var(--vscode-foreground)]'
)
@@ -181,7 +181,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
title={snippet.isMediaSnippet ? 'Media snippet' : 'Content snippet'}
>
{snippet.isMediaSnippet ? (
<PhotographIcon className="w-5 h-5 mr-1" aria-hidden={true} />
<PhotoIcon className="w-5 h-5 mr-1" aria-hidden={true} />
) : (
<DocumentTextIcon className="w-5 h-5 mr-1" aria-hidden={true} />
)}
@@ -201,7 +201,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
)
}`}>
<div className="group-hover:hidden">
<DotsHorizontalIcon className="w-4 h-4" />
<EllipsisHorizontalIcon className="w-4 h-4" />
</div>
<div className="hidden group-hover:flex">
@@ -223,7 +223,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
)
}`}>
<div className="group-hover:hidden">
<DotsHorizontalIcon className="w-4 h-4" />
<EllipsisHorizontalIcon className="w-4 h-4" />
</div>
<div className="hidden group-hover:flex">
@@ -1,5 +1,5 @@
import * as React from 'react';
import { ChevronDownIcon } from '@heroicons/react/outline';
import { ChevronDownIcon } from '@heroicons/react/24/outline';
import { Choice, SnippetField, SnippetInfoField } from '../../../models';
import useThemeColors from '../../hooks/useThemeColors';
import { useEffect } from 'react';
@@ -1,15 +1,15 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { CodeIcon, PlusSmIcon } from '@heroicons/react/outline';
import { CodeBracketIcon, PlusIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useRecoilValue } from 'recoil';
import { FeatureFlag } from '../../../components/features/FeatureFlag';
import { FEATURE_FLAG } from '../../../constants';
import { TelemetryEvent } from '../../../constants/TelemetryEvent';
import { SnippetParser } from '../../../helpers/SnippetParser';
import { DashboardMessage } from '../../DashboardMessage';
import useThemeColors from '../../hooks/useThemeColors';
import { DashboardViewAtom, ModeAtom, SettingsSelector, ViewDataSelector } from '../../state';
import { ModeAtom, SettingsSelector, ViewDataSelector } from '../../state';
import { FilterInput } from '../Header/FilterInput';
import { PageLayout } from '../Layout/PageLayout';
import { FormDialog } from '../Modals/FormDialog';
@@ -18,7 +18,6 @@ import { Item } from './Item';
import { NewForm } from './NewForm';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { NavigationType } from '../../models';
export interface ISnippetsProps { }
@@ -35,7 +34,6 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
const [mediaSnippet, setMediaSnippet] = useState(false);
const [snippetFilter, setSnippetFilter] = useState<string>('');
const { getColors } = useThemeColors();
const [, setView] = useRecoilState(DashboardViewAtom);
const snippets = settings?.snippets || {};
const snippetKeys = useMemo(() => {
@@ -84,7 +82,6 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
};
useEffect(() => {
setView(NavigationType.Snippets);
Messenger.send(DashboardMessage.sendTelemetry, {
event: TelemetryEvent.webviewSnippetsView
});
@@ -118,7 +115,7 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
title={l10n.t(LocalizationKey.dashboardSnippetsViewSnippetsButtonCreate)}
onClick={() => setShowCreateDialog(true)}
>
<PlusSmIcon className={`mr-2 h-6 w-6`} />
<PlusIcon className={`mr-2 h-6 w-6`} />
<span className={`text-sm`}>
{l10n.t(LocalizationKey.dashboardSnippetsViewSnippetsButtonCreate)}
</span>
@@ -150,7 +147,7 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
<div className="w-full h-full flex items-center justify-center text-white">
<div className={`flex flex-col items-center ${getColors('text-gray-500 dark:text-whisper-900', 'text-[var(--frontmatter-text)]')
}`}>
<CodeIcon className="w-32 h-32" />
<CodeBracketIcon className="w-32 h-32" />
<p className="text-3xl mt-2">
{l10n.t(LocalizationKey.dashboardSnippetsViewSnippetsEmptyMessage)}
</p>
@@ -1,10 +1,9 @@
import * as React from 'react';
import { CheckCircleIcon, PlusCircleIcon } from '@heroicons/react/outline';
import { CheckCircleIcon as CheckCircleIconSolid, PlusCircleIcon as PlusCircleIconSolid } from '@heroicons/react/solid';
import { CheckCircleIcon, PlusCircleIcon } from '@heroicons/react/24/outline';
import { CheckCircleIcon as CheckCircleIconSolid, PlusCircleIcon as PlusCircleIconSolid } from '@heroicons/react/24/solid';
export interface ISelectItemProps {
title: string;
icon?: "add" | "select";
buttonTitle: string;
isSelected: boolean;
disabled?: boolean;
@@ -13,7 +12,6 @@ export interface ISelectItemProps {
export const SelectItem: React.FunctionComponent<ISelectItemProps> = ({
title,
icon = "select",
buttonTitle,
isSelected,
disabled,
@@ -30,17 +28,9 @@ export const SelectItem: React.FunctionComponent<ISelectItemProps> = ({
disabled={disabled}
>
{isSelected ? (
icon === "add" ? (
<PlusCircleIconSolid className={`h-4 w-4`} />
) : (
<CheckCircleIconSolid className={`h-4 w-4`} />
)
<CheckCircleIconSolid className={`h-4 w-4`} />
) : (
icon === "add" ? (
<PlusCircleIcon className={`h-4 w-4`} />
) : (
<CheckCircleIcon className={`h-4 w-4`} />
)
<PlusCircleIcon className={`h-4 w-4`} />
)}
<span>{title}</span>
</button>
@@ -1,4 +1,4 @@
import { CheckIcon } from '@heroicons/react/outline';
import { CheckIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { Status } from '../../models/Status';
@@ -8,7 +8,7 @@ import { useMemo, useState } from 'react';
import { Menu } from '@headlessui/react';
import { MenuItem } from '../Menu';
import { Framework, StaticFolder, Template } from '../../../models';
import { ChevronDownIcon } from '@heroicons/react/outline';
import { ChevronDownIcon } from '@heroicons/react/24/outline';
import { FrameworkDetectors } from '../../../constants/FrameworkDetectors';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
@@ -31,6 +31,7 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
const [framework, setFramework] = useState<string | null>(null);
const [taxImported, setTaxImported] = useState<boolean>(false);
const [templates, setTemplates] = useState<Template[]>([]);
const [astroCollectionsStatus, setAstroCollectionsStatus] = useState<Status>(Status.Optional)
const { getColors } = useThemeColors();
const frameworks: Framework[] = FrameworkDetectors.map((detector: any) => detector.framework);
@@ -54,6 +55,10 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
});
}
const showNotification = () => {
Messenger.send(DashboardMessage.openConfig);
};
const reload = () => {
const crntState: any = Messenger.getState() || {};
@@ -175,6 +180,9 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
))
}
</div>
<p className='mt-4 text-[var(--vscode-editorWarning-foreground)]'>
<b>{l10n.t(LocalizationKey.commonImportant)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTemplateWarning)}</p>
</div>
),
show: (crntTemplates || []).length > 0,
@@ -186,10 +194,11 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
description: (
<AstroContentTypes
settings={settings}
triggerLoading={(isLoading) => setLoading(isLoading)} />
triggerLoading={(isLoading) => setLoading(isLoading)}
setStatus={(status) => setAstroCollectionsStatus(status)} />
),
show: settings.crntFramework === 'astro',
status: Status.Optional
status: astroCollectionsStatus
},
{
id: `welcome-content-folders`,
@@ -255,11 +264,14 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
: Status.NotStarted,
onClick:
settings.initialized && settings.contentFolders && settings.contentFolders.length > 0
? reload
? () => {
showNotification();
reload();
}
: undefined
}
]
), [settings, framework, taxImported, templates]);
), [settings, framework, taxImported, templates, astroCollectionsStatus]);
React.useEffect(() => {
if (settings.crntFramework || settings.framework?.name) {
@@ -1,5 +1,5 @@
import { UserIcon } from '@heroicons/react/outline';
import { PuzzleIcon } from '@heroicons/react/solid';
import { UserIcon } from '@heroicons/react/24/outline';
import { PuzzlePieceIcon } from '@heroicons/react/24/solid';
import * as React from 'react';
export interface ITemplateItemProps {
@@ -32,7 +32,7 @@ export const TemplateItem: React.FunctionComponent<ITemplateItemProps> = ({
<span>v{version}</span>
</div>
<PuzzleIcon className='absolute top-0 right-2 h-8 w-8 opacity-25' />
<PuzzlePieceIcon className='absolute top-0 right-2 h-8 w-8 opacity-25' />
</button>
);
};
@@ -1,4 +1,4 @@
import { FilterIcon, XCircleIcon } from '@heroicons/react/outline';
import { FunnelIcon, XCircleIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
export interface IFilterInputProps {
@@ -31,7 +31,7 @@ export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({
<div className="relative flex justify-center">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<FilterIcon className={`h-4 w-4 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
<FunnelIcon className={`h-4 w-4 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
</div>
<input
@@ -1,10 +1,11 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import {
ArrowCircleUpIcon,
ArrowUpCircleIcon,
PencilIcon,
PlusIcon,
TrashIcon
} from '@heroicons/react/outline';
TagIcon,
TrashIcon,
} from '@heroicons/react/24/outline';
import * as React from 'react';
import { useCallback } from 'react';
import { MergeIcon } from '../../../components/icons/MergeIcon';
@@ -17,12 +18,14 @@ export interface ITaxonomyActionsProps {
field: string | null;
value: string;
unmapped?: boolean;
onContentTagging: (value: string) => void;
}
export const TaxonomyActions: React.FunctionComponent<ITaxonomyActionsProps> = ({
field,
value,
unmapped
unmapped,
onContentTagging
}: React.PropsWithChildren<ITaxonomyActionsProps>) => {
const onEdit = useCallback(() => {
Messenger.send(DashboardMessage.editTaxonomy, {
@@ -59,52 +62,65 @@ export const TaxonomyActions: React.FunctionComponent<ITaxonomyActionsProps> = (
});
}, [field, value]);
const onTagging = useCallback(() => {
onContentTagging(value);
}, [value]);
return (
<div className={`space-x-2`}>
{unmapped && (
<>
<div className={`space-x-2`}>
{unmapped && (
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonAddTitle, value)}
onClick={onAdd}>
<PlusIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonAddTitle, value)}
</span>
</LinkButton>
)}
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonAddTitle, value)}
onClick={onAdd}>
<PlusIcon className={`w-4 h-4`} aria-hidden={true} />
title={`Tag content`}
onClick={onTagging}>
<TagIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">{l10n.t(LocalizationKey.commonEdit)}</span>
</LinkButton>
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonEditTitle, value)}
onClick={onEdit}>
<PencilIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">{l10n.t(LocalizationKey.commonEdit)}</span>
</LinkButton>
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMergeTitle, value)}
onClick={onMerge}>
<MergeIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonAddTitle, value)}
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMergeTitle, value)}
</span>
</LinkButton>
)}
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonEditTitle, value)}
onClick={onEdit}>
<PencilIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">{l10n.t(LocalizationKey.commonEdit)}</span>
</LinkButton>
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMoveTitle)}
onClick={onMove}>
<ArrowUpCircleIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMoveTitle)}
</span>
</LinkButton>
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMergeTitle, value)}
onClick={onMerge}>
<MergeIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMergeTitle, value)}
</span>
</LinkButton>
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMoveTitle)}
onClick={onMove}>
<ArrowCircleUpIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonMoveTitle)}
</span>
</LinkButton>
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonDeleteTitle, value)}
onClick={onDelete}>
<TrashIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonDeleteTitle, value)}
</span>
</LinkButton>
</div>
<LinkButton
title={l10n.t(LocalizationKey.dashboardTaxonomyViewButtonDeleteTitle, value)}
onClick={onDelete}>
<TrashIcon className={`w-4 h-4`} aria-hidden={true} />
<span className="sr-only">
{l10n.t(LocalizationKey.dashboardTaxonomyViewButtonDeleteTitle, value)}
</span>
</LinkButton>
</div>
</>
);
};
@@ -1,5 +1,5 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { ExclamationIcon, PlusSmIcon, TagIcon } from '@heroicons/react/outline';
import { ExclamationTriangleIcon, PlusIcon, TagIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
@@ -10,7 +10,6 @@ import { SettingsSelector } from '../../state';
import { getTaxonomyField } from '../../../helpers/getTaxonomyField';
import { TaxonomyActions } from './TaxonomyActions';
import { TaxonomyLookup } from './TaxonomyLookup';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { FilterInput } from './FilterInput';
@@ -21,15 +20,16 @@ export interface ITaxonomyManagerProps {
data: TaxonomyData | undefined;
taxonomy: string | null;
pages: Page[];
onContentTagging: (value: string) => void;
}
export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = ({
data,
taxonomy,
pages
pages,
onContentTagging
}: React.PropsWithChildren<ITaxonomyManagerProps>) => {
const settings = useRecoilValue(SettingsSelector);
const { getColors } = useThemeColors();
const [filterValue, setFilterValue] = React.useState('');
const debounceFilterValue = useDebounce<string>(filterValue, 500);
const prevTaxonomy = usePrevious<string | null>(taxonomy);
@@ -141,39 +141,27 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
<div className={`py-6 px-4 flex flex-col h-full overflow-hidden`}>
<div className={`flex w-full justify-between flex-shrink-0`}>
<div>
<h2 className={`text-lg first-letter:uppercase ${getColors(
'text-gray-500 dark:text-whisper-900',
'text-[var(--frontmatter-text)]'
)
}`}>
<h2 className={`text-lg first-letter:uppercase text-[var(--frontmatter-text)]`}>
{taxonomy}
</h2>
<p className={`mt-2 text-sm first-letter:uppercase ${getColors(
'text-gray-500 dark:text-whisper-900',
'text-[var(--frontmatter-secondary-text)]'
)
}`}>
<p className={`mt-2 text-sm first-letter:uppercase text-[var(--frontmatter-secondary-text)]`}>
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerDescription, taxonomy)}
</p>
</div>
<div className='flex gap-4 justify-center items-center'>
<FilterInput
placeholder='Filter'
placeholder={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerFilterInputPlaceholder, taxonomy)}
value={filterValue}
onChange={(value) => setFilterValue(value)}
onReset={() => setFilterValue('')} />
<div>
<button
className={`inline-flex items-center px-3 py-1 border border-transparent text-xs leading-4 font-medium focus:outline-none rounded ${getColors(
`text-white dark:text-vulcan-500 bg-teal-600 hover:bg-teal-700 disabled:bg-gray-500`,
`text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`
)
}`}
className={`inline-flex items-center px-3 py-1 border border-transparent text-xs leading-4 font-medium focus:outline-none rounded text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`}
title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}
onClick={onCreate}
>
<PlusSmIcon className={`mr-2 h-6 w-6`} />
<PlusIcon className={`mr-2 h-6 w-6`} />
<span className={`text-sm`}>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}</span>
</button>
</div>
@@ -181,42 +169,42 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
</div>
<div className="mt-6 pb-6 -mr-4 pr-4 flex flex-col flex-grow overflow-auto">
<table className="min-w-full divide-y divide-gray-200 dark:divide-vulcan-300">
<table className="min-w-full divide-y divide-[var(--frontmatter-border)]">
<thead>
<tr>
<th
scope="col"
className={`px-6 py-3 text-left text-xs font-medium uppercase ${getColors('text-gray-500 dark:text-whisper-900', 'text-[var(--frontmatter-secondary-text)]')}`}
className={`px-6 py-3 text-left text-xs font-medium uppercase text-[var(--frontmatter-secondary-text)]'`}
>
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerTableHeadingName)}
</th>
<th
scope="col"
className={`px-6 py-3 text-left text-xs font-medium uppercase ${getColors('text-gray-500 dark:text-whisper-900', 'text-[var(--frontmatter-secondary-text)]')}`}
className={`px-6 py-3 text-left text-xs font-medium uppercase text-[var(--frontmatter-secondary-text)]`}
>
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerTableHeadingCount)}
</th>
<th
scope="col"
className={`px-6 py-3 text-right text-xs font-medium uppercase ${getColors('text-gray-500 dark:text-whisper-900', 'text-[var(--frontmatter-secondary-text)]')}`}
className={`px-6 py-3 text-right text-xs font-medium uppercase text-[var(--frontmatter-secondary-text)]`}
>
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerTableHeadingAction)}
</th>
</tr>
</thead>
<tbody className={`divide-y ${getColors(`divide-gray-200 dark:divide-vulcan-300`, `divide-[var(--frontmatter-border)]`)}`}>
<tbody className={`divide-y divide-[var(--frontmatter-border)]`}>
{items && items.length > 0
? items.map((item, index) => (
<tr key={index}>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-medium ${getColors(`text-gray-800 dark:text-gray-200`, `text-[var(--frontmatter-text)]`)}`}>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--frontmatter-text)]`}>
<TagIcon className="inline-block h-4 w-4 mr-2" />
<span>{item}</span>
</td>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-medium ${getColors(`text-gray-800 dark:text-gray-200`, `text-[var(--frontmatter-text)]`)}`}>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--frontmatter-text)]`}>
<TaxonomyLookup taxonomy={taxonomy} value={item} pages={pages} />
</td>
<td className={`px-6 py-4 whitespace-nowrap text-right text-sm font-medium`}>
<TaxonomyActions field={taxonomy} value={item} />
<TaxonomyActions field={taxonomy} value={item} onContentTagging={onContentTagging} />
</td>
</tr>
))
@@ -224,7 +212,7 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
(unmappedItems.length === 0 && (
<tr>
<td
className={`px-6 py-4 whitespace-nowrap text-sm font-medium ${getColors(`text-gray-800 dark:text-gray-200`, `text-[var(--frontmatter-text)]`)}`}
className={`px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--frontmatter-text)]`}
colSpan={4}
>
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerTableRowEmpty, taxonomy)}
@@ -237,17 +225,17 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
unmappedItems.map((item, index) => (
<tr key={index}>
<td
className={`px-6 py-4 whitespace-nowrap text-sm font-medium ${getColors(`text-gray-800 dark:text-gray-200`, `text-[var(--frontmatter-text)]`)}`}
className={`px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--frontmatter-text)]`}
title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerTableUnmappedTitle)}
>
<ExclamationIcon className="inline-block h-4 w-4 mr-2" />
<ExclamationTriangleIcon className="inline-block h-4 w-4 mr-2" />
<span>{item}</span>
</td>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-medium ${getColors(`text-gray-800 dark:text-gray-200`, `text-[var(--frontmatter-text)]`)}`}>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--frontmatter-text)]`}>
<TaxonomyLookup taxonomy={taxonomy} value={item} pages={pages} />
</td>
<td className={`px-6 py-4 whitespace-nowrap text-right text-sm font-medium`}>
<TaxonomyActions field={taxonomy} value={item} unmapped />
<TaxonomyActions field={taxonomy} value={item} onContentTagging={onContentTagging} unmapped />
</td>
</tr>
))}
@@ -0,0 +1,211 @@
import * as React from 'react';
import { Page, PageMappings, SortingOption } from '../../models';
import { useRecoilValue } from 'recoil';
import { SettingsSelector, SortingAtom } from '../../state';
import { getTaxonomyField } from '../../../helpers/getTaxonomyField';
import { Sorting } from '../../../helpers/Sorting';
import { ArrowLeftIcon } from '@heroicons/react/24/outline';
import { Button } from '../Common/Button';
import { VSCodeCheckbox } from '@vscode/webview-ui-toolkit/react';
import { FilterInput } from './FilterInput';
import { useDebounce } from '../../../hooks/useDebounce';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { sortPages } from '../../../utils/sortPages';
import { messageHandler } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../../DashboardMessage';
import { ExtensionState } from '../../../constants';
export interface ITaxonomyTaggingProps {
taxonomy: string | null;
value: string;
pages: Page[];
onContentMapping: (value: string, pageMappings: PageMappings) => void;
onDismiss: () => void;
}
export const TaxonomyTagging: React.FunctionComponent<ITaxonomyTaggingProps> = ({
taxonomy,
value,
pages,
onContentMapping,
onDismiss,
}: React.PropsWithChildren<ITaxonomyTaggingProps>) => {
const settings = useRecoilValue(SettingsSelector);
const [sortedPages, setSortedPages] = React.useState<Page[]>([]);
const [pageMappings, setPageMappings] = React.useState<{
tagged: Page[];
untagged: Page[];
}>({
tagged: [],
untagged: []
});
const [filterValue, setFilterValue] = React.useState('');
const debounceFilterValue = useDebounce<string>(filterValue, 500);
const untaggedPages = React.useMemo(() => {
let untagged: Page[] = [];
if (!sortedPages || !settings?.contentTypes || !taxonomy) {
return untagged;
}
for (const page of sortedPages) {
if (taxonomy === 'tags') {
if (!page.fmTags || page.fmTags.indexOf(value) === -1) {
untagged.push(page);
}
continue;
} else if (taxonomy === 'categories') {
if (!page.fmCategories || page.fmCategories.indexOf(value) === -1) {
untagged.push(page);
}
continue;
} else {
const contentType = settings.contentTypes.find((ct) => ct.name === page.fmContentType);
if (!contentType) {
continue;
}
let fieldName = getTaxonomyField(taxonomy, contentType);
if (fieldName && (!page[fieldName] || page[fieldName].indexOf(value) === -1)) {
untagged.push(page);
}
}
}
untagged = untagged.sort(Sorting.number('fmPublished')).reverse();
if (debounceFilterValue) {
return untagged.filter((p) => p.title.toLowerCase().includes(debounceFilterValue.toLowerCase()));
}
return untagged;
}, [sortedPages, taxonomy, value, debounceFilterValue]);
const onCheckboxClick = React.useCallback((page: Page) => {
const untaggedPage = untaggedPages.find((p: Page) => p.fmFilePath === page.fmFilePath);
const clonedPageMappings = Object.assign({}, pageMappings);
const taggedIdx = pageMappings.tagged.findIndex((p: Page) => p.fmFilePath === page.fmFilePath);
const untaggedIdx = pageMappings.untagged.findIndex((p: Page) => p.fmFilePath === page.fmFilePath);
if (untaggedPage) {
// Page was not yet tagged
if (taggedIdx === -1) {
clonedPageMappings.tagged.push(page);
if (untaggedIdx !== -1) {
clonedPageMappings.untagged.splice(untaggedIdx, 1);
}
} else {
clonedPageMappings.tagged.splice(taggedIdx, 1);
if (untaggedIdx === -1) {
clonedPageMappings.untagged.push(page);
}
}
} else {
// Page was already tagged, so only the untagged array needs to be updated
if (untaggedIdx === -1) {
clonedPageMappings.untagged.push(page);
} else {
clonedPageMappings.untagged.splice(taggedIdx, 1);
}
}
setPageMappings(clonedPageMappings);
}, [pageMappings, untaggedPages]);
const checkIfChecked = React.useCallback((page: Page) => {
return (!untaggedPages.find((p: Page) => p.fmFilePath === page.fmFilePath) && !pageMappings.untagged.find((p: Page) => p.fmFilePath === page.fmFilePath)) || pageMappings.tagged.find((p: Page) => p.fmFilePath === page.fmFilePath);
}, [untaggedPages, pageMappings.tagged]);
React.useEffect(() => {
messageHandler.request<{ key: string; value: SortingOption; }>(DashboardMessage.getState, {
key: ExtensionState.Dashboard.Contents.Sorting
}).then(({ key, value }) => {
if (key === ExtensionState.Dashboard.Contents.Sorting && value) {
const sorted = sortPages(pages, value)
setSortedPages(sorted);
} else {
setSortedPages(pages);
}
});
}, [pages]);
return (
<div className={`py-6 px-4 flex flex-col h-full overflow-hidden`}>
<div className={`flex w-full justify-between flex-shrink-0`}>
<div className={`flex gap-2 items-center`}>
<button onClick={onDismiss} title={l10n.t(LocalizationKey.commonBack)}>
<span className='sr-only'>{l10n.t(LocalizationKey.commonBack)}</span>
<ArrowLeftIcon className='w-5 h-5 text-[var(--frontmatter-text)]' />
</button>
<h2 className={`text-lg first-letter:uppercase text-[var(--frontmatter-text)]`}>
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyTaggingPageTitle, value)}
</h2>
</div>
<div className='flex gap-4 justify-center items-center'>
<FilterInput
placeholder={l10n.t(LocalizationKey.commonFilter)}
value={filterValue}
onChange={(value) => setFilterValue(value)}
onReset={() => setFilterValue('')} />
</div>
</div>
<div className='mt-6 mb-2 -mr-4 pr-4 flex flex-col flex-grow overflow-auto'>
<table className="min-w-full divide-y divide-[var(--frontmatter-border)]">
<thead>
<tr>
<th
scope="col"
className={``}
>
</th>
<th
scope="col"
className={`pr-6 py-3 text-left text-xs font-medium uppercase text-[var(--frontmatter-secondary-text)]`}
>
{l10n.t(LocalizationKey.commonTitle)}
</th>
</tr>
</thead>
<tbody className={`divide-y divide-[var(--frontmatter-border)]`}>
{untaggedPages && sortedPages && sortedPages.map((page) => (
<tr key={page.fmFilePath} className='py-2'>
<td className={`pl-6 w-[25px]`}>
<VSCodeCheckbox
title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyTaggingCheckbox, value)}
onClick={() => onCheckboxClick(page)}
checked={checkIfChecked(page)}>
<span className='sr-only'>
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyTaggingCheckbox, value)}
</span>
</VSCodeCheckbox>
</td>
<td className={`pr-6 whitespace-nowrap text-sm font-medium text-[var(--frontmatter-text)]`}>
<button
title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyTaggingCheckbox, value)}
className='hover:text-[var(--vscode-textLink-activeForeground)]'
onClick={() => onCheckboxClick(page)}>
{page.title}
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className='flex justify-end space-x-2'>
<Button onClick={onDismiss} secondary>{l10n.t(LocalizationKey.commonCancel)}</Button>
<Button onClick={() => onContentMapping(value, pageMappings)}>{l10n.t(LocalizationKey.commonApply)}</Button>
</div>
</div>
);
};
@@ -1,19 +1,20 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { ChevronRightIcon, DownloadIcon } from '@heroicons/react/outline';
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { ChevronRightIcon, ArrowDownTrayIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { useEffect, useState } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useRecoilValue } from 'recoil';
import { TelemetryEvent } from '../../../constants';
import { TaxonomyData } from '../../../models';
import { DashboardMessage } from '../../DashboardMessage';
import { NavigationType, Page } from '../../models';
import { DashboardViewAtom, SettingsSelector } from '../../state';
import { Page, PageMappings } from '../../models';
import { SettingsSelector } from '../../state';
import { NavigationBar, NavigationItem } from '../Layout';
import { PageLayout } from '../Layout/PageLayout';
import { SponsorMsg } from '../Layout/SponsorMsg';
import { TaxonomyManager } from './TaxonomyManager';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { TaxonomyTagging } from './TaxonomyTagging';
export interface ITaxonomyViewProps {
pages: Page[];
@@ -25,12 +26,24 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
const settings = useRecoilValue(SettingsSelector);
const [taxonomySettings, setTaxonomySettings] = useState<TaxonomyData>();
const [selectedTaxonomy, setSelectedTaxonomy] = useState<string | null>(`tags`);
const [, setView] = useRecoilState(DashboardViewAtom);
const [contentTagging, setContentTagging] = useState<string | null>(null);
const onImport = () => {
Messenger.send(DashboardMessage.importTaxonomy);
};
const onContentMapping = React.useCallback((value: string, pageMappings: PageMappings) => {
messageHandler.request(DashboardMessage.mapTaxonomy, {
taxonomy: selectedTaxonomy,
value,
pageMappings
}).then(() => {
setContentTagging(null);
}).catch(() => {
setContentTagging(null);
});
}, [selectedTaxonomy]);
useEffect(() => {
setTaxonomySettings({
tags: settings?.tags || [],
@@ -40,7 +53,6 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
}, [settings?.tags, settings?.categories, settings?.customTaxonomy]);
useEffect(() => {
setView(NavigationType.Taxonomy);
Messenger.send(DashboardMessage.sendTelemetry, {
event: TelemetryEvent.webviewTaxonomyDashboard
});
@@ -57,14 +69,17 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyViewButtonImport)}
onClick={onImport}
>
<DownloadIcon className={`w-5 mr-2`} />
<ArrowDownTrayIcon className={`w-5 mr-2`} />
<span>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyViewButtonImport)}</span>
</button>
}
>
<NavigationItem
isSelected={selectedTaxonomy === 'tags'}
onClick={() => setSelectedTaxonomy(`tags`)}
onClick={() => {
setSelectedTaxonomy(`tags`);
setContentTagging(null);
}}
>
<ChevronRightIcon className="-ml-1 w-5 mr-2" />
<span>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyViewNavigationItemTags)}</span>
@@ -72,7 +87,10 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
<NavigationItem
isSelected={selectedTaxonomy === 'categories'}
onClick={() => setSelectedTaxonomy(`categories`)}
onClick={() => {
setSelectedTaxonomy(`categories`);
setContentTagging(null);
}}
>
<ChevronRightIcon className="-ml-1 w-5 mr-2" />
<span>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyViewNavigationItemCategories)}</span>
@@ -83,7 +101,10 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
<NavigationItem
key={`${taxonomy.id}-${index}`}
isSelected={selectedTaxonomy === taxonomy.id}
onClick={() => setSelectedTaxonomy(taxonomy.id)}
onClick={() => {
setSelectedTaxonomy(taxonomy.id);
setContentTagging(null);
}}
>
<ChevronRightIcon className="-ml-1 w-5 mr-2" />
<span className={`first-letter:uppercase`}>{taxonomy.id}</span>
@@ -92,10 +113,22 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
</NavigationBar>
<div className={`w-10/12 h-full overflow-hidden`}>
<TaxonomyManager
data={taxonomySettings}
taxonomy={selectedTaxonomy}
pages={pages} />
{
contentTagging ? (
<TaxonomyTagging
value={contentTagging}
taxonomy={selectedTaxonomy}
pages={pages}
onContentMapping={(value: string, pageMappings: PageMappings) => onContentMapping(value, pageMappings)}
onDismiss={() => setContentTagging(null)} />
) : (
<TaxonomyManager
data={taxonomySettings}
taxonomy={selectedTaxonomy}
pages={pages}
onContentTagging={(value: string) => setContentTagging(value)} />
)
}
</div>
</div>
@@ -1,4 +1,4 @@
import { StopIcon } from '@heroicons/react/outline';
import { StopIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
@@ -1,4 +1,4 @@
import { BookOpenIcon, HeartIcon, StarIcon } from '@heroicons/react/outline';
import { BookOpenIcon, HeartIcon, StarIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { DOCUMENTATION_LINK, GITHUB_LINK, REVIEW_LINK, SPONSOR_LINK, TelemetryEvent } from '../../../constants';
import { Messenger } from '@estruyf/vscode/dist/client';
+27 -21
View File
@@ -1,6 +1,6 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { EventData } from '@estruyf/vscode/dist/models';
import { useState, useEffect, useCallback } from 'react';
import { useState, useEffect, useCallback, useMemo } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { MediaInfo, MediaPaths } from '../../models';
import { DashboardCommand } from '../DashboardCommand';
@@ -52,27 +52,11 @@ export default function useMedia() {
}
}, [search, prevSearch]);
const getMedia = useCallback(() => {
const allMedia = useMemo(() => {
return searchedMedia.slice(page * pageSetNr, (page + 1) * pageSetNr);
}, [searchedMedia, page, pageSetNr]);
const messageListener = (
message: MessageEvent<EventData<MediaPaths | { key: string; value: any }>>
) => {
if (message.data.command === DashboardCommand.media) {
const payload: MediaPaths = message.data.payload as MediaPaths;
setLoading(false);
setMedia(payload.media);
setTotal(payload.total);
setFolders(payload.folders);
setSelectedFolder(payload.selectedFolder);
setSearchedMedia(payload.media);
setAllContentFolders(payload.allContentFolders);
setAllStaticFolders(payload.allStaticfolders);
}
};
useEffect(() => {
const searchMedia = (search: string, media: MediaInfo[]) => {
if (search) {
const fuse = new Fuse(media, fuseOptions);
const results = fuse.search(search);
@@ -86,6 +70,28 @@ export default function useMedia() {
setTotal(media.length);
setSearchedMedia(media);
}
const messageListener = useCallback((message: MessageEvent<EventData<MediaPaths | { key: string; value: any }>>) => {
if (message.data.command === DashboardCommand.media) {
const payload: MediaPaths = message.data.payload as MediaPaths;
setLoading(false);
setMedia(payload.media);
setTotal(payload.total);
setFolders(payload.folders);
setSelectedFolder(payload.selectedFolder);
if (search) {
searchMedia(search, payload.media);
} else {
setSearchedMedia(payload.media);
}
setAllContentFolders(payload.allContentFolders);
setAllStaticFolders(payload.allStaticfolders);
}
}, [search]);
useEffect(() => {
searchMedia(search, media);
}, [search, media]);
useEffect(() => {
@@ -94,9 +100,9 @@ export default function useMedia() {
return () => {
Messenger.unlisten(messageListener);
};
}, []);
}, [search]);
return {
media: getMedia()
media: allMedia
};
}
+23 -43
View File
@@ -14,12 +14,13 @@ import {
TabSelector,
TagSelector
} from '../state';
import { SortOrder, SortType } from '../../models';
import { Sorting } from '../../helpers/Sorting';
import { Messenger } from '@estruyf/vscode/dist/client';
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../DashboardMessage';
import { EventData } from '@estruyf/vscode/dist/models';
import { parseWinPath } from '../../helpers/parseWinPath';
import { sortPages } from '../../utils/sortPages';
import { ExtensionState } from '../../constants';
import { SortingOption } from '../models';
export default function usePages(pages: Page[]) {
const [pageItems, setPageItems] = useRecoilState(AllPagesAtom);
@@ -37,7 +38,7 @@ export default function usePages(pages: Page[]) {
* Process all the pages by applying the sorting, filtering and searching.
*/
const processPages = useCallback(
(searchedPages: Page[], fullProcess: boolean = true) => {
(searchedPages: Page[]) => {
const framework = settings?.crntFramework;
// Filter the pages
@@ -67,35 +68,7 @@ export default function usePages(pages: Page[]) {
// Sort the pages
let pagesSorted: Page[] = Object.assign([], pagesToShow);
if (!search) {
if (sorting && sorting.id === SortOption.FileNameAsc) {
pagesSorted = pagesSorted.sort(Sorting.alphabetically('fmFileName'));
} else if (sorting && sorting.id === SortOption.FileNameDesc) {
pagesSorted = pagesSorted.sort(Sorting.alphabetically('fmFileName')).reverse();
} else if (sorting && sorting.id === SortOption.PublishedAsc) {
pagesSorted = pagesSorted.sort(Sorting.number('fmPublished'));
} else if (sorting && sorting.id === SortOption.LastModifiedAsc) {
pagesSorted = pagesSorted.sort(Sorting.number('fmModified'));
} else if (sorting && sorting.id === SortOption.PublishedDesc) {
pagesSorted = pagesSorted.sort(Sorting.number('fmPublished')).reverse();
} else if (sorting && sorting.id === SortOption.LastModifiedDesc) {
pagesSorted = pagesSorted.sort(Sorting.number('fmModified')).reverse();
} else if (sorting && sorting.id && sorting.name) {
const { order, name, type } = sorting;
if (type === SortType.string) {
pagesSorted = pagesSorted.sort(Sorting.alphabetically(name));
} else if (type === SortType.date) {
pagesSorted = pagesSorted.sort(Sorting.date(name));
} else if (type === SortType.number) {
pagesSorted = pagesSorted.sort(Sorting.number(name));
}
if (order === SortOrder.desc) {
pagesSorted = pagesSorted.reverse();
}
} else {
pagesSorted = pagesSorted.sort(Sorting.number('fmModified')).reverse();
}
pagesSorted = sortPages(pagesSorted, sorting);
}
if (folder) {
@@ -208,20 +181,27 @@ export default function usePages(pages: Page[]) {
useEffect(() => {
let usedSorting = sorting;
if (!usedSorting) {
const lastSort = settings?.dashboardState.contents.sorting;
if (lastSort) {
setSorting(lastSort);
return;
const startPageProcessing = () => {
// Check if search needs to be performed
let searchedPages = pages;
if (search) {
Messenger.send(DashboardMessage.searchPages, { query: search });
} else {
processPages(searchedPages);
}
}
// Check if search needs to be performed
let searchedPages = pages;
if (search) {
Messenger.send(DashboardMessage.searchPages, { query: search });
if (!usedSorting) {
messageHandler.request<{ key: string; value: SortingOption; }>(DashboardMessage.getState, {
key: ExtensionState.Dashboard.Contents.Sorting
}).then(({ key, value }) => {
if (key === ExtensionState.Dashboard.Contents.Sorting && value) {
setSorting(value);
return;
}
});
} else {
processPages(searchedPages);
startPageProcessing();
}
}, [settings?.draftField, pages, sorting, search, tag, category, folder]);
@@ -0,0 +1,6 @@
import { Page } from './Page';
export interface PageMappings {
tagged: Page[];
untagged: Page[];
}
+1
View File
@@ -1,6 +1,7 @@
export * from './DashboardViewType';
export * from './NavigationType';
export * from './Page';
export * from './PageMappings';
export * from './Settings';
export * from './SortingOption';
export * from './Status';
+14 -5
View File
@@ -130,10 +130,10 @@
}
input[type='submit'] {
@apply mt-4 inline-flex w-auto cursor-pointer items-center border border-transparent bg-teal-600 px-3 py-2 text-sm font-medium leading-4 text-white;
@apply mt-4 inline-flex w-auto items-center rounded border border-transparent bg-[var(--frontmatter-button-background)] px-3 py-2 text-sm font-medium leading-4 text-[var(--vscode-button-foreground)];
&:hover {
@apply bg-teal-700;
@apply bg-[var(--frontmatter-button-hoverBackground)];
}
&:focus {
@@ -141,12 +141,21 @@
}
&:disabled {
@apply bg-gray-500 opacity-50;
@apply opacity-50;
}
}
}
.fields {
> .fields {
> div > label:first-of-type {
color: var(--primary-color);
}
> div:not(:first-child) > label:first-of-type {
margin-block-start: 2rem;
border-block-start: 1px solid;
padding-block-start: 2rem;
}
}
}
.ant-list.ant-list-bordered {
+7 -2
View File
@@ -1,6 +1,6 @@
import { GitListener } from './listeners/general/GitListener';
import * as vscode from 'vscode';
import { COMMAND_NAME, TelemetryEvent } from './constants';
import { COMMAND_NAME, CONTEXT, EXTENSION_NAME, TelemetryEvent } from './constants';
import { MarkdownFoldingProvider } from './providers/MarkdownFoldingProvider';
import { TagType } from './panelWebView/TagType';
import { PanelProvider } from './panelWebView/PanelProvider';
@@ -46,6 +46,11 @@ export async function activate(context: vscode.ExtensionContext) {
const { subscriptions, extensionUri, extensionPath } = context;
const extension = Extension.getInstance(context);
// Set development context
if (!Extension.getInstance().isProductionMode) {
vscode.commands.executeCommand('setContext', CONTEXT.isDevelopment, true);
}
Backers.init(context).then(() => {});
// Make sure the EN language file is loaded
@@ -281,7 +286,7 @@ export async function activate(context: vscode.ExtensionContext) {
);
fmStatusBarItem.command = COMMAND_NAME.dashboard;
fmStatusBarItem.text = `$(fm-logo)`;
fmStatusBarItem.tooltip = `Front Matter CMS`;
fmStatusBarItem.tooltip = EXTENSION_NAME;
fmStatusBarItem.show();
// Register listeners that make sure the status bar updates
+20 -6
View File
@@ -42,6 +42,8 @@ import { CustomScript } from './CustomScript';
import { Folders } from '../commands/Folders';
import { existsAsync, readFileAsync } from '../utils';
import { mkdirAsync } from '../utils/mkdirAsync';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class ArticleHelper {
private static notifiedFiles: string[] = [];
@@ -442,7 +444,11 @@ export class ArticleHelper {
const newFolder = join(folderPath, sanitizedName);
if (await existsAsync(newFolder)) {
Notifications.error(
`A page bundle with the name ${sanitizedName} already exists in ${folderPath}`
l10n.t(
LocalizationKey.helpersArticleHelperCreateContentPageBundleError,
sanitizedName,
folderPath
)
);
return;
} else {
@@ -466,7 +472,9 @@ export class ArticleHelper {
await mkdirAsync(folderPath, { recursive: true });
if (await existsAsync(newFilePath)) {
Notifications.warning(`Content with the title already exists. Please specify a new title.`);
Notifications.warning(
l10n.t(LocalizationKey.helpersArticleHelperCreateContentContentExistsWarning)
);
return;
}
}
@@ -597,7 +605,12 @@ export class ArticleHelper {
value = value.replace(regex, updatedValue);
}
} catch (e) {
Notifications.error(`Error while processing the ${placeholder.id} placeholder`);
Notifications.error(
l10n.t(
LocalizationKey.helpersArticleHelperProcessCustomPlaceholdersPlaceholderError,
placeholder.id
)
);
Logger.error((e as Error).message);
value = DefaultFieldValues.faultyCustomPlaceholder;
@@ -795,9 +808,10 @@ export class ArticleHelper {
Extension.getInstance().diagnosticCollection.set(editor.document.uri, [
{
severity: DiagnosticSeverity.Error,
message: `${
error.name ? `${error.name}: ` : ''
}Error parsing the front matter of ${fileName}`,
message: `${error.name ? `${error.name}: ` : ''}${l10n.t(
LocalizationKey.helpersArticleHelperParseFileDiagnosticError,
fileName
)}`,
range: fmRange
}
]);
+152 -37
View File
@@ -1,8 +1,9 @@
import { ModeListener } from './../listeners/general/ModeListener';
import { PagesListener } from './../listeners/dashboard';
import { ArticleHelper, CustomScript, Settings } from '.';
import { ArticleHelper, CustomScript, Logger, Settings } from '.';
import {
DefaultFieldValues,
EXTENSION_NAME,
FEATURE_FLAG,
SETTING_CONTENT_DRAFT_FIELD,
SETTING_DATE_FORMAT,
@@ -28,7 +29,9 @@ import { Telemetry } from './Telemetry';
import { processKnownPlaceholders } from './PlaceholderHelper';
import { basename } from 'path';
import { ParsedFrontMatter } from '../parsers';
import { encodeEmoji, existsAsync, writeFileAsync } from '../utils';
import { encodeEmoji, existsAsync, fieldWhenClause, writeFileAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class ContentType {
/**
@@ -173,30 +176,34 @@ export class ContentType {
const filePath = editor?.document.uri.fsPath;
if (!content || !content.data) {
Notifications.warning(`No front matter data found to generate a content type.`);
Notifications.warning(l10n.t(LocalizationKey.helpersContentTypeGenerateNoFrontMatterError));
return;
}
const override = await window.showQuickPick(['Yes', 'No'], {
title: 'Override default content type',
placeHolder:
'Do you want to overwrite the default content type configuration with the fields used in the current field?',
ignoreFocusOut: true
});
const overrideBool = override === 'Yes';
const override = await window.showQuickPick(
[l10n.t(LocalizationKey.commonYes), l10n.t(LocalizationKey.commonNo)],
{
title: l10n.t(LocalizationKey.helpersContentTypeGenerateOverrideQuickPickTitle),
placeHolder: l10n.t(LocalizationKey.helpersContentTypeGenerateOverrideQuickPickPlaceholder),
ignoreFocusOut: true
}
);
const overrideBool = override === l10n.t(LocalizationKey.commonYes);
let contentTypeName: string | undefined = `default`;
// Ask for the new content type name
if (!overrideBool) {
contentTypeName = await window.showInputBox({
title: 'Generate Content Type',
placeHolder: 'Enter the name of the content type to generate',
prompt: 'Enter the name of the content type to generate',
title: l10n.t(LocalizationKey.helpersContentTypeGenerateContentTypeInputTitle),
placeHolder: l10n.t(LocalizationKey.helpersContentTypeGenerateContentTypeInputPrompt),
prompt: l10n.t(LocalizationKey.helpersContentTypeGenerateContentTypeInputPrompt),
ignoreFocusOut: true,
validateInput: (value: string) => {
if (!value) {
return 'Please enter a name for the content type';
return l10n.t(
LocalizationKey.helpersContentTypeGenerateContentTypeInputValidationEnterName
);
}
const contentTypes = ContentType.getAll();
@@ -204,7 +211,9 @@ export class ContentType {
contentTypes &&
contentTypes.find((ct) => ct.name.toLowerCase() === value.toLowerCase())
) {
return 'A content type with this name already exists';
return l10n.t(
LocalizationKey.helpersContentTypeGenerateContentTypeInputValidationNameExists
);
}
return null;
@@ -212,7 +221,9 @@ export class ContentType {
});
if (!contentTypeName) {
Notifications.warning(`You didn't specify a name for the content type.`);
Notifications.warning(
l10n.t(LocalizationKey.helpersContentTypeGenerateNoContentTypeNameWarning)
);
return;
}
}
@@ -221,12 +232,17 @@ export class ContentType {
let pageBundle = false;
const fileName = filePath ? basename(filePath) : undefined;
if (fileName?.startsWith(`index.`)) {
const pageBundleAnswer = await window.showQuickPick(['Yes', 'No'], {
title: 'Use as page bundle',
placeHolder: 'Do you want to use this content type as a page bundle?',
ignoreFocusOut: true
});
pageBundle = pageBundleAnswer === 'Yes';
const pageBundleAnswer = await window.showQuickPick(
[l10n.t(LocalizationKey.commonYes), l10n.t(LocalizationKey.commonNo)],
{
title: l10n.t(LocalizationKey.helpersContentTypeGeneratePageBundleQuickPickTitle),
placeHolder: l10n.t(
LocalizationKey.helpersContentTypeGeneratePageBundleQuickPickPlaceHolder
),
ignoreFocusOut: true
}
);
pageBundle = pageBundleAnswer === l10n.t(LocalizationKey.commonYes);
}
const fields = ContentType.generateFields(content.data);
@@ -256,11 +272,19 @@ export class ContentType {
const configPath = await Settings.projectConfigPath();
const notificationAction = await Notifications.info(
`Content type ${contentTypeName} has been ${overrideBool ? `updated` : `generated`}.`,
configPath && (await existsAsync(configPath)) ? `Open settings` : undefined
overrideBool
? l10n.t(LocalizationKey.helpersContentTypeGenerateUpdatedSuccess)
: l10n.t(LocalizationKey.helpersContentTypeGenerateGeneratedSuccess),
configPath && (await existsAsync(configPath))
? l10n.t(LocalizationKey.commonOpenSettings)
: undefined
);
if (notificationAction === 'Open settings' && configPath && (await existsAsync(configPath))) {
if (
notificationAction === l10n.t(LocalizationKey.commonOpenSettings) &&
configPath &&
(await existsAsync(configPath))
) {
commands.executeCommand('vscode.open', Uri.file(configPath));
}
}
@@ -278,7 +302,9 @@ export class ContentType {
const content = ArticleHelper.getCurrent();
if (!content || !content.data) {
Notifications.warning(`No front matter data found to add missing fields.`);
Notifications.warning(
l10n.t(LocalizationKey.helpersContentTypeAddMissingFieldsNoFrontMatterWarning)
);
return;
}
@@ -293,11 +319,17 @@ export class ContentType {
const configPath = await Settings.projectConfigPath();
const notificationAction = await Notifications.info(
`Content type ${contentType.name} has been updated.`,
configPath && (await existsAsync(configPath)) ? `Open settings` : undefined
l10n.t(LocalizationKey.helpersContentTypeAddMissingFieldsUpdatedSuccess, contentType.name),
configPath && (await existsAsync(configPath))
? l10n.t(LocalizationKey.commonOpenSettings)
: undefined
);
if (notificationAction === 'Open settings' && configPath && (await existsAsync(configPath))) {
if (
notificationAction === l10n.t(LocalizationKey.commonOpenSettings) &&
configPath &&
(await existsAsync(configPath))
) {
commands.executeCommand('vscode.open', Uri.file(configPath));
}
}
@@ -316,16 +348,18 @@ export class ContentType {
const contentTypes = ContentType.getAll() || [];
if (!content || !content.data) {
Notifications.warning(`No front matter data found to set the content type.`);
Notifications.warning(
l10n.t(LocalizationKey.helpersContentTypeSetContentTypeNoFrontMatterWarning)
);
return;
}
const ctAnswer = await window.showQuickPick(
contentTypes.map((ct) => ct.name),
{
title: 'Select the content type',
ignoreFocusOut: true,
placeHolder: 'Which content type would you like to use?'
title: l10n.t(LocalizationKey.helpersContentTypeSetContentTypeQuickPickTitle),
placeHolder: l10n.t(LocalizationKey.helpersContentTypeSetContentTypeQuickPickPlaceholder),
ignoreFocusOut: true
}
);
@@ -739,6 +773,20 @@ export class ContentType {
name: field,
type: 'number'
} as Field);
} else if (typeof fieldData === 'boolean') {
if (field.toLowerCase() === 'draft') {
fields.push({
title: field,
name: field,
type: 'draft'
} as Field);
} else {
fields.push({
title: field,
name: field,
type: 'boolean'
} as Field);
}
} else if (!isNaN(new Date(fieldData).getDate())) {
fields.push({
title: field,
@@ -776,10 +824,66 @@ export class ContentType {
window.withProgress(
{
location: ProgressLocation.Notification,
title: 'Front Matter: Creating content...',
title: l10n.t(LocalizationKey.helpersContentTypeCreateProgressTitle, EXTENSION_NAME),
cancellable: false
},
async () => {
if (contentType.isSubContent || contentType.allowAsSubContent) {
let showDialog = true;
if (contentType.allowAsSubContent) {
const subContentAnswer = await window.showQuickPick(
[l10n.t(LocalizationKey.commonNo), l10n.t(LocalizationKey.commonYes)],
{
title: l10n.t(LocalizationKey.helpersContentTypeCreateAllowSubContentTitle),
placeHolder: l10n.t(
LocalizationKey.helpersContentTypeCreateAllowSubContentPlaceHolder
),
ignoreFocusOut: true
}
);
showDialog = subContentAnswer === l10n.t(LocalizationKey.commonYes);
}
if (showDialog) {
const folderLocation = await window.showOpenDialog({
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
defaultUri: Uri.file(folderPath),
openLabel: l10n.t(
LocalizationKey.helpersContentTypeCreateAllowSubContentShowOpenDialogOpenLabel
),
title: l10n.t(
LocalizationKey.helpersContentTypeCreateAllowSubContentShowOpenDialogTitle
)
});
if (!folderLocation || folderLocation.length === 0) {
return;
}
folderPath = folderLocation[0].fsPath;
if (contentType.pageBundle) {
const createAsPageBundle = await window.showQuickPick(
[l10n.t(LocalizationKey.commonNo), l10n.t(LocalizationKey.commonYes)],
{
title: l10n.t(LocalizationKey.helpersContentTypeCreatePageBundleTitle),
placeHolder: l10n.t(
LocalizationKey.helpersContentTypeCreatePageBundlePlaceHolder
),
ignoreFocusOut: true
}
);
if (createAsPageBundle === l10n.t(LocalizationKey.commonNo)) {
contentType.pageBundle = false;
}
}
}
}
let titleValue = await Questions.ContentTitle();
if (!titleValue) {
return;
@@ -826,7 +930,13 @@ export class ContentType {
!!contentType.clearEmpty
);
data = ArticleHelper.updateDates(Object.assign({}, data));
const article: ParsedFrontMatter = {
content: '',
data: Object.assign({}, data),
path: newFilePath
};
data = ArticleHelper.updateDates(article);
if (contentType.name !== DEFAULT_CONTENT_TYPE_NAME) {
data['type'] = contentType.name;
@@ -851,7 +961,7 @@ export class ContentType {
await commands.executeCommand('vscode.open', Uri.file(newFilePath));
Notifications.info(`Your new content has been created.`);
Notifications.info(l10n.t(LocalizationKey.helpersContentTypeCreateSuccess));
Telemetry.send(TelemetryEvent.createContentFromContentType);
@@ -878,6 +988,11 @@ export class ContentType {
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
for (const field of obj.fields) {
if (!fieldWhenClause(field, data, obj.fields)) {
Logger.info(`Field ${field.name} not added because of when clause`);
continue;
}
if (field.name === 'title') {
if (field.default) {
data[field.name] = processKnownPlaceholders(
@@ -992,7 +1107,7 @@ export class ContentType {
private static async verify() {
const hasFeature = await ModeListener.hasFeature(FEATURE_FLAG.panel.contentType);
if (!hasFeature) {
Notifications.warning(`The content type actions are not available in this mode.`);
Notifications.warning(l10n.t(LocalizationKey.helpersContentTypeVerifyWarning));
return false;
}
+31 -12
View File
@@ -15,6 +15,8 @@ import { ParsedFrontMatter } from '../parsers';
import { TelemetryEvent } from '../constants/TelemetryEvent';
import { SETTING_CUSTOM_SCRIPTS } from '../constants';
import { existsAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class CustomScript {
/**
@@ -101,7 +103,9 @@ export class CustomScript {
}
);
} else {
Notifications.warning(`${script.title}: Article couldn't be retrieved.`);
Notifications.warning(
l10n.t(LocalizationKey.helpersCustomScriptSingleRunArticleWarning, script.title)
);
}
}
@@ -115,7 +119,9 @@ export class CustomScript {
const folders = await Folders.getInfo();
if (!folders || folders.length === 0) {
Notifications.warning(`${script.title}: No files found.`);
Notifications.warning(
l10n.t(LocalizationKey.helpersCustomScriptBulkRunNoFilesWarning, script.title)
);
return;
}
@@ -124,7 +130,7 @@ export class CustomScript {
window.withProgress(
{
location: ProgressLocation.Notification,
title: `Executing: ${script.title}`,
title: l10n.t(LocalizationKey.helpersCustomScriptExecuting, script.title),
cancellable: false
},
async (progress, token) => {
@@ -169,7 +175,9 @@ export class CustomScript {
script: ICustomScript
): Promise<void> {
if (!path) {
Notifications.error(`${script.title}: There was no folder or media path specified.`);
Notifications.error(
l10n.t(LocalizationKey.helpersCustomScriptRunMediaScriptNoFolderWarning, script.title)
);
return;
}
@@ -177,7 +185,7 @@ export class CustomScript {
window.withProgress(
{
location: ProgressLocation.Notification,
title: `Executing: ${script.title}`,
title: l10n.t(LocalizationKey.helpersCustomScriptExecuting, script.title),
cancellable: false
},
async () => {
@@ -196,7 +204,7 @@ export class CustomScript {
return;
} catch (e) {
Notifications.error(`${script.title}: ${(e as Error).message}`);
Notifications.errorWithOutput(`${script.title} -`);
return;
}
}
@@ -286,11 +294,15 @@ export class CustomScript {
} else if (editor) {
await ArticleHelper.update(editor, article);
} else {
Logger.error(`Couldn't update article.`);
throw new Error(`Couldn't update article.`);
}
Notifications.info(`${script.title}: front matter updated.`);
Notifications.info(
l10n.t(LocalizationKey.helpersCustomScriptShowOutputFrontMatterSuccess, script.title)
);
}
} else {
Logger.error(`No frontmatter found.`);
throw new Error(`No frontmatter found.`);
}
} catch (error) {
@@ -298,16 +310,21 @@ export class CustomScript {
ContentProvider.show(output, script.title, script.outputType || 'text');
} else {
window
.showInformationMessage(`${script.title}: ${output}`, 'Copy output')
.showInformationMessage(
`${script.title}: ${output}`,
l10n.t(LocalizationKey.helpersCustomScriptShowOutputCopyOutputAction)
)
.then((value) => {
if (value === 'Copy output') {
if (value === l10n.t(LocalizationKey.helpersCustomScriptShowOutputCopyOutputAction)) {
vscodeEnv.clipboard.writeText(output);
}
});
}
}
} else {
Notifications.info(`${script.title}: Executed your custom script.`);
Notifications.info(
l10n.t(LocalizationKey.helpersCustomScriptShowOutputSuccess, script.title)
);
}
}
@@ -360,6 +377,7 @@ export class CustomScript {
}
if (!(await existsAsync(scriptPath))) {
Logger.error(`Script not found: ${scriptPath}`);
throw new Error(`Script not found: ${scriptPath}`);
}
@@ -368,7 +386,7 @@ export class CustomScript {
}
const fullScript = `${command} "${scriptPath}" ${args}`;
Logger.info(`Executing: ${fullScript}`);
Logger.info(l10n.t(LocalizationKey.helpersCustomScriptExecuting, fullScript));
const output: string = await CustomScript.executeScriptAsync(fullScript, wsPath);
@@ -416,6 +434,7 @@ export class CustomScript {
return new Promise(async (resolve, reject) => {
exec(fullScript, { cwd: wsPath }, (error, stdout) => {
if (error) {
Logger.error(error.message);
reject(error.message);
return;
}
@@ -441,7 +460,7 @@ export class CustomScript {
return true;
} catch (e) {
Logger.error(`Invalid command: ${command}`);
Logger.error(l10n.t(LocalizationKey.helpersCustomScriptValidateCommandError, command));
return false;
}
}
+16
View File
@@ -59,6 +59,22 @@ export class DashboardSettings {
return this.cachedSettings;
}
public static async updateAfterClose() {
if (this.cachedSettings) {
this.cachedSettings = await this.getSettings();
const ext = Extension.getInstance();
// Update states
this.cachedSettings.dashboardState.contents.sorting = await ext.getState<
SortingOption | undefined
>(ExtensionState.Dashboard.Contents.Sorting, 'workspace');
this.cachedSettings.dashboardState.media.sorting = await ext.getState<
SortingOption | undefined
>(ExtensionState.Dashboard.Media.Sorting, 'workspace');
}
}
public static async getSettings() {
const ext = Extension.getInstance();
const wsFolder = Folders.getWorkspaceFolder();
+4 -10
View File
@@ -7,6 +7,8 @@ import { commands } from 'vscode';
import { COMMAND_NAME, SETTING_DATA_FILES } from '../constants';
import { Settings } from './SettingsHelper';
import { existsAsync, readFileAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class DataFileHelper {
/**
@@ -54,21 +56,13 @@ export class DataFileHelper {
const dataFile = await DataFileHelper.get(file);
if (fileType === 'yaml') {
return yaml.safeLoad(dataFile || '');
return yaml.load(dataFile || '');
} else {
return dataFile ? JSON.parse(dataFile) : undefined;
}
} catch (ex) {
Logger.error(`DataFileHelper::process: ${(ex as Error).message}`);
const btnClick = await Notifications.error(
`Something went wrong while processing the data file. Check your file and output log for more information.`,
'Open output'
);
if (btnClick && btnClick === 'Open output') {
commands.executeCommand(COMMAND_NAME.showOutputChannel);
}
Notifications.errorWithOutput(l10n.t(LocalizationKey.helpersDataFileHelperProcessError));
return;
}
}
+38 -17
View File
@@ -33,6 +33,8 @@ import { Notifications } from './Notifications';
import { Settings } from './SettingsHelper';
import { TaxonomyHelper } from './TaxonomyHelper';
import { Cache } from '../commands/Cache';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class Extension {
private static instance: Extension;
@@ -72,8 +74,8 @@ export class Extension {
}
if (usedVersion !== installedVersion) {
const whatIsNewTitle = `Check the changelog`;
const githubTitle = `Give it a ⭐️`;
const whatIsNewTitle = l10n.t(LocalizationKey.helpersExtensionGetVersionChangelog);
const githubTitle = l10n.t(LocalizationKey.helpersExtensionGetVersionStarIt);
const whatIsNew = {
title: whatIsNewTitle,
@@ -94,7 +96,11 @@ export class Extension {
window
.showInformationMessage(
`${EXTENSION_NAME} has been updated to v${installedVersion} — check out what's new!`,
l10n.t(
LocalizationKey.helpersExtensionGetVersionUpdateNotification,
EXTENSION_NAME,
installedVersion
),
starGitHub,
whatIsNew
)
@@ -215,11 +221,18 @@ export class Extension {
modifiedField?.teamValue
) {
Notifications.warning(
`The "${CONFIG_KEY}.${SETTING_DATE_FIELD}" and "${CONFIG_KEY}.${SETTING_MODIFIED_FIELD}" settings have been deprecated. Please use the "isPublishDate" and "isModifiedDate" datetime field properties instead.`,
'Hide',
'See migration guide'
l10n.t(
LocalizationKey.helpersExtensionMigrateSettingsDeprecatedWarning,
`${CONFIG_KEY}.${SETTING_DATE_FIELD}`,
`${CONFIG_KEY}.${SETTING_MODIFIED_FIELD}`
),
l10n.t(LocalizationKey.helpersExtensionMigrateSettingsDeprecatedWarningHide),
l10n.t(LocalizationKey.helpersExtensionMigrateSettingsDeprecatedWarningSeeGuide)
).then(async (value) => {
if (value === 'See migration guide') {
if (
value ===
l10n.t(LocalizationKey.helpersExtensionMigrateSettingsDeprecatedWarningSeeGuide)
) {
const isProd = this.isProductionMode;
commands.executeCommand(
'vscode.open',
@@ -234,7 +247,9 @@ export class Extension {
true,
'workspace'
);
} else if (value === 'Hide') {
} else if (
value === l10n.t(LocalizationKey.helpersExtensionMigrateSettingsDeprecatedWarningHide)
) {
await Extension.getInstance().setState<boolean>(
ExtensionState.Updates.v7_0_0.dateFields,
true,
@@ -291,15 +306,23 @@ export class Extension {
const templates = await Template.getTemplates();
if (templates && templates.length > 0) {
const answer = await window.showQuickPick(['Yes', 'No'], {
title: 'Front Matter - Templates',
placeHolder: 'Do you want to keep on using the template functionality?',
ignoreFocusOut: true
});
const answer = await window.showQuickPick(
[l10n.t(LocalizationKey.commonYes), l10n.t(LocalizationKey.commonNo)],
{
title: l10n.t(
LocalizationKey.helpersExtensionMigrateSettingsTemplatesQuickPickTitle,
EXTENSION_NAME
),
placeHolder: l10n.t(
LocalizationKey.helpersExtensionMigrateSettingsTemplatesQuickPickPlaceholder
),
ignoreFocusOut: true
}
);
await Settings.update(
SETTING_TEMPLATES_ENABLED,
answer?.toLocaleLowerCase() === 'yes',
answer?.toLocaleLowerCase() === l10n.t(LocalizationKey.commonYes),
true
);
}
@@ -410,9 +433,7 @@ export class Extension {
const mainVersionInstalled = extensions.getExtension(EXTENSION_ID);
if (mainVersionInstalled) {
Notifications.error(
`Front Matter BETA cannot be used while the main version is installed. Please ensure that you have only over version installed.`
);
Notifications.error(l10n.t(LocalizationKey.helpersExtensionCheckIfExtensionCanRunWarning));
return false;
}
}
+22 -6
View File
@@ -30,6 +30,8 @@ import { MediaListener as DashboardMediaListener } from '../listeners/dashboard'
import { ArticleHelper } from './ArticleHelper';
import { lookup } from 'mime-types';
import { existsAsync, readdirAsync, unlinkAsync, writeFileAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
export class MediaHelpers {
private static media: MediaInfo[] = [];
@@ -308,7 +310,7 @@ export class MediaHelpers {
}
if (!(await existsAsync(absFolderPath))) {
Notifications.error(`We couldn't find your selected folder.`);
Notifications.error(l10n.t(LocalizationKey.helpersMediaHelperSaveFileFolderError));
return;
}
@@ -317,12 +319,22 @@ export class MediaHelpers {
if (imgData) {
await writeFileAsync(staticPath, imgData.data);
Notifications.info(`File ${fileName} uploaded to: ${folder}`);
Notifications.info(
l10n.t(
LocalizationKey.helpersMediaHelperSaveFileFileUploadedSuccess,
fileName,
folder || ''
)
);
return true;
} else {
Notifications.error(`Something went wrong uploading ${fileName}`);
throw new Error(`Something went wrong uploading ${fileName}`);
Notifications.error(
l10n.t(LocalizationKey.helpersMediaHelperSaveFileFileUploadedFailed, fileName)
);
throw new Error(
l10n.t(LocalizationKey.helpersMediaHelperSaveFileFileUploadedFailed, fileName)
);
}
}
@@ -355,8 +367,12 @@ export class MediaHelpers {
MediaHelpers.media = [];
return true;
} catch (err: any) {
Notifications.error(`Something went wrong deleting ${basename(file)}`);
throw new Error(`Something went wrong deleting ${basename(file)}`);
Notifications.error(
l10n.t(LocalizationKey.helpersMediaHelperDeleteFileFileDeletionFailed, basename(file))
);
throw new Error(
l10n.t(LocalizationKey.helpersMediaHelperDeleteFileFileDeletionFailed, basename(file))
);
}
}
+4 -2
View File
@@ -9,6 +9,8 @@ import { LocalStore } from '../constants';
import { existsAsync, renameAsync } from '../utils';
import { existsSync, mkdirSync, renameSync } from 'fs';
import { lookup } from 'mime-types';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
interface MediaRecord {
description: string;
@@ -160,14 +162,14 @@ export class MediaLibrary {
const newPath = join(dirname(filePath), `${newFileInfo.name}${oldFileInfo.ext}`);
if (await existsAsync(newPath)) {
Notifications.warning(`The name "${filename}" already exists at the file location.`);
Notifications.warning(LocalizationKey.helpersMediaLibraryRemoveWarning, filename);
} else {
await renameAsync(filePath, newPath);
await this.rename(filePath, newPath);
MediaHelpers.resetMedia();
}
} catch (err) {
Notifications.error(`Something went wrong updating "${name}" to "${filename}".`);
Notifications.error(l10n.t(LocalizationKey.helpersMediaLibraryRemoveError, name, filename));
}
}
}
+27 -1
View File
@@ -1,8 +1,10 @@
import { SETTING_GLOBAL_NOTIFICATIONS_DISABLED } from './../constants/settings';
import { window } from 'vscode';
import { EXTENSION_NAME, SETTING_GLOBAL_NOTIFICATIONS } from '../constants';
import { COMMAND_NAME, EXTENSION_NAME, SETTING_GLOBAL_NOTIFICATIONS } from '../constants';
import { Logger } from './Logger';
import { Settings } from './SettingsHelper';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
type NotificationType = 'INFO' | 'WARNING' | 'ERROR' | 'ERROR_ONCE';
@@ -57,6 +59,30 @@ export class Notifications {
return Promise.resolve(undefined);
}
/**
* Show an error notification to the user with a link to the output channel
* @param message
* @param items
* @returns
*/
public static errorWithOutput(message: string, ...items: any): Thenable<string | undefined> {
Logger.info(`${EXTENSION_NAME}: ${message}`, 'ERROR');
if (this.shouldShow('ERROR')) {
return window.showErrorMessage(
`${EXTENSION_NAME}: ${message} ${l10n.t(
LocalizationKey.notificationsOutputChannelDescription,
`[${l10n.t(LocalizationKey.notificationsOutputChannelLink)}](command:${
COMMAND_NAME.showOutputChannel
})`
)}`,
...items
);
}
return Promise.resolve(undefined);
}
/**
* Show an error notification to the user only once
* @param message

Some files were not shown because too many files have changed in this diff Show More