Compare commits

..

57 Commits

Author SHA1 Message Date
Elio Struyf 599d43b254 Merge pull request #658 from estruyf/dev 2023-09-11 10:05:26 +02:00
Elio Struyf 48890be4dc Updated changelog 2023-09-11 09:59:20 +02:00
Elio Struyf 0ed93977bc #650 - Use the templates repo 2023-09-09 16:56:58 +02:00
Elio Struyf a2d1100123 #657 - Windows script outcome fix 2023-09-08 13:29:41 +02:00
Elio Struyf 160d901358 Removed draft toggle + Added fm action 2023-09-07 21:57:40 +02:00
Elio Struyf 0c613187bf Added environment 2023-09-07 16:56:05 +02:00
Elio Struyf 1128b5ac65 #655 - Refresh settings 2023-09-07 16:40:59 +02:00
Elio Struyf c6ec07fa17 #654 - Add the open on website action 2023-09-07 16:25:52 +02:00
Elio Struyf 3f578fdfa9 Grouping and status tabs enhancements 2023-09-07 14:50:13 +02:00
Elio Struyf c5cb1bbb06 #652 - start/stop server enhancements 2023-09-07 12:11:14 +02:00
Elio Struyf 3001e9f3cc #651 - fix setting listeners 2023-09-07 11:52:34 +02:00
Elio Struyf eb5bdd6119 #650 - add max level 2023-09-06 18:08:37 +02:00
Elio Struyf 802e34890a Update color 2023-09-06 16:17:39 +02:00
Elio Struyf 1041429e84 Update framework reference #650 2023-09-06 16:01:28 +02:00
Elio Struyf 5139453ae9 #650 - Add template support 2023-09-06 15:59:30 +02:00
Elio Struyf 7b6be79bb0 #649 - Update snippet parser 2023-09-06 13:42:33 +02:00
Elio Struyf 3469771a02 Align button text 2023-09-06 12:21:36 +02:00
Elio Struyf 65f15c54f4 Fix chatbot 2023-09-06 12:09:24 +02:00
Elio Struyf e7478aecc6 Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-09-06 12:06:25 +02:00
Elio Struyf 69a18bdcea #570 - Clear empty values 2023-09-06 12:06:19 +02:00
Elio Struyf 83f15b65a4 #648 - update schema reference 2023-09-05 11:46:32 +02:00
Elio Struyf b16fc4dfbb Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-09-05 10:58:31 +02:00
Elio Struyf 40f7ca5a2f Return empty array on empty project 2023-09-05 10:58:20 +02:00
Elio Struyf ab3988e253 #647 - Fix open in browser 2023-09-04 17:18:18 +02:00
Elio Struyf c6cfc02e5d #646 - Update Astro port 2023-09-04 16:56:45 +02:00
Elio Struyf f93b6bae3e Updated changelog 2023-09-04 16:55:25 +02:00
Elio Struyf 1b88ff9932 Merge branch 'cba85-main' into dev 2023-08-31 17:01:49 +02:00
Elio Struyf 6e964a58c1 Merge branch 'main' of github.com:cba85/vscode-front-matter into cba85-main 2023-08-31 17:01:32 +02:00
Elio Struyf 01b45e43b8 9.2.0 2023-08-31 17:00:08 +02:00
Elio Struyf 4f11c8347a Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-08-31 16:59:57 +02:00
Clément Barbaza e4530ee5ca add french translation 2023-08-31 15:48:50 +02:00
Elio Struyf 8e197ab865 Merge pull request #644 from estruyf/dev 2023-08-31 09:36:30 +02:00
Elio Struyf db3e12cc56 Update changelog 2023-08-31 09:36:13 +02:00
Elio Struyf 959aa5a03c Audit fixes 2023-08-31 09:28:53 +02:00
Elio Struyf ad58ed2967 Update changelog 2023-08-31 09:22:21 +02:00
Elio Struyf e6d93bbf5d Update changelog 2023-08-30 17:07:55 +02:00
Elio Struyf 13eede26ce Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-08-30 15:51:13 +02:00
Elio Struyf 00b3e195a8 #641 - file parse 2023-08-30 15:51:05 +02:00
Elio Struyf dc590e53d8 #642 - Store the search index in a storage file 2023-08-30 15:27:11 +02:00
Elio Struyf becdec6bc2 Updated ignore 2023-08-30 14:28:45 +02:00
Elio Struyf 3af8b62b7d Remove files 2023-08-30 14:27:25 +02:00
Elio Struyf 06f65c3627 #639 - Add check for content type in page folders 2023-08-30 13:57:38 +02:00
Elio Struyf e3bbcf252c Remove logging 2023-08-25 13:24:41 +02:00
Elio Struyf 0ac04d2247 #636 - Fix lightbox theme issues 2023-08-25 13:24:10 +02:00
Elio Struyf 4c7d5bacea #635 - Fix navigation theming issues 2023-08-25 13:23:58 +02:00
Elio Struyf 16762a5fa5 #634 - Process relative public folders 2023-08-25 11:41:06 +02:00
Elio Struyf a6c0685184 #633 - Fix custom taxonomy used as single value 2023-08-25 10:53:42 +02:00
Elio Struyf 38e485584f Fix on empty path 2023-08-22 14:08:02 +02:00
Elio Struyf faf8e66cdb Merge branch 'dev' of github.com:estruyf/vscode-front-matter into dev 2023-08-22 11:52:36 +02:00
Elio Struyf dc5a48ea89 #628 - Fix path and data argument 2023-08-22 11:52:00 +02:00
Elio Struyf 5435a6c42a Update fm 2023-08-22 09:54:01 +02:00
Elio Struyf 0b722e3dba Update changelog 2023-08-22 09:50:33 +02:00
Elio Struyf f1130aaf96 9.1.0 2023-08-22 09:48:52 +02:00
Elio Struyf 26c9033299 Merge pull request #630 from kasuken/dev 2023-08-22 09:48:38 +02:00
Emanuele Bartolesi a8909fadc2 italian translations fix 2023-08-21 14:52:55 +02:00
Emanuele Bartolesi cda6d8ddaa italian translations 2023-08-21 14:52:01 +02:00
Emanuele Bartolesi 8fd7355878 Create bundlel10n.it.json 2023-08-21 13:13:09 +02:00
91 changed files with 2247 additions and 717 deletions
+7 -6
View File
@@ -7,19 +7,21 @@ on:
jobs:
build:
name: "Build and release"
name: 'Build and release'
runs-on: ubuntu-latest
environment:
name: Beta
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
registry-url: https://registry.npmjs.org/
- name: Install the dependencies
run: npm i
- name: Prepare BETA
run: node scripts/beta-release.js $GITHUB_RUN_ID
@@ -28,4 +30,3 @@ jobs:
- name: Publish to open-vsx.org
run: npx ovsx publish -p ${{ secrets.OPEN_VSX_PAT }}
+8 -6
View File
@@ -7,19 +7,21 @@ on:
jobs:
build:
name: "Build and release"
name: 'Build and release'
runs-on: ubuntu-latest
environment:
name: Stable
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
registry-url: https://registry.npmjs.org/
- name: Install the dependencies
run: npm i
- name: Prepare MAIN release
run: node scripts/main-release.js
@@ -27,4 +29,4 @@ jobs:
run: npx @vscode/vsce publish -p ${{ secrets.VSCE_PAT }}
- name: Publish to open-vsx.org
run: npx ovsx publish -p ${{ secrets.OPEN_VSX_PAT }}
run: npx ovsx publish -p ${{ secrets.OPEN_VSX_PAT }}
+2
View File
@@ -5,6 +5,7 @@ src/**
.gitignore
vsc-extension-quickstart.md
**/tsconfig.json
**/tsconfig.e2e.json
**/*.map
**/*.ts
webpack.config.js
@@ -28,3 +29,4 @@ webpack
README.beta.md
e2e
storage
pnpm-lock.yaml
+45
View File
@@ -1,5 +1,50 @@
# Change Log
## [9.2.0] - 2023-09-11
### ✨ New features
- [#650](https://github.com/estruyf/vscode-front-matter/issues/650): Added template support for [Astro Starlight](https://starlight.astro.build/)
- [#655](https://github.com/estruyf/vscode-front-matter/issues/655): Added a new command to manually refresh the settings of the Front Matter CMS
### 🎨 Enhancements
- Grouping and status tabs enhancements
- Removed the status bar item to toggle the draft field
- Added a FM status bar item to open the dashboard
- [#570](https://github.com/estruyf/vscode-front-matter/issues/570): Clear empty values on content creation and editing
- [#645](https://github.com/estruyf/vscode-front-matter/issues/645): French localization added (thanks to [Clément Barbaza](https://github.com/cba85))
- [#649](https://github.com/estruyf/vscode-front-matter/issues/649): Parse optional variables from snippets
- [#652](https://github.com/estruyf/vscode-front-matter/issues/652): Show the start/stop server buttons depending on the local terminal session
### 🐞 Fixes
- [#646](https://github.com/estruyf/vscode-front-matter/issues/646): Update the Astro `3000` port to `4321`
- [#647](https://github.com/estruyf/vscode-front-matter/issues/647): Fix the open in browser action on the preview
- [#648](https://github.com/estruyf/vscode-front-matter/issues/648): Fix the global configuration reference to the URL of the schema file
- [#651](https://github.com/estruyf/vscode-front-matter/issues/651): Fix settings listeners which did not push updates to the webviews
- [#657](https://github.com/estruyf/vscode-front-matter/issues/657): Fix correctly updating front matter with scripts outcome on Windows
## [9.1.0] - 2023-08-31
### ✨ New features
- [#630](https://github.com/estruyf/vscode-front-matter/issues/630): Italian localization added (thanks to [Emanuele Bartolesi](https://github.com/kasuken))
### ⚡️ Optimizations
- [#639](https://github.com/estruyf/vscode-front-matter/issues/639): Add check for content type in page folders setting
- [#642](https://github.com/estruyf/vscode-front-matter/issues/642): Store the search index in a storage file
### 🐞 Fixes
- [#628](https://github.com/estruyf/vscode-front-matter/issues/628): Fix path argument and JSON data on custom scripts
- [#633](https://github.com/estruyf/vscode-front-matter/issues/633): Fix custom taxonomy used as single value
- [#634](https://github.com/estruyf/vscode-front-matter/issues/634): Fix public folder processing in case of Hexo
- [#635](https://github.com/estruyf/vscode-front-matter/issues/635): Fix UI themes make some links hard to discover or see
- [#636](https://github.com/estruyf/vscode-front-matter/issues/636): Fix media browser lightbox background color
- [#641](https://github.com/estruyf/vscode-front-matter/issues/641): Fix file parsing of the localization file
## [9.0.0] - 2023-08-21 - [Release notes](https://beta.frontmatter.codes/updates/v9.0.0)
### 🌎 Multilingual support
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

+1
View File
@@ -1,5 +1,6 @@
{
"$schema": "https://beta.frontmatter.codes/frontmatter.schema.json",
"frontMatter.snippets.wrapper.enabled": false,
"frontMatter.framework.id": "other",
"frontMatter.content.publicFolder": "",
"frontMatter.content.pageFolders": [
+5 -1
View File
@@ -332,5 +332,9 @@
"dashboard.steps.stepsToGetStarted.assetsFolder.description": "Wählen Sie den Ordner aus, der Ihre Assets enthält. In diesem Ordner werden alle Ihre Mediendateien für Ihre Artikel gespeichert.",
"dashboard.steps.stepsToGetStarted.assetsFolder.public.title": "Verwende den 'public'-Ordner",
"dashboard.steps.stepsToGetStarted.assetsFolder.assets.title": "Verwende den Astro-Assets-Ordner (src/assets)",
"dashboard.steps.stepsToGetStarted.assetsFolder.other.description": "Wenn Sie einen anderen Ordner konfigurieren möchten, können Sie dies manuell in der frontmatter.json-Datei tun."
"dashboard.steps.stepsToGetStarted.assetsFolder.other.description": "Wenn Sie einen anderen Ordner konfigurieren möchten, können Sie dies manuell in der frontmatter.json-Datei tun.",
"dashboard.steps.stepsToGetStarted.template.name": "Verwende eine Konfigurationsvorlage",
"dashboard.steps.stepsToGetStarted.template.description": "Wählen Sie eine Vorlage aus, um die Datei frontmatter.json mit den empfohlenen Einstellungen vorzufüllen.",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "Vorlagendateien kopiert.",
"common.openOnWebsite": "Auf der Website öffnen"
}
+340
View File
@@ -0,0 +1,340 @@
{
"common.add": "Ajouter",
"common.edit": "Modifier",
"common.delete": "Supprimer",
"common.cancel": "Annuler",
"common.clear": "Réinitialiser",
"common.clear.value": "Réinitialiser la valeur",
"common.search": "Rechercher",
"common.save": "Sauvegarder",
"common.menu": "Menu",
"common.insert": "Insérer",
"common.insert.snippet": "Insérer snippet",
"common.title": "Titre",
"common.description": "Description",
"common.retry": "Réessayer",
"common.update": "Mettre à jour",
"common.information": "Information",
"common.important": "Important",
"common.sync": "Synchroniser",
"common.slug": "Slug",
"common.support": "Support",
"common.remove.value": "Supprimer {0}",
"common.error.message": "Désolé, une erreur s'est produite.",
"developer.title": "Mode développeur",
"developer.reload.title": "Recharger le tableau de bord",
"developer.reload.label": "Recharger",
"developer.devTools.title": "Ouvrir les options pour les développeurs",
"developer.devTools.label": "Options pour les développeurs",
"field.required": "Champ obligatoire",
"field.unknown": "Champ inconnu",
"dashboard.chatbot.answer.answer": "Réponse",
"dashboard.chatbot.answer.resources": "Ressources",
"dashboard.chatbot.answer.warning": "Attention : les réponses peuvent être fausses. En cas de doute, consultez la documentation.",
"dashboard.chatbot.chatbot.loading": "L'assistant se charge",
"dashboard.chatbot.chatbot.ready": "Je suis prêt, que voulez-vous savoir ?",
"dashboard.chatbot.chatbox.placeholder": "Comment configurer Front Matter ?",
"dashboard.chatbot.header.heading": "Demander à Front Matter AI",
"dashboard.chatbot.header.description": "Notre IA, propulsée par mendable.ai, a élaboré la documentation et peut maintenant vous aider concernant n'importe quelle demande sur Front Matter. Allez-y, demandez lui quelque chose!",
"dashboard.common.choiceButton.open": "Ouvrir les options",
"dashboard.contents.contentActions.actionMenuButton.title": "Menu",
"dashboard.contents.contentActions.menuItem.view": "Vue",
"dashboard.contents.contentActions.alert.title": "Supprimer : {0}",
"dashboard.contents.contentActions.alert.description": "Etes-vous sûr de vouloir supprimer le contenu \"{0}\" ?",
"dashboard.contents.item.invalidTitle": "<titre invalide>",
"dashboard.contents.item.invalidDescription": "<description invalide>",
"dashboard.contents.list.title": "Titre",
"dashboard.contents.list.date": "Date",
"dashboard.contents.list.status": "Statut",
"dashboard.contents.overview.noMarkdown": "Aucun Markdown à afficher",
"dashboard.contents.overview.noFolders": "Enregistez un dossier de contenu dans votre projet pour que Front Matter puisse trouver vos contenus.",
"dashboard.contents.status.draft": "Brouillon",
"dashboard.contents.status.published": "En-ligne",
"dashboard.dataView.dataForm.modify": "Modifier les données",
"dashboard.dataView.dataForm.add": "Ajouter une nouvelle donnée",
"dashboard.dataView.dataView.select": "Sélectionnez votre type de donnée",
"dashboard.dataView.dataView.title": "Votre entrée de donnée {0}",
"dashboard.dataView.dataView.add": "Ajouter une nouvelle entrée",
"dashboard.dataView.dataView.empty": "Aucune entrée trouvée pour {0}",
"dashboard.dataView.dataView.createOrModify": "Créer ou modifier votre donnée {0}",
"dashboard.dataView.dataView.getStarted": "Sélectionnez un type de données pour commencer",
"dashboard.dataView.dataView.noDataFiles": "Aucun fichier de données trouvé",
"dashboard.dataView.dataView.getStarted.link": "En savoir plus sur l'utilisation des données",
"dashboard.dataView.emptyView.heading": "Sélectionnez d'abord votre type de données",
"dashboard.dataView.sortableItem.editButton.title": "Modifier \"{0}\"",
"dashboard.dataView.sortableItem.deleteButton.title": "Supprimer \"{0}\"",
"dashboard.dataView.sortableItem.alert.title": "Supprimer la valeur",
"dashboard.dataView.sortableItem.alert.description": "Etes-vous sûr de vouloir supprimer cette valeur?",
"dashboard.errorView.description": "Merci de fermer le tableau de bord et de réessayer.",
"dashboard.header.breadcrumb.home": "Accueil",
"dashboard.header.clearFilters.title": "Réinitialiser les filtres, les groupes et le tri",
"dashboard.header.filter.default": "Aucun filtre",
"dashboard.header.folders.default": "Tous les types",
"dashboard.header.folders.menuButton.showing": "Afficher",
"dashboard.header.grouping.option.none": "Aucun",
"dashboard.header.grouping.option.year": "Année",
"dashboard.header.grouping.option.draft": "Brouillon/En-ligne",
"dashboard.header.grouping.menuButton.label": "Groupé par",
"dashboard.header.navigation.allArticles": "Tous les articles",
"dashboard.header.navigation.published": "En-ligne",
"dashboard.header.navigation.draft": "Brouillon",
"dashboard.header.header.createContent": "Créer contenu",
"dashboard.header.header.createByContentType": "Créer par type de contenu",
"dashboard.header.header.createByTemplate": "Créer par modèle",
"dashboard.header.pagination.first": "Premier",
"dashboard.header.pagination.previous": "Précédent",
"dashboard.header.pagination.next": "suivant",
"dashboard.header.pagination.last": "Dernier",
"dashboard.header.paginationStatus.text": "Afficher {0} de {1} des {2} résultats",
"dashboard.header.projectSwitcher.label": "projet",
"dashboard.header.refreshDashboard.label": "Actualiser le dashboard",
"dashboard.header.sorting.lastModified.asc": "Dernière modification (croissant)",
"dashboard.header.sorting.lastModified.desc": "Dernière modification (décroissant)",
"dashboard.header.sorting.filename.asc": "Par nom de fichier (croissant)",
"dashboard.header.sorting.filename.desc": "Par nom de fichier (décroissant)",
"dashboard.header.sorting.published.asc": "En-ligne (croissant)",
"dashboard.header.sorting.published.desc": "En-ligne (décroissant)",
"dashboard.header.sorting.size.asc": "Taille (croissant)",
"dashboard.header.sorting.size.desc": "Taille (décroissant)",
"dashboard.header.sorting.caption.asc": "Légende (croissant)",
"dashboard.header.sorting.caption.desc": "Légende (décroissant)",
"dashboard.header.sorting.alt.asc": "Alt (croissant)",
"dashboard.header.sorting.alt.desc": "Alt (décroissant)",
"dashboard.header.sorting.label": "Trier par",
"dashboard.header.startup.label": "Ouvrir au démarrage?",
"dashboard.header.tabs.contents": "Contenus",
"dashboard.header.tabs.media": "Médias",
"dashboard.header.tabs.snippets": "Snippets",
"dashboard.header.tabs.data": "données",
"dashboard.header.tabs.taxonomies": "Taxonomies",
"dashboard.header.viewSwitch.toGrid": "Afficher en grille",
"dashboard.header.viewSwitch.toList": "Afficher en liste",
"dashboard.layout.sponsor.support.msg": "Soutenir Front Matter",
"dashboard.layout.sponsor.review.label": "Donnez votre avis",
"dashboard.layout.sponsor.review.msg": "Donnez votre avis sur Front Matter",
"dashboard.media.common.title": "Titre",
"dashboard.media.common.caption": "Légende",
"dashboard.media.common.alt": "Texte alternatif",
"dashboard.media.common.size": "Taille",
"dashboard.media.dialog.title": "Voir les détails",
"dashboard.media.panel.close": "Fermer le panneau",
"dashboard.media.metadata.panel.title": "Mettre à jour les métadonnées",
"dashboard.media.metadata.panel.description": "Spécifiez les métadonnées que vous voulez utiliser pour ce fichier.",
"dashboard.media.metadata.panel.field.fileName": "Nom de fichier",
"dashboard.media.metadata.panel.form.metadata.title": "Métadonnées",
"dashboard.media.metadata.panel.form.information.title": "Information",
"dashboard.media.metadata.panel.form.information.createdDate": "Créé",
"dashboard.media.metadata.panel.form.information.modifiedDate": "Dernières modifications",
"dashboard.media.metadata.panel.form.information.dimensions": "Dimensions",
"dashboard.media.metadata.panel.form.information.folder": "Dossier",
"dashboard.media.folderCreation.hexo.create": "Créer un dossier de ressource de l'article",
"dashboard.media.folderCreation.folder.create": "Créer un nouveau dossier",
"dashboard.media.item.quickAction.insert.field": "Insérer une image pour le champ \"{0}\"",
"dashboard.media.item.quickAction.insert.markdown": "Insérer une image avec le markup markdown",
"dashboard.media.item.quickAction.copy.path": "Copier le chemin du média",
"dashboard.media.item.quickAction.delete": "Supprimer le fichier du média",
"dashboard.media.item.menuItem.edit.metadata": "Modifier les métadonnées",
"dashboard.media.item.menuItem.insert.image": "Insérer une image",
"dashboard.media.item.menuItem.reveal.media": "Afficher le média",
"dashboard.media.item.infoDialog.snippet.description": "Sélectionnez le snippet de média à utiliser pour le fichier de média courant.",
"dashboard.media.item.alert.delete.description": "Etes-vous sûr de vouloir supprimer le fichier du dossier {0} ?",
"dashboard.media.media.description": "Sélectionnez le fichier média à ajouter à votre contenu.",
"dashboard.media.media.dragAndDrop": "Vous pouvez aussi glisser-déposer des images depuis votre bureau et les sélectionner une fois envoyés.",
"dashboard.media.media.folder.upload": "Envoyer dans {0}",
"dashboard.media.media.folder.default": "Aucun dossier sélectionné, les fichiers que vous envoyez seront ajoutés au dossier {0}",
"dashboard.media.media.placeholder": "Aucun fichier de média à afficher. Vous pouvez glisser-déposer de nouveaux fichiers en maintenant la touche [shift] appuyée.",
"dashboard.media.media.contentFolder": "Dossier de contenu",
"dashboard.media.media.publicFolder": "Dossier public",
"dashboard.media.mediaHeaderTop.searchbox.placeholder": "Rechercher dans le dossier",
"dashboard.media.mediaSnippetForm.formDialog.title": "Insérer un média: {0}",
"dashboard.media.mediaSnippetForm.formDialog.description": "Insérer le fichier de média {0} dans l'article courant",
"dashboard.preview.input.placeholder": "Entrer une URL",
"dashboard.preview.button.navigate.title": "Naviguer",
"dashboard.preview.button.refresh.title": "Rafraichir",
"dashboard.preview.button.open.title": "Ouvrir",
"dashboard.snippetsView.item.quickAction.editSnippet": "Modifier le snippet",
"dashboard.snippetsView.item.quickAction.deleteSnippet": "Supprimer le snippet",
"dashboard.snippetsView.item.quickAction.viewSnippet": "Voir le fichier de snippet",
"dashboard.snippetsView.item.insert.formDialog.title": "Insérer le snippet: {0}",
"dashboard.snippetsView.item.insert.formDialog.description": "Insérer le snippet {0} dans l'article courant",
"dashboard.snippetsView.item.edit.formDialog.title": "Modifier le snippet: {0}",
"dashboard.snippetsView.item.edit.formDialog.description": "Modifier le snippet {0}",
"dashboard.snippetsView.item.alert.title": "Supprimer le snippet : {0}",
"dashboard.snippetsView.item.alert.description": "Etes-vous sûr de vouloir supprimer le snippet {0} ?",
"dashboard.snippetsView.newForm.snippetInput.title.placeholder": "Titre ",
"dashboard.snippetsView.newForm.snippetInput.description.label": "Description",
"dashboard.snippetsView.newForm.snippetInput.description.placeholder": "Description du snippet",
"dashboard.snippetsView.newForm.snippetInput.snippet.label": "Snippet",
"dashboard.snippetsView.newForm.snippetInput.snippet.placeholder": "Contenu du snippet",
"dashboard.snippetsView.newForm.snippetInput.isMediaSnippet.label": "Snippet média ?",
"dashboard.snippetsView.newForm.snippetInput.isMediaSnippet.checkbox.label": "Snippet média",
"dashboard.snippetsView.newForm.snippetInput.isMediaSnippet.checkbox.description": "Utiliser le snippet actuel pour insérer des fichiers médias dans votre contenu.",
"dashboard.snippetsView.newForm.snippetInput.docsButton.title": "En savoir plus sur l'utilisation des substituts de snippet médias",
"dashboard.snippetsView.newForm.snippetInput.docsButton.description": "Vérifier la documentation des substituts de snippet média pour savoir quel substitut utiliser.",
"dashboard.snippetsView.snippets.ariaLabel": "En-tête de snippet",
"dashboard.snippetsView.snippets.button.create": "Créer un nouveau snippet",
"dashboard.snippetsView.snippets.select.description": "Sélectionnez le snippet à ajouter à votre contenu.",
"dashboard.snippetsView.snippets.empty.message": "Aucun snippet trouvé",
"dashboard.snippetsView.snippets.readMore": "En savoir plus sur l'utilisation des snippets",
"dashboard.snippetsView.snippets.formDialog.title": "Créer un snippet",
"dashboard.steps.stepsToGetStarted.button.addFolder.title": "Ajouter un dossier de contenu à Front Matter",
"dashboard.steps.stepsToGetStarted.initializeProject.name": "Initialiser le projet",
"dashboard.steps.stepsToGetStarted.initializeProject.description": "Initialiser le projet crée les fichiers et dossiers nécéssaire au bon fonctionnement du CMS Front Matter. Commencez par cliquer sur cette action.",
"dashboard.steps.stepsToGetStarted.framework.name": "Réglages framework",
"dashboard.steps.stepsToGetStarted.framework.description": "Sélectionnez votre générateur de site ou votre framework pour pré-remplir les paramètres recommandés.",
"dashboard.steps.stepsToGetStarted.framework.select": "Sélectionnez votre framework",
"dashboard.steps.stepsToGetStarted.framework.select.other": "autre",
"dashboard.steps.stepsToGetStarted.assetsFolder.name": "Quel est votre dossier de ressources ?",
"dashboard.steps.stepsToGetStarted.assetsFolder.description": "Sélectionner le dossier contenant vos ressources. Ce dossier sera utilisé pour stocker tous les fichiers médias de vos articles.",
"dashboard.steps.stepsToGetStarted.assetsFolder.public.title": "Utiliser le dossier 'public'",
"dashboard.steps.stepsToGetStarted.assetsFolder.assets.title": "Utiliser le dossier de ressources d'Astro (src/assets)",
"dashboard.steps.stepsToGetStarted.assetsFolder.other.description": "Si vous voulez configurer un autre dossier, vous pouvez le faire manuellement dans le fichier frontmatter.json.",
"dashboard.steps.stepsToGetStarted.contentFolders.name": "Enregistrer le ou less dossiers de contenus ?",
"dashboard.steps.stepsToGetStarted.contentFolders.description": "Ajouter un des dossiers que nous avons trouvé dans votre projet en tant que dossier de contenus. Une fois ce dossier sélectionné, Front Matter pourra lister tous les contenus et vous permettra de créer vos contenus.",
"dashboard.steps.stepsToGetStarted.contentFolders.label": "Dossiers contenant des contenus :",
"dashboard.steps.stepsToGetStarted.contentFolders.information.description": "Vous pouvez aussi effectuer cette action en faisant un clic droit sur le dossier dans la vue d'exploration, et sélectionner le dossier à enregister.",
"dashboard.steps.stepsToGetStarted.tags.name": "Importer tous les tags et toutes les catégories (optionnel)",
"dashboard.steps.stepsToGetStarted.tags.description": "Maintenant que Front Matter connaît tous vos dossiers de contenus, voulez-vous importer tous les tags et toutes les catégories de ces contenus ?",
"dashboard.steps.stepsToGetStarted.showDashboard.name": "Afficher le tableau de bord",
"dashboard.steps.stepsToGetStarted.showDashboard.description": "Une fois que toutes ces actions sont effectuées, le tableau de bord pourra être chargé.",
"dashboard.taxonomyView.button.add.title": "Ajouter {0} aux paramètres de taxonomie",
"dashboard.taxonomyView.button.edit.title": "Modifier {0}",
"dashboard.taxonomyView.button.merge.title": "Fusionner {0}",
"dashboard.taxonomyView.button.move.title": "Déplacer dans un autre type de taxonomie",
"dashboard.taxonomyView.button.delete.title": "Supprimer {0}",
"dashboard.taxonomyView.taxonomyLookup.button.title": "Afficher les contenus contenants {0} dans {1}",
"dashboard.taxonomyView.taxonomyManager.description": "Créer, modifier, et gérer le {0} de votre site",
"dashboard.taxonomyView.taxonomyManager.button.create": "Créer une nouvelle valeur pour {0}",
"dashboard.taxonomyView.taxonomyManager.table.heading.name": "Nom",
"dashboard.taxonomyView.taxonomyManager.table.heading.count": "Compteur",
"dashboard.taxonomyView.taxonomyManager.table.heading.action": "Action",
"dashboard.taxonomyView.taxonomyManager.table.row.empty": "Aucun {0} trouvé",
"dashboard.taxonomyView.taxonomyManager.table.unmapped.title": "Paramètre manquant",
"dashboard.taxonomyView.taxonomyView.navigationBar.title": "Sélectionnez la taxonomie",
"dashboard.taxonomyView.taxonomyView.button.import": "Importer la taxonomie",
"dashboard.taxonomyView.taxonomyView.navigationItem.tags": "Tags",
"dashboard.taxonomyView.taxonomyView.navigationItem.categories": "Catégories",
"dashboard.unkownView.title": "La vue n'existe pas",
"dashboard.unkownView.description": "Il semble que vous ayez fermé une vue qui n'existe plus. Merci de réouvrir votre tableau de bord.",
"dashboard.welcomeScreen.title": "Gérer votre site statique avec Front Matter",
"dashboard.welcomeScreen.thanks": "Merci d'utiliser Front Matter !",
"dashboard.welcomeScreen.description": "Nous faisons de notre mieux pour faire de Front Maker un CMS facile à utiliser. Si vous avez des questions ou des suggestions, n'hésitez pas à nous contacter sur Github.",
"dashboard.welcomeScreen.link.github.title": "GitHub",
"dashboard.welcomeScreen.link.github.label": "GitHub / Documentation",
"dashboard.welcomeScreen.link.sponsor.title": "Devenez contributeur",
"dashboard.welcomeScreen.link.sponsor.label": "Contributeur",
"dashboard.welcomeScreen.link.review.title": "Donnez votre avis",
"dashboard.welcomeScreen.link.review.label": "Avis",
"dashboard.welcomeScreen.actions.heading": "Effectuez les étapes suivants pour commencer à utiliser l'extension",
"dashboard.welcomeScreen.actions.description": "Vous pouvez aussi utiliser l'extension depuis la barre latérale Front Matter. Vous trouverez les actions à effectuer spécifiquement pour vos pages.",
"dashboard.welcomeScreen.actions.thanks": "Nous espérons que vous aimez Front Matter !",
"panel.contentType.contentTypeValidator.title": "Type de contenu",
"panel.contentType.contentTypeValidator.hint": "Nous avons remarqué des différences entre le type de contenu et les données front matter.\n Voulez vous créer, mettre à jour ou définir le type de contenu pour ce contenu ?",
"panel.contentType.contentTypeValidator.button.create": "Créer un type de contenu",
"panel.contentType.contentTypeValidator.button.add": "Ajouter les champs manquants au type de contenu",
"panel.contentType.contentTypeValidator.button.change": "Changer le type de contenu du fichier",
"panel.dataBlock.dataBlockField.group.selected.edit": "Modification: {0}",
"panel.dataBlock.dataBlockField.group.selected.create": "Créer un nouveau {0}",
"panel.dataBlock.dataBlockField.group.select": "Sélectionner un groupe",
"panel.dataBlock.dataBlockField.add": "Ajouter {0}",
"panel.dataBlock.dataBlockRecord.edit": "Modifier l'enregistrement",
"panel.dataBlock.dataBlockRecord.delete": "Supprimer l'enregistrement",
"panel.dataBlock.dataBlockRecords.label": "Enregistrements",
"panel.dataBlock.dataBlockSelector.label": "Type de bloc",
"panel.errorBoundary.fieldBoundary.label": "Echec d'affichage du champ",
"panel.fields.choiceField.select": "Sélectionner {0}",
"panel.fields.choiceField.clear": "Réinitialiser la valeur",
"panel.fields.contentTypeRelationshipField.loading": "Récupération des valeurs possible...",
"panel.fields.dateTimeField.button.pick": "Choisissez votre date",
"panel.fields.dateTimeField.time": "Heure :",
"panel.fields.fieldMessage.required": "Le champ {0} est obligatoire",
"panel.fields.fileField.delete": "Supprimer le fichier",
"panel.fields.fileField.add": "Ajouter votre {0}",
"panel.fields.imageFallback.label": "L'image ne peut pas être chargée",
"panel.fields.listField.edit": "Modifier l'enregistrement",
"panel.fields.listField.delete": "Supprimer l'enregistrement",
"panel.fields.previewImage.remove": "Supprimer l'image",
"panel.fields.previewImageField.add": "Ajouter votre {0}",
"panel.fields.slugField.update": "Mise à jour disponible",
"panel.fields.slugField.generate": "Générer le slug",
"panel.fields.textField.ai.message": "Utiliser Front Matter AI pour suggérer {0}",
"panel.fields.textField.ai.generate": "Génération de la suggestion...",
"panel.fields.textField.loading": "Chargement",
"panel.fields.textField.limit": "Limite de champ atteinte {0}",
"panel.fields.wrapperField.unknown": "Type de champ inconnu : {0}",
"panel.actions.title": "Actions",
"panel.articleDetails.title": "Plus de détails",
"panel.articleDetails.type": "Type",
"panel.articleDetails.total": "Total",
"panel.articleDetails.headings": "En-têtes",
"panel.articleDetails.paragraphs": "Paragraphes",
"panel.articleDetails.internalLinks": "Liens internes",
"panel.articleDetails.externalLinks": "Liens externes",
"panel.articleDetails.images": "Images",
"panel.baseView.initialize": "Initialiser le projet",
"panel.baseView.actions.title": "Actions",
"panel.baseView.action.openDashboard": "Ouvrir le tableau de bord",
"panel.baseView.action.openPreview": "Ouvrir la prévisualisation",
"panel.baseView.action.createContent": "Créer le contenu",
"panel.baseView.empty": "Ouvrir un fichier pour afficher plus d'actions",
"panel.fileList.label.singular": "fichier",
"panel.fileList.label.plural": "fichiers",
"panel.folderAndFiles.title": "Récemment modifié",
"panel.globalSettings.title": "Paramètres globaux",
"panel.globalSettings.action.modifiedDate.label": "Date de modification",
"panel.globalSettings.action.modifiedDate.description": "Mettre à jour automatiquement la date de modification",
"panel.globalSettings.action.frontMatter.label": "Front Matter highlight",
"panel.globalSettings.action.frontMatter.description": "Highlight Front Matter",
"panel.globalSettings.action.preview.label": "Prévisualisation locale",
"panel.globalSettings.action.preview.placeholder": "Exemple : {0}",
"panel.globalSettings.action.server.label": "Commande de server local",
"panel.globalSettings.action.server.placeholder": "Exemple : {0}",
"panel.metadata.title": "Métadonnées",
"panel.otherActions.title": "Autres actions",
"panel.otherActions.writingSettings.enabled": "Paramètres d'écriture activés",
"panel.otherActions.writingSettings.disabled": "Activer les paramètres d'écriture",
"panel.otherActions.centerMode": "Basculer le mode central",
"panel.otherActions.createTemplate": "Créer modèle",
"panel.otherActions.revealFile": "Afficher le fichier dans le dossier",
"panel.otherActions.openProject": "Afficher le dossier du projet",
"panel.otherActions.documentation": "Ouvrir la documentation",
"panel.otherActions.settings": "Paramètres globaux",
"panel.otherActions.issue": "Signaler un problème",
"panel.preview.title": "Ouvrir la prévisualisation",
"panel.publishAction.publish": "Publié",
"panel.publishAction.unpublish": "Retourner au brouillon",
"panel.seoDetails.recommended": "Recommandé",
"panel.seoKeywordInfo.density": "Utilisation du mot clé {0} *",
"panel.seoKeywordInfo.validInfo.label": "Utilisé dans le ou les en-tête(s)",
"panel.seoKeywordInfo.validInfo.content": "Contenu",
"panel.seoKeywords.title": "Mot-clés",
"panel.seoKeywords.header.keyword": "Mot-clé",
"panel.seoKeywords.header.details": "Détails",
"panel.seoKeywords.density": "* Une densité de mot-clé de 1-1.5% est suffisante dans la plupart des cas",
"panel.seoStatus.title": "Recommandations",
"panel.seoStatus.header.property": "Propriété",
"panel.seoStatus.header.length": "Longueur",
"panel.seoStatus.header.valid": "Valide",
"panel.seoStatus.seoFieldInfo.characters": "{0} caractères",
"panel.seoStatus.seoFieldInfo.words": "{0} mots",
"panel.seoStatus.seoFieldInfo.article": "Longueur de l'article",
"panel.seoStatus.collapsible.title": "Statut SEO",
"panel.seoStatus.required": "{0} ou {1} est requis.",
"panel.slugAction.title": "Optimisation du slug",
"panel.spinner.loading": "Chargement...",
"panel.startServerbutton.start": "Démarrer le serveur",
"panel.startServerbutton.stop": "Arrêter le serveur",
"panel.tag.add": "Ajouter {0} à vos paramètres",
"panel.tagPicker.inputPlaceholder.empty": "Choisissez votre {0}",
"panel.tagPicker.inputPlaceholder.disabled": "Vous avez atteint la limite de {0}",
"panel.tagPicker.ai.suggest": "Utiliser Front Matter AI pour suggérer {0}",
"panel.tagPicker.ai.generating": "Génération des suggestions...",
"panel.tagPicker.limit": "Max : {0}",
"panel.tagPicker.unkown": "Ajouter le tag non-classé",
"panel.tags.tag.warning": "Attention, ce tag \"{0}\" n'est pas enregistré dans vos paramètres. Une fois supprimé, il sera définitivement supprimé.",
"panel.viewPanel.mediaInsert": "Continuer dans le tableau de bord des médias pour sélectionner l'image que vous voulez insérer.",
"dashboard.steps.stepsToGetStarted.template.name": "Utiliser un modèle de configuration",
"dashboard.steps.stepsToGetStarted.template.description": "Sélectionnez un modèle pour préremplir le fichier frontmatter.json avec les paramètres recommandés.",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "Fichiers de modèle copiés.",
"common.openOnWebsite": "Ouvrir sur le site web"
}
+340
View File
@@ -0,0 +1,340 @@
{
"common.add": "Aggiungi",
"common.edit": "Modifica",
"common.delete": "Elimina",
"common.cancel": "Annulla",
"common.clear": "Pulisci",
"common.clear.value": "Pulisci valore",
"common.search": "Ricerca",
"common.save": "Salva",
"common.menu": "Menu",
"common.insert": "Inserisci",
"common.insert.snippet": "Inserisci snippet",
"common.title": "Titolo",
"common.description": "Descrizione",
"common.retry": "Riprova",
"common.update": "Aggiorna",
"common.information": "Informazioni",
"common.important": "Importante",
"common.sync": "Sincronizza",
"common.slug": "Slug",
"common.support": "Supporto",
"common.remove.value": "Rimuovi {0}",
"common.error.message": "Siamo spiacenti, qualcosa è andato storto.",
"developer.title": "Modalità sviluppatore",
"developer.reload.title": "Ricarica la dashboard",
"developer.reload.label": "Ricarica",
"developer.devTools.title": "Apri DevTools",
"developer.devTools.label": "DevTools",
"field.required": "Campo obbligatorio",
"field.unknown": "Campo sconosciuto",
"dashboard.chatbot.answer.answer": "Risposta",
"dashboard.chatbot.answer.resources": "Risorse",
"dashboard.chatbot.answer.warning": "Attenzione: Answers potrebbe sbagliarsi. In caso di dubbio, si prega di consultare la documentazione.",
"dashboard.chatbot.chatbot.loading": "L'assistente si sta preparando",
"dashboard.chatbot.chatbot.ready": "Sono pronto, cosa vuoi sapere?",
"dashboard.chatbot.chatbox.placeholder": "Come posso configurare Front Matter?",
"dashboard.chatbot.header.heading": "Chiedi a Front Matter AI",
"dashboard.chatbot.header.description": "La nostra intelligenza artificiale, alimentata da mendable.ai, ha elaborato la documentazione e può assisterti con qualsiasi domanda relativa a Front Matter. Vai avanti e chiedi!",
"dashboard.common.choiceButton.open": "Apri opzioni",
"dashboard.contents.contentActions.actionMenuButton.title": "Menu",
"dashboard.contents.contentActions.menuItem.view": "Vista",
"dashboard.contents.contentActions.alert.title": "Elimina: {0}",
"dashboard.contents.contentActions.alert.description": "Sei sicuro di voler eliminare il contenuto \"{0}\"?",
"dashboard.contents.item.invalidTitle": "<titolo non valido>",
"dashboard.contents.item.invalidDescription": "<Descrizione non valida>",
"dashboard.contents.list.title": "Titolo",
"dashboard.contents.list.date": "Data",
"dashboard.contents.list.status": "Stato",
"dashboard.contents.overview.noMarkdown": "Nessun markdown da mostrare",
"dashboard.contents.overview.noFolders": "Assicurati di aver registrato una cartella di contenuti nel tuo progetto per consentire a Front Matter di trovare il contenuto.",
"dashboard.contents.status.draft": "Bozza",
"dashboard.contents.status.published": "Pubblicato",
"dashboard.dataView.dataForm.modify": "Modificare i dati",
"dashboard.dataView.dataForm.add": "Aggiungere nuovi dati",
"dashboard.dataView.dataView.select": "Seleziona il tuo tipo di dati",
"dashboard.dataView.dataView.title": "I tuoi {0} elementi di dati",
"dashboard.dataView.dataView.add": "Aggiungere una nuova voce",
"dashboard.dataView.dataView.empty": "Nessuna voce di dati {0} trovata",
"dashboard.dataView.dataView.createOrModify": "Creare o modificare i dati {0}",
"dashboard.dataView.dataView.getStarted": "Seleziona un tipo di dati per iniziare",
"dashboard.dataView.dataView.noDataFiles": "Nessun file di dati trovato",
"dashboard.dataView.dataView.getStarted.link": "Ulteriori informazioni per iniziare a utilizzare i file di dati",
"dashboard.dataView.emptyView.heading": "Seleziona prima il tipo di data",
"dashboard.dataView.sortableItem.editButton.title": "Modifica \"{0}\"",
"dashboard.dataView.sortableItem.deleteButton.title": "Elimina \"{0}\"",
"dashboard.dataView.sortableItem.alert.title": "Eliminare l'immissione dei dati",
"dashboard.dataView.sortableItem.alert.description": "Sei sicuro di voler cancellare l'inserimento dei dati?",
"dashboard.errorView.description": "Chiudere la dashboard e riprovare.",
"dashboard.header.breadcrumb.home": "Home",
"dashboard.header.clearFilters.title": "Rimuovi filtri, raggruppamento e ordinamento",
"dashboard.header.filter.default": "Nessun filtro",
"dashboard.header.folders.default": "Tutti i tipi",
"dashboard.header.folders.menuButton.showing": "Risultati",
"dashboard.header.grouping.option.none": "Nessuno",
"dashboard.header.grouping.option.year": "Anno",
"dashboard.header.grouping.option.draft": "Bozza/Pubblicato",
"dashboard.header.grouping.menuButton.label": "Raggruppa per",
"dashboard.header.navigation.allArticles": "Tutti gli articoli",
"dashboard.header.navigation.published": "Pubblicato",
"dashboard.header.navigation.draft": "In bozza",
"dashboard.header.header.createContent": "Creare contenuti",
"dashboard.header.header.createByContentType": "Crea per tipo di contenuto",
"dashboard.header.header.createByTemplate": "Crea da modello",
"dashboard.header.pagination.first": "Primo",
"dashboard.header.pagination.previous": "Precedente",
"dashboard.header.pagination.next": "Prossimo",
"dashboard.header.pagination.last": "Ultimo",
"dashboard.header.paginationStatus.text": "Visualizzazione {0} a {1} di {2} risultati",
"dashboard.header.projectSwitcher.label": "progetto",
"dashboard.header.refreshDashboard.label": "Aggiorna dashboard",
"dashboard.header.sorting.lastModified.asc": "Ultima modifica (asc)",
"dashboard.header.sorting.lastModified.desc": "Ultima modifica (desc)",
"dashboard.header.sorting.filename.asc": "Per nome file (asc)",
"dashboard.header.sorting.filename.desc": "Per nome file (desc)",
"dashboard.header.sorting.published.asc": "Pubblicato (asc)",
"dashboard.header.sorting.published.desc": "Pubblicato (desc)",
"dashboard.header.sorting.size.asc": "Dimensione (asc)",
"dashboard.header.sorting.size.desc": "Dimensioni (desc)",
"dashboard.header.sorting.caption.asc": "Didascalia (asc)",
"dashboard.header.sorting.caption.desc": "Didascalia (desc)",
"dashboard.header.sorting.alt.asc": "Alt (asc)",
"dashboard.header.sorting.alt.desc": "Alt (desc)",
"dashboard.header.sorting.label": "Ordina per",
"dashboard.header.startup.label": "Aprire all'avvio?",
"dashboard.header.tabs.contents": "Contenuto",
"dashboard.header.tabs.media": "Media",
"dashboard.header.tabs.snippets": "Snippets",
"dashboard.header.tabs.data": "dati",
"dashboard.header.tabs.taxonomies": "Tassonomie",
"dashboard.header.viewSwitch.toGrid": "Passa alla griglia",
"dashboard.header.viewSwitch.toList": "Passa all'elenco",
"dashboard.layout.sponsor.support.msg": "Supporto Front Matter",
"dashboard.layout.sponsor.review.label": "Recensisci",
"dashboard.layout.sponsor.review.msg": "Recensisci Front Matter",
"dashboard.media.common.title": "Titolo",
"dashboard.media.common.caption": "Didascalia",
"dashboard.media.common.alt": "Testo alternativo",
"dashboard.media.common.size": "Dimensioni",
"dashboard.media.dialog.title": "Visualizza dettagli",
"dashboard.media.panel.close": "Chiudi pannello",
"dashboard.media.metadata.panel.title": "Aggiornare i metadati",
"dashboard.media.metadata.panel.description": "Specificare i metadati che si desidera impostare per il file.",
"dashboard.media.metadata.panel.field.fileName": "Filename",
"dashboard.media.metadata.panel.form.metadata.title": "Metadati",
"dashboard.media.metadata.panel.form.information.title": "Informazione",
"dashboard.media.metadata.panel.form.information.createdDate": "Creato",
"dashboard.media.metadata.panel.form.information.modifiedDate": "Ultima modifica",
"dashboard.media.metadata.panel.form.information.dimensions": "Dimensioni",
"dashboard.media.metadata.panel.form.information.folder": "Cartella",
"dashboard.media.folderCreation.hexo.create": "Creare una cartella di risorse",
"dashboard.media.folderCreation.folder.create": "Crea nuova cartella",
"dashboard.media.item.quickAction.insert.field": "Inserisci immagine per il campo \"{0}\"",
"dashboard.media.item.quickAction.insert.markdown": "Inserisci immagine con markup markdown",
"dashboard.media.item.quickAction.copy.path": "Copia percorso",
"dashboard.media.item.quickAction.delete": "Elimina file multimediale",
"dashboard.media.item.menuItem.edit.metadata": "Modificare i metadati",
"dashboard.media.item.menuItem.insert.image": "Inserisci immagine",
"dashboard.media.item.menuItem.reveal.media": "Rivela i media",
"dashboard.media.item.infoDialog.snippet.description": "Seleziona lo snippet del file multimediale da utilizzare per il file multimediale corrente.",
"dashboard.media.item.alert.delete.description": "Eliminare il file dalla cartella {0}?",
"dashboard.media.media.description": "Selezionare il file multimediale da aggiungere al contenuto.",
"dashboard.media.media.dragAndDrop": "Puoi anche trascinare e rilasciare le immagini dal desktop e selezionarle una volta caricate.",
"dashboard.media.media.folder.upload": "Carica su {0}",
"dashboard.media.media.folder.default": "Nessuna cartella selezionata, i file eliminati verranno aggiunti alla cartella {0}",
"dashboard.media.media.placeholder": "Nessun file multimediale da mostrare. Puoi trascinare e rilasciare nuovi file tenendo premuto il tasto [Maiusc].",
"dashboard.media.media.contentFolder": "Cartella dei contenuti",
"dashboard.media.media.publicFolder": "Cartella pubblica",
"dashboard.media.mediaHeaderTop.searchbox.placeholder": "Cerca nella cartella",
"dashboard.media.mediaSnippetForm.formDialog.title": "Inserisci supporto: {0}",
"dashboard.media.mediaSnippetForm.formDialog.description": "Inserire il file multimediale {0} nell'articolo corrente",
"dashboard.preview.input.placeholder": "Inserisci un URL",
"dashboard.preview.button.navigate.title": "Navigare",
"dashboard.preview.button.refresh.title": "Aggiorna",
"dashboard.preview.button.open.title": "Apri",
"dashboard.snippetsView.item.quickAction.editSnippet": "Modifica snippet",
"dashboard.snippetsView.item.quickAction.deleteSnippet": "Eliminare snippet",
"dashboard.snippetsView.item.quickAction.viewSnippet": "Visualizza file di frammento",
"dashboard.snippetsView.item.insert.formDialog.title": "Inserisci frammento: {0}",
"dashboard.snippetsView.item.insert.formDialog.description": "Inserisci il frammento di {0} nell'articolo corrente",
"dashboard.snippetsView.item.edit.formDialog.title": "Modifica Snippet: {0}",
"dashboard.snippetsView.item.edit.formDialog.description": "Modificare lo snippet {0}",
"dashboard.snippetsView.item.alert.title": "Elimina snippet: {0}",
"dashboard.snippetsView.item.alert.description": "Sei sicuro di voler eliminare lo snippet {0}?",
"dashboard.snippetsView.newForm.snippetInput.title.placeholder": "Titolo dello snippet",
"dashboard.snippetsView.newForm.snippetInput.description.label": "Descrizione",
"dashboard.snippetsView.newForm.snippetInput.description.placeholder": "Descrizione dello snippet",
"dashboard.snippetsView.newForm.snippetInput.snippet.label": "Snippet",
"dashboard.snippetsView.newForm.snippetInput.snippet.placeholder": "Contenuto dello snippet",
"dashboard.snippetsView.newForm.snippetInput.isMediaSnippet.label": "È uno snippet multimediale?",
"dashboard.snippetsView.newForm.snippetInput.isMediaSnippet.checkbox.label": "Snippet multimediale",
"dashboard.snippetsView.newForm.snippetInput.isMediaSnippet.checkbox.description": "Utilizzare lo snippet corrente per inserire file multimediali nel contenuto.",
"dashboard.snippetsView.newForm.snippetInput.docsButton.title": "Ulteriori informazioni sull'uso dei segnaposto degli snippet multimediali",
"dashboard.snippetsView.newForm.snippetInput.docsButton.description": "Consulta la nostra documentazione dei segnaposto degli snippet multimediali per sapere quali segnaposto puoi usare.",
"dashboard.snippetsView.snippets.ariaLabel": "Intestazione Snippets",
"dashboard.snippetsView.snippets.button.create": "Creare un nuovo snippet",
"dashboard.snippetsView.snippets.select.description": "Seleziona lo snippet da aggiungere ai tuoi contenuti.",
"dashboard.snippetsView.snippets.empty.message": "Nessun Snippet trovato",
"dashboard.snippetsView.snippets.readMore": "Scopri di più per iniziare a usare gli snippet",
"dashboard.snippetsView.snippets.formDialog.title": "Creare uno snippet",
"dashboard.steps.stepsToGetStarted.button.addFolder.title": "Aggiungi come cartella di contenuti a Front Matter",
"dashboard.steps.stepsToGetStarted.initializeProject.name": "Inizializzare il progetto",
"dashboard.steps.stepsToGetStarted.initializeProject.description": "Inizializzare il progetto creerà i file e le cartelle necessari per l'utilizzo del CMS Front Matter. Inizia facendo clic su questa azione.",
"dashboard.steps.stepsToGetStarted.framework.name": "Predefiniti del framework",
"dashboard.steps.stepsToGetStarted.framework.description": "Seleziona il generatore di siti o il framework per precompilare alcune delle impostazioni consigliate.",
"dashboard.steps.stepsToGetStarted.framework.select": "Seleziona il tuo framework",
"dashboard.steps.stepsToGetStarted.framework.select.other": "Altro",
"dashboard.steps.stepsToGetStarted.assetsFolder.name": "Qual è la cartella delle risorse?",
"dashboard.steps.stepsToGetStarted.assetsFolder.description": "Seleziona la cartella contenente le tue risorse. Questa cartella verrà utilizzata per archiviare tutti i file multimediali per i tuoi articoli.",
"dashboard.steps.stepsToGetStarted.assetsFolder.public.title": "Utilizzare la cartella 'pubblica'",
"dashboard.steps.stepsToGetStarted.assetsFolder.assets.title": "Utilizzare la cartella Astro assets (src/assets)",
"dashboard.steps.stepsToGetStarted.assetsFolder.other.description": "Nel caso in cui si desideri configurare un'altra cartella, è possibile farlo manualmente nel file frontmatter.json.",
"dashboard.steps.stepsToGetStarted.contentFolders.name": "Registrare le cartelle dei contenuti",
"dashboard.steps.stepsToGetStarted.contentFolders.description": "Aggiungi una delle cartelle che abbiamo trovato nel tuo progetto come cartella di contenuti. Una volta impostata una cartella, Front Matter può essere utilizzato per elencare tutti i contenuti e consentire di creare contenuti.",
"dashboard.steps.stepsToGetStarted.contentFolders.label": "Cartelle contenenti contenuto:",
"dashboard.steps.stepsToGetStarted.contentFolders.information.description": "È inoltre possibile eseguire questa azione facendo clic con il pulsante destro del mouse sulla cartella nella visualizzazione Esplora risorse e selezionando Registra cartella",
"dashboard.steps.stepsToGetStarted.tags.name": "Importa tutti i tag e le categorie (facoltativo)",
"dashboard.steps.stepsToGetStarted.tags.description": "Ora che Front Matter conosce tutte le cartelle dei contenuti. Desideri importare tutti i tag e le categorie dai contenuti disponibili?",
"dashboard.steps.stepsToGetStarted.showDashboard.name": "Mostra il dashboard",
"dashboard.steps.stepsToGetStarted.showDashboard.description": "Una volta completate tutte le azioni, è possibile caricare la dashboard.",
"dashboard.taxonomyView.button.add.title": "Aggiungere {0} alle impostazioni della tassonomia",
"dashboard.taxonomyView.button.edit.title": "Modifica {0}",
"dashboard.taxonomyView.button.merge.title": "Unisci {0}",
"dashboard.taxonomyView.button.move.title": "Passare a un altro tipo di tassonomia",
"dashboard.taxonomyView.button.delete.title": "Elimina {0}",
"dashboard.taxonomyView.taxonomyLookup.button.title": "Mostra contenuti con {0} in {1}",
"dashboard.taxonomyView.taxonomyManager.description": "Crea, modifica e gestisci le {0} del tuo sito",
"dashboard.taxonomyView.taxonomyManager.button.create": "Creare un nuovo valore {0}",
"dashboard.taxonomyView.taxonomyManager.table.heading.name": "Nome",
"dashboard.taxonomyView.taxonomyManager.table.heading.count": "Conteggio",
"dashboard.taxonomyView.taxonomyManager.table.heading.action": "Azione",
"dashboard.taxonomyView.taxonomyManager.table.row.empty": "Nessun {0} trovato",
"dashboard.taxonomyView.taxonomyManager.table.unmapped.title": "Manca nelle impostazioni",
"dashboard.taxonomyView.taxonomyView.navigationBar.title": "Selezionare la tassonomia",
"dashboard.taxonomyView.taxonomyView.button.import": "Tassonomia delle importazioni",
"dashboard.taxonomyView.taxonomyView.navigationItem.tags": "Tag",
"dashboard.taxonomyView.taxonomyView.navigationItem.categories": "Categorie",
"dashboard.unkownView.title": "La vista non esiste",
"dashboard.unkownView.description": "Sembra che tu sia finito su una vista che non esiste. Riapri la dashboard.",
"dashboard.welcomeScreen.title": "Gestisci il tuo sito statico con Front Matter",
"dashboard.welcomeScreen.thanks": "Grazie per aver scelto Front Matter!",
"dashboard.welcomeScreen.description": "Cerchiamo di mirare a rendere Front Matter il più facile da usare possibile, ma se avete domande o suggerimenti. Non esitare a contattarci su GitHub.",
"dashboard.welcomeScreen.link.github.title": "GitHub",
"dashboard.welcomeScreen.link.github.label": "GitHub / Documentazione",
"dashboard.welcomeScreen.link.sponsor.title": "Diventa sponsor",
"dashboard.welcomeScreen.link.sponsor.label": "Sponsor",
"dashboard.welcomeScreen.link.review.title": "Scrivi una recensione",
"dashboard.welcomeScreen.link.review.label": "Recensione",
"dashboard.welcomeScreen.actions.heading": "Esegui i passaggi successivi per iniziare con l'estensione",
"dashboard.welcomeScreen.actions.description": "È inoltre possibile utilizzare l'estensione dal pannello laterale Front Matter. Lì troverai le azioni che puoi eseguire specificamente per le tue pagine.",
"dashboard.welcomeScreen.actions.thanks": "Ci auguriamo che Front Matter vi piaccia!",
"panel.contentType.contentTypeValidator.title": "Tipo di contenuto",
"panel.contentType.contentTypeValidator.hint": "Abbiamo notato differenze di campo tra il tipo di contenuto e i dati della prima questione. \n Si desidera creare, aggiornare o impostare il tipo di contenuto per questo contenuto?",
"panel.contentType.contentTypeValidator.button.create": "Crea tipo di contenuto",
"panel.contentType.contentTypeValidator.button.add": "Aggiungere campi mancanti a content-type",
"panel.contentType.contentTypeValidator.button.change": "Modificare il tipo di contenuto del file",
"panel.dataBlock.dataBlockField.group.selected.edit": "Modifica: {0}",
"panel.dataBlock.dataBlockField.group.selected.create": "Creare una nuova {0}",
"panel.dataBlock.dataBlockField.group.select": "Seleziona un gruppo",
"panel.dataBlock.dataBlockField.add": "Aggiungi {0}",
"panel.dataBlock.dataBlockRecord.edit": "Modifica record",
"panel.dataBlock.dataBlockRecord.delete": "Elimina record",
"panel.dataBlock.dataBlockRecords.label": "Archivio",
"panel.dataBlock.dataBlockSelector.label": "Tipo di blocco",
"panel.errorBoundary.fieldBoundary.label": "Visualizzazione del campo non riuscita",
"panel.fields.choiceField.select": "Seleziona {0}",
"panel.fields.choiceField.clear": "Pulisci valore",
"panel.fields.contentTypeRelationshipField.loading": "Recupero di possibili valori...",
"panel.fields.dateTimeField.button.pick": "Scegli la tua data",
"panel.fields.dateTimeField.time": "Ore:",
"panel.fields.fieldMessage.required": "Il campo {0} è obbligatorio",
"panel.fields.fileField.delete": "Elimina file",
"panel.fields.fileField.add": "Aggiungi il tuo {0}",
"panel.fields.imageFallback.label": "L'immagine non deve essere caricata",
"panel.fields.listField.edit": "Modifica record",
"panel.fields.listField.delete": "Elimina record",
"panel.fields.previewImage.remove": "Rimuovi immagine",
"panel.fields.previewImageField.add": "Aggiungi il tuo {0}",
"panel.fields.slugField.update": "Aggiornamento disponibile",
"panel.fields.slugField.generate": "Genera slug",
"panel.fields.textField.ai.message": "Usa Front Matter AI per suggerire {0}",
"panel.fields.textField.ai.generate": "Genera suggerimenti...",
"panel.fields.textField.loading": "caricamento",
"panel.fields.textField.limit": "Limite di campi raggiunto {0}",
"panel.fields.wrapperField.unknown": "Tipo di campo sconosciuto: {0}",
"panel.actions.title": "Azioni",
"panel.articleDetails.title": "Più dettagli",
"panel.articleDetails.type": "Digitare",
"panel.articleDetails.total": "Totale",
"panel.articleDetails.headings": "Intestazioni",
"panel.articleDetails.paragraphs": "Paragrafi",
"panel.articleDetails.internalLinks": "Collegamenti esterni",
"panel.articleDetails.externalLinks": "Collegamenti esterni",
"panel.articleDetails.images": "Immagini",
"panel.baseView.initialize": "Inizializzare il progetto",
"panel.baseView.actions.title": "Azioni",
"panel.baseView.action.openDashboard": "Apri dashboard",
"panel.baseView.action.openPreview": "Apri anteprima",
"panel.baseView.action.createContent": "Creare contenuti",
"panel.baseView.empty": "Apri un file per visualizzare altre azioni",
"panel.fileList.label.singular": "file",
"panel.fileList.label.plural": "file",
"panel.folderAndFiles.title": "Modifiche recenti",
"panel.globalSettings.title": "Impostazioni globali",
"panel.globalSettings.action.modifiedDate.label": "Data di modifica",
"panel.globalSettings.action.modifiedDate.description": "Aggiornamento automatico della data di modifica",
"panel.globalSettings.action.frontMatter.label": "Evidenziazione di Front Matter",
"panel.globalSettings.action.frontMatter.description": "Highlight Front Matter",
"panel.globalSettings.action.preview.label": "Anteprima locale",
"panel.globalSettings.action.preview.placeholder": "Esempio: {0}",
"panel.globalSettings.action.server.label": "Comando server locale",
"panel.globalSettings.action.server.placeholder": "Esempio: {0}",
"panel.metadata.title": "Metadati",
"panel.otherActions.title": "Altre azioni",
"panel.otherActions.writingSettings.enabled": "Impostazioni di scrittura abilitate",
"panel.otherActions.writingSettings.disabled": "Abilitare le impostazioni di scrittura",
"panel.otherActions.centerMode": "Attiva/disattiva la modalità centrale",
"panel.otherActions.createTemplate": "Crea modello",
"panel.otherActions.revealFile": "Rivela il file nella cartella",
"panel.otherActions.openProject": "Rivela cartella del progetto",
"panel.otherActions.documentation": "Apri la documentazione",
"panel.otherActions.settings": "Panoramica delle impostazioni",
"panel.otherActions.issue": "Segnala un problema",
"panel.preview.title": "Apri anteprima",
"panel.publishAction.publish": "Pubblica",
"panel.publishAction.unpublish": "Tornare alla bozza",
"panel.seoDetails.recommended": "Raccomandato",
"panel.seoKeywordInfo.density": "Utilizzo delle parole chiave {0} *",
"panel.seoKeywordInfo.validInfo.label": "Utilizzato nelle rubriche",
"panel.seoKeywordInfo.validInfo.content": "Contenuto",
"panel.seoKeywords.title": "Parole chiavi",
"panel.seoKeywords.header.keyword": "Parola chiave",
"panel.seoKeywords.header.details": "Dettagli",
"panel.seoKeywords.density": "* Una densità di parole chiave dell'1-1,5% è sufficiente nella maggior parte dei casi.",
"panel.seoStatus.title": "Consigli",
"panel.seoStatus.header.property": "Proprietà",
"panel.seoStatus.header.length": "Lunghezza",
"panel.seoStatus.header.valid": "Valido",
"panel.seoStatus.seoFieldInfo.characters": "{0} caratteri",
"panel.seoStatus.seoFieldInfo.words": "{0} parole",
"panel.seoStatus.seoFieldInfo.article": "Lunghezza dell'articolo",
"panel.seoStatus.collapsible.title": "Stato SEO",
"panel.seoStatus.required": "{0} o {1} è obbligatorio.",
"panel.slugAction.title": "Ottimizza slug",
"panel.spinner.loading": "Caricamento...",
"panel.startServerbutton.start": "Avvia Server",
"panel.startServerbutton.stop": "Arrestare il Server",
"panel.tag.add": "Aggiungi {0} alle tue impostazioni",
"panel.tagPicker.inputPlaceholder.empty": "Scegli il tuo {0}",
"panel.tagPicker.inputPlaceholder.disabled": "Hai raggiunto il limite di {0}",
"panel.tagPicker.ai.suggest": "Usa Front Matter AI per suggerire {0}",
"panel.tagPicker.ai.generating": "Genera suggerimenti...",
"panel.tagPicker.limit": "Max.: {0}",
"panel.tagPicker.unkown": "Aggiungi il tag sconosciuto",
"panel.tags.tag.warning": "Tieni presente che questo tag \"{0}\" non viene salvato nelle tue impostazioni. Una volta rimosso, sarà eliminato per sempre.",
"panel.viewPanel.mediaInsert": "Continuare nella dashboard multimediale per selezionare l'immagine che si desidera inserire.",
"dashboard.steps.stepsToGetStarted.template.name": "Usa un modello di configurazione",
"dashboard.steps.stepsToGetStarted.template.description": "Seleziona un modello per riempire in anticipo il file frontmatter.json con le impostazioni consigliate.",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "File del modello copiati.",
"common.openOnWebsite": "Apri sul sito web"
}
+5 -1
View File
@@ -332,5 +332,9 @@
"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.assetsFolder.other.description": "別のフォルダを設定する場合は、frontmatter.jsonファイルで手動で行うことができます。",
"dashboard.steps.stepsToGetStarted.template.name": "設定テンプレートを使用する",
"dashboard.steps.stepsToGetStarted.template.description": "おすすめの設定でfrontmatter.jsonファイルを事前に埋めるテンプレートを選択します。",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "テンプレートファイルがコピーされました。",
"common.openOnWebsite": "ウェブサイトで開く"
}
+7 -2
View File
@@ -21,6 +21,7 @@
"common.support": "Support",
"common.remove.value": "Remove {0}",
"common.error.message": "Sorry, something went wrong.",
"common.openOnWebsite": "Open on website",
"developer.title": "Developer mode",
"developer.reload.title": "Reload the dashboard",
@@ -130,7 +131,7 @@
"dashboard.header.sorting.alt.asc": "Alt (asc)",
"dashboard.header.sorting.alt.desc": "Alt (desc)",
"dashboard.header.sorting.label": "Sort by",
"dashboard.header.startup.label": "Open on startup?",
"dashboard.header.tabs.contents": "Contents",
@@ -242,6 +243,8 @@
"dashboard.steps.stepsToGetStarted.tags.description": "Now that Front Matter knows all the content folders. Would you like to import all tags and categories from the available content?",
"dashboard.steps.stepsToGetStarted.showDashboard.name": "Show the dashboard",
"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.taxonomyView.button.add.title": "Add {0} to taxonomy settings",
"dashboard.taxonomyView.button.edit.title": "Edit {0}",
@@ -422,5 +425,7 @@
"panel.tags.tag.warning": "Be aware, this tag \"{0}\" is not saved in your settings. Once removed, it will be gone forever.",
"panel.viewPanel.mediaInsert": "Continue in the media dashboard to select the image you want to insert."
"panel.viewPanel.mediaInsert": "Continue in the media dashboard to select the image you want to insert.",
"listeners.dashboard.settingsListener.triggerTemplate.notification": "Template files copied."
}
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

+177 -110
View File
@@ -1,12 +1,12 @@
{
"name": "vscode-front-matter-beta",
"version": "9.0.0",
"version": "9.2.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "vscode-front-matter-beta",
"version": "9.0.0",
"version": "9.2.0",
"license": "MIT",
"devDependencies": {
"@actions/core": "^1.10.0",
@@ -54,6 +54,7 @@
"downshift": "6.0.6",
"eslint": "^8.33.0",
"fuse.js": "6.5.3",
"github-directory-downloader": "^1.3.6",
"glob": "7.1.6",
"gray-matter": "4.0.3",
"html-loader": "1.3.2",
@@ -1564,28 +1565,29 @@
"dev": true
},
"node_modules/@vscode/vsce": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.17.0.tgz",
"integrity": "sha512-W4HN5MtTVj/mroQU1d82bUEeWM3dUykMFnMYZPtZ6jrMiHN1PUoN3RGcS896N0r2rIq8KpWDtufcQHgK8VfgpA==",
"version": "2.21.0",
"resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.21.0.tgz",
"integrity": "sha512-KuxYqScqUY/duJbkj9eE2tN2X/WJoGAy54hHtxT3ZBkM6IzrOg7H7CXGUPBxNlmqku2w/cAjOUSrgIHlzz0mbA==",
"dev": true,
"dependencies": {
"azure-devops-node-api": "^11.0.1",
"chalk": "^2.4.2",
"cheerio": "^1.0.0-rc.9",
"commander": "^6.1.0",
"commander": "^6.2.1",
"glob": "^7.0.6",
"hosted-git-info": "^4.0.2",
"jsonc-parser": "^3.2.0",
"leven": "^3.1.0",
"markdown-it": "^12.3.2",
"mime": "^1.3.4",
"minimatch": "^3.0.3",
"parse-semver": "^1.1.1",
"read": "^1.0.7",
"semver": "^5.1.0",
"semver": "^7.5.2",
"tmp": "^0.2.1",
"typed-rest-client": "^1.8.4",
"url-join": "^4.0.1",
"xml2js": "^0.4.23",
"xml2js": "^0.5.0",
"yauzl": "^2.3.1",
"yazl": "^2.2.2"
},
@@ -1620,15 +1622,6 @@
"node": ">=10"
}
},
"node_modules/@vscode/vsce/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/@vscode/webview-ui-toolkit": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-0.9.3.tgz",
@@ -2154,6 +2147,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"dev": true,
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/attr-accept": {
"version": "2.2.2",
"dev": true,
@@ -3327,9 +3329,10 @@
}
},
"node_modules/cross-spawn/node_modules/semver": {
"version": "5.7.1",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver"
}
@@ -3362,12 +3365,10 @@
}
},
"node_modules/css-loader/node_modules/json5": {
"version": "2.2.0",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.5"
},
"bin": {
"json5": "lib/cli.js"
},
@@ -3376,9 +3377,10 @@
}
},
"node_modules/css-loader/node_modules/loader-utils": {
"version": "2.0.0",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"license": "MIT",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -4920,6 +4922,21 @@
"dev": true,
"license": "MIT"
},
"node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"dependencies": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/fs-monkey": {
"version": "1.0.3",
"dev": true,
@@ -5012,6 +5029,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/github-directory-downloader": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/github-directory-downloader/-/github-directory-downloader-1.3.6.tgz",
"integrity": "sha512-k43h2cjdE5FIpM+0aYuK4DTdTZ2FcopgbY8kvzR2hihdq/gRyINrLDpLlFrkVID6sTi0vSaBqVJm7goLcbBxQg==",
"dev": true,
"dependencies": {
"fs-extra": "^9.0.1",
"node-fetch": "^2.6.1",
"yargs-parser": "^20.2.4"
},
"bin": {
"github-directory-downloader": "bin/cli.js"
}
},
"node_modules/github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
@@ -5339,12 +5370,10 @@
}
},
"node_modules/html-loader/node_modules/json5": {
"version": "2.1.3",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.5"
},
"bin": {
"json5": "lib/cli.js"
},
@@ -5353,9 +5382,10 @@
}
},
"node_modules/html-loader/node_modules/loader-utils": {
"version": "2.0.0",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"license": "MIT",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -6318,9 +6348,10 @@
}
},
"node_modules/json5": {
"version": "1.0.1",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.0"
},
@@ -6523,9 +6554,10 @@
}
},
"node_modules/loader-utils": {
"version": "1.4.0",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
"dev": true,
"license": "MIT",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -8012,9 +8044,10 @@
}
},
"node_modules/normalize-package-data/node_modules/semver": {
"version": "5.7.1",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver"
}
@@ -8418,9 +8451,9 @@
}
},
"node_modules/parse-semver/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -10614,9 +10647,9 @@
}
},
"node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@@ -11202,12 +11235,10 @@
}
},
"node_modules/style-loader/node_modules/json5": {
"version": "2.2.0",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.5"
},
"bin": {
"json5": "lib/cli.js"
},
@@ -11216,9 +11247,10 @@
}
},
"node_modules/style-loader/node_modules/loader-utils": {
"version": "2.0.0",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"license": "MIT",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -12803,9 +12835,9 @@
"license": "MIT"
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -12907,9 +12939,9 @@
}
},
"node_modules/xml2js": {
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"dev": true,
"dependencies": {
"sax": ">=0.6.0",
@@ -12950,9 +12982,9 @@
"license": "ISC"
},
"node_modules/yaml": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
"integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
"integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
"dev": true,
"engines": {
"node": ">= 14"
@@ -14215,17 +14247,18 @@
"dev": true
},
"@vscode/vsce": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.17.0.tgz",
"integrity": "sha512-W4HN5MtTVj/mroQU1d82bUEeWM3dUykMFnMYZPtZ6jrMiHN1PUoN3RGcS896N0r2rIq8KpWDtufcQHgK8VfgpA==",
"version": "2.21.0",
"resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.21.0.tgz",
"integrity": "sha512-KuxYqScqUY/duJbkj9eE2tN2X/WJoGAy54hHtxT3ZBkM6IzrOg7H7CXGUPBxNlmqku2w/cAjOUSrgIHlzz0mbA==",
"dev": true,
"requires": {
"azure-devops-node-api": "^11.0.1",
"chalk": "^2.4.2",
"cheerio": "^1.0.0-rc.9",
"commander": "^6.1.0",
"commander": "^6.2.1",
"glob": "^7.0.6",
"hosted-git-info": "^4.0.2",
"jsonc-parser": "^3.2.0",
"keytar": "^7.7.0",
"leven": "^3.1.0",
"markdown-it": "^12.3.2",
@@ -14233,11 +14266,11 @@
"minimatch": "^3.0.3",
"parse-semver": "^1.1.1",
"read": "^1.0.7",
"semver": "^5.1.0",
"semver": "^7.5.2",
"tmp": "^0.2.1",
"typed-rest-client": "^1.8.4",
"url-join": "^4.0.1",
"xml2js": "^0.4.23",
"xml2js": "^0.5.0",
"yauzl": "^2.3.1",
"yazl": "^2.2.2"
},
@@ -14256,12 +14289,6 @@
"requires": {
"lru-cache": "^6.0.0"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
@@ -14681,6 +14708,12 @@
"version": "0.4.0",
"dev": true
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"dev": true
},
"attr-accept": {
"version": "2.2.2",
"dev": true
@@ -15498,7 +15531,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
}
}
@@ -15520,14 +15555,15 @@
},
"dependencies": {
"json5": {
"version": "2.2.0",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"loader-utils": {
"version": "2.0.0",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@@ -16615,6 +16651,18 @@
"version": "1.0.0",
"dev": true
},
"fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
}
},
"fs-monkey": {
"version": "1.0.3",
"dev": true
@@ -16669,6 +16717,17 @@
"get-intrinsic": "^1.1.1"
}
},
"github-directory-downloader": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/github-directory-downloader/-/github-directory-downloader-1.3.6.tgz",
"integrity": "sha512-k43h2cjdE5FIpM+0aYuK4DTdTZ2FcopgbY8kvzR2hihdq/gRyINrLDpLlFrkVID6sTi0vSaBqVJm7goLcbBxQg==",
"dev": true,
"requires": {
"fs-extra": "^9.0.1",
"node-fetch": "^2.6.1",
"yargs-parser": "^20.2.4"
}
},
"github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
@@ -16896,14 +16955,15 @@
}
},
"json5": {
"version": "2.1.3",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"loader-utils": {
"version": "2.0.0",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@@ -17503,7 +17563,9 @@
}
},
"json5": {
"version": "1.0.1",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
@@ -17663,7 +17725,9 @@
"dev": true
},
"loader-utils": {
"version": "1.4.0",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@@ -18620,7 +18684,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
}
}
@@ -18880,9 +18946,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
}
}
@@ -20356,9 +20422,9 @@
}
},
"semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
@@ -20773,14 +20839,15 @@
},
"dependencies": {
"json5": {
"version": "2.2.0",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"loader-utils": {
"version": "2.0.0",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
@@ -21887,9 +21954,9 @@
"dev": true
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true
},
"workerpool": {
@@ -21946,9 +22013,9 @@
"requires": {}
},
"xml2js": {
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"dev": true,
"requires": {
"sax": ">=0.6.0",
@@ -21974,9 +22041,9 @@
"dev": true
},
"yaml": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
"integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
"integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
"dev": true
},
"yaml-js": {
+189 -127
View File
@@ -3,14 +3,15 @@
"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.0.0",
"version": "9.2.0",
"preview": false,
"publisher": "eliostruyf",
"galleryBanner": {
"color": "#0e131f",
"theme": "dark"
},
"badges": [{
"badges": [
{
"description": "version",
"url": "https://img.shields.io/github/package-json/v/estruyf/vscode-front-matter?color=green&label=vscode-front-matter&style=flat-square",
"href": "https://github.com/estruyf/vscode-front-matter"
@@ -55,13 +56,23 @@
],
"main": "./dist/extension.js",
"contributes": {
"icons": {
"fm-logo": {
"description": "Front Matter icon",
"default": {
"fontPath": "assets/frontmatter.woff",
"fontCharacter": "\\e900"
}
}
},
"configurationDefaults": {
"files.associations": {
"**/frontmatter.json": "jsonc",
"**/.frontmatter/config/*.json": "jsonc"
}
},
"keybindings": [{
"keybindings": [
{
"command": "frontMatter.dashboard",
"key": "alt+d"
},
@@ -79,23 +90,26 @@
}
],
"viewsContainers": {
"activitybar": [{
"id": "frontmatter-explorer",
"title": "Front Matter",
"icon": "assets/frontmatter-short-min.svg"
}]
"activitybar": [
{
"id": "frontmatter-explorer",
"title": "Front Matter",
"icon": "assets/frontmatter-short-min.svg"
}
]
},
"views": {
"frontmatter-explorer": [{
"id": "frontMatter.explorer",
"name": "Front Matter",
"icon": "assets/frontmatter-short-min.svg",
"contextualTitle": "Front Matter",
"type": "webview"
}]
"frontmatter-explorer": [
{
"id": "frontMatter.explorer",
"name": "Front Matter",
"icon": "assets/frontmatter-short-min.svg",
"contextualTitle": "Front Matter",
"type": "webview"
}
]
},
"configuration": {
"$id": "#globalconfiguration",
"title": "%settings.configuration.title%",
"type": "object",
"properties": {
@@ -115,7 +129,7 @@
"markdownDescription": "%setting.frontMatter.projects.items.properties.default.markdownDescription%"
},
"configuration": {
"$ref": "#globalconfiguration"
"$ref": "https://frontmatter.codes/frontmatter.schema.json"
}
}
}
@@ -156,7 +170,8 @@
"frontMatter.content.defaultFileType": {
"type": "string",
"default": "md",
"oneOf": [{
"oneOf": [
{
"enum": [
"md",
"mdx"
@@ -172,7 +187,8 @@
"frontMatter.content.defaultSorting": {
"type": "string",
"default": "",
"oneOf": [{
"oneOf": [
{
"enum": [
"LastModifiedAsc",
"LastModifiedDesc",
@@ -327,7 +343,10 @@
"scope": "Content"
},
"frontMatter.content.publicFolder": {
"type": ["string", "object"],
"type": [
"string",
"object"
],
"properties": {
"path": {
"type": "string",
@@ -516,7 +535,8 @@
"command": {
"$id": "#scriptCommand",
"type": "string",
"anyOf": [{
"anyOf": [
{
"enum": [
"node",
"bash",
@@ -716,7 +736,8 @@
"title",
"file"
],
"anyOf": [{
"anyOf": [
{
"required": [
"schema"
]
@@ -770,7 +791,8 @@
"id",
"path"
],
"anyOf": [{
"anyOf": [
{
"required": [
"schema"
]
@@ -1138,7 +1160,8 @@
"default": "",
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.taxonomyId.description%",
"not": {
"anyOf": [{
"anyOf": [
{
"const": ""
},
{
@@ -1258,6 +1281,11 @@
"default": false,
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.required.description%"
},
"clearEmpty": {
"type": "boolean",
"default": false,
"description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.clearEmpty.description%"
},
"customType": {
"type": "string",
"default": "",
@@ -1327,7 +1355,8 @@
"type",
"name"
],
"allOf": [{
"allOf": [
{
"if": {
"properties": {
"type": {
@@ -1513,48 +1542,51 @@
"fields"
]
},
"default": [{
"name": "default",
"pageBundle": false,
"fields": [{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
"name": "preview",
"type": "image"
},
{
"title": "Is in draft",
"name": "draft",
"type": "boolean"
},
{
"title": "Tags",
"name": "tags",
"type": "tags"
},
{
"title": "Categories",
"name": "categories",
"type": "categories"
}
]
}],
"default": [
{
"name": "default",
"pageBundle": false,
"fields": [
{
"title": "Title",
"name": "title",
"type": "string"
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
"name": "preview",
"type": "image"
},
{
"title": "Is in draft",
"name": "draft",
"type": "boolean"
},
{
"title": "Tags",
"name": "tags",
"type": "tags"
},
{
"title": "Categories",
"name": "categories",
"type": "categories"
}
]
}
],
"scope": "Taxonomy"
},
"frontMatter.taxonomy.customTaxonomy": {
@@ -1567,7 +1599,8 @@
"type": "string",
"description": "%setting.frontMatter.taxonomy.customTaxonomy.items.properties.id.description%",
"not": {
"anyOf": [{
"anyOf": [
{
"const": ""
},
{
@@ -1746,15 +1779,26 @@
"default": "yyyy-MM-dd",
"markdownDescription": "%setting.frontMatter.templates.prefix.markdownDescription%",
"scope": "Templates"
},
"frontMatter.website.host": {
"type": "string",
"markdownDescription": "%setting.frontMatter.website.host.markdownDescription%"
}
}
},
"commands": [{
"commands": [
{
"command": "frontMatter.project.switch",
"title": "%command.frontMatter.project.switch%",
"category": "Front Matter",
"icon": "$(arrow-swap)"
},
{
"command": "frontMatter.settings.refresh",
"title": "%command.frontMatter.settings.refresh%",
"category": "Front Matter",
"icon": "$(refresh)"
},
{
"command": "frontMatter.config.reload",
"title": "%command.frontMatter.config.reload%",
@@ -2078,12 +2122,15 @@
"category": "Front Matter"
}
],
"submenus": [{
"id": "frontmatter.submenu",
"label": "Front Matter"
}],
"submenus": [
{
"id": "frontmatter.submenu",
"label": "Front Matter"
}
],
"menus": {
"editor/title": [{
"editor/title": [
{
"command": "frontMatter.markup.heading",
"group": "navigation@-133",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
@@ -2164,11 +2211,14 @@
"when": "resourceFilename == 'frontmatter.json'"
}
],
"explorer/context": [{
"submenu": "frontmatter.submenu",
"group": "frontmatter@1"
}],
"frontmatter.submenu": [{
"explorer/context": [
{
"submenu": "frontmatter.submenu",
"group": "frontmatter@1"
}
],
"frontmatter.submenu": [
{
"command": "frontMatter.createFromTemplate",
"when": "explorerResourceIsFolder",
"group": "frontmatter@1"
@@ -2184,7 +2234,8 @@
"group": "frontmatter@3"
}
],
"commandPalette": [{
"commandPalette": [
{
"command": "frontMatter.init",
"when": "frontMatterCanInit"
},
@@ -2329,7 +2380,8 @@
"when": "frontMatter:file:isValid == true"
}
],
"view/title": [{
"view/title": [
{
"command": "frontMatter.chatbot",
"group": "navigation@0",
"when": "view == frontMatter.explorer"
@@ -2349,59 +2401,68 @@
"group": "navigation@3",
"when": "view == frontMatter.explorer && frontMatter:project:switch:enabled"
},
{
"command": "frontMatter.settings.refresh",
"group": "navigation@4"
},
{
"command": "frontMatter.dashboard",
"group": "navigation@4",
"group": "navigation@5",
"when": "view == frontMatter.explorer || view == explorer"
}
]
},
"grammars": [{
"path": "./syntaxes/hugo.tmLanguage.json",
"scopeName": "frontmatter.markdown.hugo",
"injectTo": [
"text.html.markdown"
]
}],
"walkthroughs": [{
"id": "frontmatter.welcome",
"title": "Get started with Front Matter",
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
"steps": [{
"id": "frontmatter.welcome.init",
"title": "Get started",
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
"media": {
"markdown": "assets/walkthrough/get-started.md"
"grammars": [
{
"path": "./syntaxes/hugo.tmLanguage.json",
"scopeName": "frontmatter.markdown.hugo",
"injectTo": [
"text.html.markdown"
]
}
],
"walkthroughs": [
{
"id": "frontmatter.welcome",
"title": "Get started with Front Matter",
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
"steps": [
{
"id": "frontmatter.welcome.init",
"title": "Get started",
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
"media": {
"markdown": "assets/walkthrough/get-started.md"
},
"completionEvents": [
"onContext:frontMatterInitialized"
]
},
"completionEvents": [
"onContext:frontMatterInitialized"
]
},
{
"id": "frontmatter.welcome.documentation",
"title": "Documentation",
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
"media": {
"markdown": "assets/walkthrough/documentation.md"
{
"id": "frontmatter.welcome.documentation",
"title": "Documentation",
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
"media": {
"markdown": "assets/walkthrough/documentation.md"
},
"completionEvents": [
"onLink:https://frontmatter.codes/docs"
]
},
"completionEvents": [
"onLink:https://frontmatter.codes/docs"
]
},
{
"id": "frontmatter.welcome.supporter",
"title": "Support the project",
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
"media": {
"markdown": "assets/walkthrough/support-the-project.md"
},
"completionEvents": [
"onLink:https://github.com/sponsors/estruyf"
]
}
]
}]
{
"id": "frontmatter.welcome.supporter",
"title": "Support the project",
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
"media": {
"markdown": "assets/walkthrough/support-the-project.md"
},
"completionEvents": [
"onLink:https://github.com/sponsors/estruyf"
]
}
]
}
]
},
"scripts": {
"dev:ext": "npm run clean && npm run localization:generate && npm-run-all --parallel watch:*",
@@ -2474,6 +2535,7 @@
"downshift": "6.0.6",
"eslint": "^8.33.0",
"fuse.js": "6.5.3",
"github-directory-downloader": "^1.3.6",
"glob": "7.1.6",
"gray-matter": "4.0.3",
"html-loader": "1.3.2",
@@ -2535,4 +2597,4 @@
"vsce": {
"dependencies": false
}
}
}
+4 -1
View File
@@ -239,5 +239,8 @@
"setting.frontMatter.dashboard.mediaSnippet.deprecationMessage": "Diese Einstellung ist veraltet und wird in der nächsten Hauptversion entfernt. Bitte definieren Sie Ihr Medien-Snippet in der `frontMatter.content.snippet` Einstellung.",
"setting.frontMatter.taxonomy.dateField.deprecationMessage": "Diese Einstellung ist veraltet und wird in der nächsten Hauptversion entfernt. Bitte verwenden Sie stattdessen die neuen `isPublishDate`-Einstellungen in den Datumsfeldern Ihrer Content-Typen.",
"setting.frontMatter.taxonomy.modifiedField.deprecationMessage": "Diese Einstellung ist veraltet und wird in der nächsten Hauptversion entfernt. Bitte verwenden Sie stattdessen die neuen `isModifiedDate`-Einstellungen in den Datumsfeldern Ihrer Content-Typen.",
"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.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.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"
}
+4 -1
View File
@@ -240,5 +240,8 @@
"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.global.disabledNotifications.markdownDescription": "🚧: This is an array with the notifications types that can be disabled for Front Matter CMS. [Check in the docs](https://frontmatter.codes/docs/settings/overview#frontmatter.global.disablednotifications)",
"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.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.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"
}
+4 -1
View File
@@ -239,5 +239,8 @@
"setting.frontMatter.dashboard.mediaSnippet.deprecationMessage": "This setting is deprecated and will be removed in the next major version. Please define your media snippet in the `frontMatter.content.snippet` setting.",
"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.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.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"
}
+17 -2
View File
@@ -1,9 +1,10 @@
import { Telemetry } from './../helpers/Telemetry';
import { TelemetryEvent, PreviewCommands, SETTING_EXPERIMENTAL } from './../constants';
import { TelemetryEvent, PreviewCommands, GeneralCommands } from './../constants';
import { join } from 'path';
import { commands, Uri, ViewColumn, window } from 'vscode';
import { Extension, Settings } from '../helpers';
import { WebviewHelper } from '@estruyf/vscode';
import { getLocalizationFile } from '../utils/getLocalizationFile';
export class Chatbot {
/**
@@ -30,13 +31,27 @@ export class Chatbot {
const cspSource = webView.webview.cspSource;
webView.webview.onDidReceiveMessage((message) => {
webView.webview.onDidReceiveMessage(async (message) => {
switch (message.command) {
case PreviewCommands.toVSCode.open:
if (message.data) {
commands.executeCommand('vscode.open', message.data);
}
return;
case GeneralCommands.toVSCode.getLocalization:
const { requestId } = message;
if (!requestId) {
return;
}
const fileContents = await getLocalizationFile();
webView.webview.postMessage({
command: GeneralCommands.toVSCode.getLocalization,
requestId,
payload: fileContents
});
return;
}
});
+6 -2
View File
@@ -160,7 +160,7 @@ export class Dashboard {
await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, false);
});
SettingsHelper.onConfigChange(() => {
SettingsHelper.attachListener('dashboard-listener', () => {
SettingsListener.getSettings(true);
});
@@ -198,7 +198,11 @@ export class Dashboard {
* Post data to the dashboard
* @param msg
*/
public static postWebviewMessage(msg: { command: DashboardCommand; payload?: unknown }) {
public static postWebviewMessage(msg: {
command: DashboardCommand;
requestId?: string;
payload?: unknown;
}) {
if (Dashboard.isDisposed) {
return;
}
+5 -1
View File
@@ -197,7 +197,7 @@ export class Folders {
}
}
return assetFolder;
return assetFolder || '/';
}
/**
@@ -495,6 +495,10 @@ export class Folders {
public static async getContentFolders() {
// Find folders that contain files
const wsFolder = Folders.getWorkspaceFolder();
if (!wsFolder) {
return [];
}
const supportedFiles =
Settings.get<string[]>(SETTING_CONTENT_SUPPORTED_FILETYPES) || DEFAULT_FILE_TYPES;
const patterns = supportedFiles.map(
+21 -5
View File
@@ -8,7 +8,8 @@ import {
TelemetryEvent,
PreviewCommands,
SETTING_EXPERIMENTAL,
SETTING_DATE_FORMAT
SETTING_DATE_FORMAT,
GeneralCommands
} from './../constants';
import { ArticleHelper } from './../helpers/ArticleHelper';
import { join, parse } from 'path';
@@ -23,6 +24,7 @@ import { WebviewHelper } from '@estruyf/vscode';
import { Folders } from './Folders';
import { DataListener } from '../listeners/panel';
import { ParsedFrontMatter } from '../parsers';
import { getLocalizationFile } from '../utils/getLocalizationFile';
export class Preview {
public static filePath: string | undefined = undefined;
@@ -103,13 +105,27 @@ export class Preview {
}
});
webView.webview.onDidReceiveMessage((message) => {
webView.webview.onDidReceiveMessage(async (message) => {
switch (message.command) {
case PreviewCommands.toVSCode.open:
if (message.data) {
commands.executeCommand('vscode.open', message.data);
if (message.payload) {
commands.executeCommand('vscode.open', message.payload);
}
return;
case GeneralCommands.toVSCode.getLocalization:
const { requestId } = message;
if (!requestId) {
return;
}
const fileContents = await getLocalizationFile();
webView.webview.postMessage({
command: GeneralCommands.toVSCode.getLocalization,
requestId,
payload: fileContents
});
return;
}
});
@@ -205,7 +221,7 @@ export class Preview {
* @param filePath
* @returns
*/
private static async getContentSlug(
public static async getContentSlug(
article: ParsedFrontMatter | null,
filePath?: string
): Promise<string | undefined> {
+1 -25
View File
@@ -24,18 +24,7 @@ export class StatusListener {
* @param frontMatterSB
* @param collection
*/
public static async verify(
frontMatterSB: vscode.StatusBarItem,
collection: vscode.DiagnosticCollection
) {
const draftMsg = 'in draft';
const publishMsg = 'to publish';
const draft = ContentType.getDraftField();
if (!draft || draft.type !== 'boolean') {
frontMatterSB.hide();
}
public static async verify(collection: vscode.DiagnosticCollection) {
const editor = vscode.window.activeTextEditor;
let document = editor?.document;
@@ -54,17 +43,6 @@ export class StatusListener {
? ArticleHelper.getFrontMatter(editor)
: await ArticleHelper.getFrontMatterByPath(document.uri.fsPath);
// Update the StatusBar based on the article draft state
if (article && typeof article.data['draft'] !== 'undefined') {
if (article.data['draft'] === true) {
frontMatterSB.text = `$(book) ${draftMsg}`;
frontMatterSB.show();
} else if (article.data['draft'] === false) {
frontMatterSB.text = `$(book) ${publishMsg}`;
frontMatterSB.show();
}
}
// Check SEO and required fields
if (article && article.data) {
collection.clear();
@@ -108,8 +86,6 @@ export class StatusListener {
DataListener.pushMetadata(null);
}
}
frontMatterSB.hide();
}
/**
+3 -1
View File
@@ -18,7 +18,6 @@ export const COMMAND_NAME = {
setLastModifiedDate: getCommandName('setLastModifiedDate'),
generateSlug: getCommandName('generateSlug'),
createFromTemplate: getCommandName('createFromTemplate'),
toggleDraft: getCommandName('toggleDraft'),
registerFolder: getCommandName('registerFolder'),
unregisterFolder: getCommandName('unregisterFolder'),
createContent: getCommandName('createContent'),
@@ -42,6 +41,9 @@ export const COMMAND_NAME = {
showOutputChannel: getCommandName('showOutputChannel'),
// Settings
settingsRefresh: getCommandName('settings.refresh'),
// Insert dashboards
insertMedia: getCommandName('insertMedia'),
insertSnippet: getCommandName('insertSnippet'),
+1 -1
View File
@@ -5,7 +5,7 @@ export const FrameworkDetectors = [
dist: 'dist',
static: ['public', 'src/assets'],
build: 'npm run build',
server: 'http://localhost:3000'
server: 'http://localhost:4321'
},
requiredFiles: ['astro.config.mjs'],
requiredDependencies: ['astro'],
+2 -1
View File
@@ -8,6 +8,7 @@ export const GeneralCommands = {
toVSCode: {
openLink: 'openLink',
gitSync: 'gitSync',
getLocalization: 'getLocalization'
getLocalization: 'getLocalization',
openOnWebsite: 'openOnWebsite'
}
};
+3
View File
@@ -0,0 +1,3 @@
export const Templates = {
url: 'https://frontmatter.github.io/templates/templates.json'
};
+1
View File
@@ -16,6 +16,7 @@ export * from './SentryIgnore';
export * from './Snippet';
export * from './StaticFolderPlaceholder';
export * from './TelemetryEvent';
export * from './Templates';
export * from './charCode';
export * from './charMap';
export * from './context';
+2
View File
@@ -103,6 +103,8 @@ export const SETTING_GIT_SUBMODULE_FOLDER = 'git.submodule.folder';
export const SETTING_SNIPPETS_WRAPPER = 'snippets.wrapper.enabled';
export const SETTING_WEBSITE_URL = 'website.host';
/**
* Sponsors only settings
*/
+1
View File
@@ -13,6 +13,7 @@ export enum DashboardMessage {
setFramework = 'setFramework',
addFolder = 'addFolder',
addAssetsFolder = 'addAssetsFolder',
triggerTemplate = 'triggerTemplate',
// Content dashboard
getData = 'getData',
@@ -9,6 +9,8 @@ import { useSettingsContext } from '../../providers/SettingsProvider';
import { AiInitResponse } from './models/AiInitResponse';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { messageHandler } from '@estruyf/vscode/dist/client';
import { GeneralCommands } from '../../../constants';
export interface IChatbotProps { }
@@ -21,9 +23,19 @@ export const Chatbot: React.FunctionComponent<IChatbotProps> = ({ }: React.Props
const [answerIds, setAnswerIds] = React.useState<number[]>([]);
const [sources, setSources] = React.useState<string[][]>([]);
const [loading, setLoading] = React.useState<boolean>(false);
const [localeReady, setLocaleReady] = React.useState<boolean>(false);
const init = async () => {
setLoading(true);
messageHandler.request<any>(GeneralCommands.toVSCode.getLocalization).then((data) => {
if (data) {
l10n.config({
contents: data
});
}
setLocaleReady(true);
});
const initResponse = await fetch(`${aiUrl}/api/ai-init`);
if (!initResponse.ok) {
@@ -54,7 +66,7 @@ export const Chatbot: React.FunctionComponent<IChatbotProps> = ({ }: React.Props
setSources(prev => [...prev, []])
setAnswerIds(prev => [...prev, 0])
if (!company || !chatId) {
if (!company || !chatId || !localeReady) {
return;
}
@@ -1,4 +1,4 @@
import { format } from 'date-fns';
import { format as fnsFormat } from 'date-fns';
import * as React from 'react';
import { DateHelper } from '../../../helpers/DateHelper';
import useThemeColors from '../../hooks/useThemeColors';
@@ -6,24 +6,32 @@ import useThemeColors from '../../hooks/useThemeColors';
export interface IDateFieldProps {
className?: string;
value: Date | string;
format?: string;
}
export const DateField: React.FunctionComponent<IDateFieldProps> = ({
className,
value
value,
format
}: React.PropsWithChildren<IDateFieldProps>) => {
const [dateValue, setDateValue] = React.useState<string>('');
const { getColors } = useThemeColors();
React.useEffect(() => {
try {
const parsedValue = typeof value === 'string' ? DateHelper.tryParse(value) : value;
const dateString = parsedValue ? format(parsedValue, 'yyyy-MM-dd') : parsedValue;
setDateValue(dateString || '');
const parsedValue = typeof value === 'string' ? DateHelper.tryParse(value, format) : value;
const dateString = parsedValue ? fnsFormat(parsedValue, 'yyyy-MM-dd') : parsedValue;
if (dateString) {
setDateValue(dateString);
} else if (!dateString && typeof value === 'string') {
setDateValue(value);
}
} catch (e) {
// Date is invalid
setDateValue(typeof value === 'string' ? value : '');
}
}, [value]);
}, [value, format]);
if (!dateValue) {
return null;
@@ -1,6 +1,6 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { Menu } from '@headlessui/react';
import { EyeIcon, TerminalIcon, TrashIcon } from '@heroicons/react/outline';
import { EyeIcon, GlobeIcon, TerminalIcon, TrashIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { CustomScript, ScriptType } from '../../../models';
import { DashboardMessage } from '../../DashboardMessage';
@@ -11,6 +11,9 @@ import { useState } from 'react';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { useRecoilValue } from 'recoil';
import { SettingsSelector } from '../../state';
import { GeneralCommands } from '../../../constants';
export interface IContentActionsProps {
title: string;
@@ -29,6 +32,7 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
}: React.PropsWithChildren<IContentActionsProps>) => {
const [showDeletionAlert, setShowDeletionAlert] = React.useState(false);
const { getColors } = useThemeColors();
const settings = useRecoilValue(SettingsSelector);
const [referenceElement, setReferenceElement] = useState<any>(null);
const [popperElement, setPopperElement] = useState<any>(null);
@@ -54,6 +58,16 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
setShowDeletionAlert(false);
};
const openOnWebsite = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
if (settings?.websiteUrl && path) {
Messenger.send(GeneralCommands.toVSCode.openOnWebsite, {
websiteUrl: settings.websiteUrl,
filePath: path
});
}
}, [settings?.websiteUrl, path]);
const runCustomScript = React.useCallback(
(e: React.MouseEvent<HTMLButtonElement>, script: CustomScript) => {
e.stopPropagation();
@@ -101,11 +115,19 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
<Menu as="div" className={`relative flex text-left`}>
{!listView && (
<div className="hidden group-hover/card:flex">
<QuickAction title={`View content`} onClick={onView}>
<QuickAction title={l10n.t(LocalizationKey.dashboardContentsContentActionsMenuItemView)} onClick={onView}>
<EyeIcon className={`w-4 h-4`} aria-hidden="true" />
</QuickAction>
<QuickAction title={`Delete content`} onClick={onDelete}>
{
settings?.websiteUrl && (
<QuickAction title={l10n.t(LocalizationKey.commonOpenOnWebsite)} onClick={openOnWebsite}>
<GlobeIcon className={`w-4 h-4`} aria-hidden="true" />
</QuickAction>
)
}
<QuickAction title={l10n.t(LocalizationKey.commonDelete)} onClick={onDelete}>
<TrashIcon className={`w-4 h-4`} aria-hidden="true" />
</QuickAction>
</div>
@@ -136,6 +158,20 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
onClick={(_, e) => onView(e)}
/>
{
settings?.websiteUrl && (
<MenuItem
title={
<div className="flex items-center">
<GlobeIcon className="mr-2 h-5 w-5 flex-shrink-0" aria-hidden={true} />{' '}
<span>{l10n.t(LocalizationKey.commonOpenOnWebsite)}</span>
</div>
}
onClick={(_, e) => openOnWebsite(e)}
/>
)
}
{customScriptActions}
<MenuItem
@@ -21,6 +21,7 @@ const PREVIEW_IMAGE_FIELD = 'fmPreviewImage';
export const Item: React.FunctionComponent<IItemProps> = ({
fmFilePath,
fmDateFormat,
date,
title,
description,
@@ -174,7 +175,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
dateHtml ? (
<div className='mr-4' dangerouslySetInnerHTML={{ __html: dateHtml }} />
) : (
cardFields?.date && <DateField className={`mr-4`} value={date} />
cardFields?.date && <DateField className={`mr-4`} value={date} format={fmDateFormat} />
)
}
</div>
@@ -1,8 +1,8 @@
import { Menu } from '@headlessui/react';
import * as React from 'react';
import { useRecoilState } from 'recoil';
import { useRecoilState, useRecoilValue } from 'recoil';
import { GroupOption } from '../../constants/GroupOption';
import { GroupingAtom } from '../../state';
import { AllPagesAtom, GroupingAtom, PageAtom } from '../../state';
import { MenuButton, MenuItem, MenuItems } from '../Menu';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
@@ -13,15 +13,34 @@ export const Grouping: React.FunctionComponent<
IGroupingProps
> = ({ }: React.PropsWithChildren<IGroupingProps>) => {
const [group, setGroup] = useRecoilState(GroupingAtom);
const pages = useRecoilValue(AllPagesAtom);
const GROUP_OPTIONS = [
{ name: l10n.t(LocalizationKey.dashboardHeaderGroupingOptionNone), id: GroupOption.none },
{ name: l10n.t(LocalizationKey.dashboardHeaderGroupingOptionYear), id: GroupOption.Year },
{ name: l10n.t(LocalizationKey.dashboardHeaderGroupingOptionDraft), id: GroupOption.Draft }
];
const GROUP_OPTIONS = React.useMemo(() => {
let options: { name: string, id: GroupOption }[] = [];
if (pages.length > 0) {
if (pages.some((x) => x.fmYear)) {
options.push({ name: l10n.t(LocalizationKey.dashboardHeaderGroupingOptionYear), id: GroupOption.Year })
}
if (pages.some((x) => x.fmDraft)) {
options.push({ name: l10n.t(LocalizationKey.dashboardHeaderGroupingOptionDraft), id: GroupOption.Draft })
}
}
if (options.length > 0) {
options.unshift({ name: l10n.t(LocalizationKey.dashboardHeaderGroupingOptionNone), id: GroupOption.none })
}
return options;
}, [pages])
const crntGroup = GROUP_OPTIONS.find((x) => x.id === group);
if (GROUP_OPTIONS.length === 0) {
return null;
}
return (
<div className="flex items-center">
<Menu as="div" className="relative z-10 inline-block text-left">
@@ -1,8 +1,7 @@
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { Tab } from '../../constants/Tab';
import useThemeColors from '../../hooks/useThemeColors';
import { SettingsAtom, TabAtom, TabInfoAtom } from '../../state';
import { AllPagesAtom, SettingsAtom, TabAtom, TabInfoAtom } from '../../state';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
@@ -22,20 +21,13 @@ const NavigationItem: React.FunctionComponent<INavigationItemProps> = ({
onClick,
children
}: React.PropsWithChildren<INavigationItemProps>) => {
const { getColors } = useThemeColors();
return (
<button
className={`${isCrntTab
?
getColors(
'border-teal-900 dark:border-teal-300 text-teal-900 dark:text-teal-300',
'border-[var(--vscode-textLink-foreground)] text-[var(--vscode-textLink-foreground)]'
) :
getColors(
`border-transparent text-gray-500 dark:text-whisper-600 hover:text-gray-700 dark:hover:text-whisper-700 hover:border-gray-300 dark:hover:border-whisper-500`,
`border-transparent text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-textLink-activeForeground)] hover:border-[var(--vscode-textLink-activeForeground)]`
)
`border-[var(--vscode-textLink-foreground)] text-[var(--vscode-textLink-foreground)]` :
`border-transparent text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-textLink-activeForeground)] hover:border-[var(--vscode-textLink-activeForeground)]`
} whitespace-nowrap py-2 px-1 border-b-2 font-medium text-sm`}
aria-current={isCrntTab ? 'page' : undefined}
onClick={onClick}
@@ -46,8 +38,9 @@ const NavigationItem: React.FunctionComponent<INavigationItemProps> = ({
};
export const Navigation: React.FunctionComponent<INavigationProps> = ({
totalPages
}: React.PropsWithChildren<INavigationProps>) => {
const pages = useRecoilValue(AllPagesAtom);
const [crntTab, setCrntTab] = useRecoilState(TabAtom);
const tabInfo = useRecoilValue(TabInfoAtom);
const settings = useRecoilValue(SettingsAtom);
@@ -58,6 +51,14 @@ export const Navigation: React.FunctionComponent<INavigationProps> = ({
{ name: l10n.t(LocalizationKey.dashboardHeaderNavigationDraft), id: Tab.Draft }
];
const usesDraft = React.useMemo(() => {
return pages.some((x) => x.fmDraft);
}, [pages]);
if (!usesDraft) {
return null;
}
return (
<nav className="flex-1 -mb-px flex space-x-6 xl:space-x-8" aria-label="Tabs">
{settings?.draftField?.type === 'boolean' ? (
@@ -23,7 +23,7 @@ import { LocalizationKey } from '../../../localization';
export interface IRefreshDashboardDataProps { }
export const RefreshDashboardData: React.FunctionComponent<IRefreshDashboardDataProps> = (
props: React.PropsWithChildren<IRefreshDashboardDataProps>
{ }: React.PropsWithChildren<IRefreshDashboardDataProps>
) => {
const view = useRecoilValue(DashboardViewAtom);
const [, setLoading] = useRecoilState(LoadingAtom);
@@ -35,7 +35,6 @@ export const RefreshDashboardData: React.FunctionComponent<IRefreshDashboardData
// Media
const resetPage = useResetRecoilState(PageAtom);
const selectedFolder = useRecoilValue(SelectedMediaFolderSelector);
const { getColors } = useThemeColors();
const refreshPages = () => {
setLoading(true);
@@ -64,11 +63,7 @@ export const RefreshDashboardData: React.FunctionComponent<IRefreshDashboardData
return (
<button
className={`mr-2 ${getColors(
'text-gray-500 hover:text-gray-600 dark:text-whisper-900 dark:hover:text-whisper-500',
'text-[var(--vscode-foreground)] hover:text-[var(--vscode-textLink-foreground)]'
)
}`}
className={`mr-2 text-[var(--vscode-foreground)] hover:text-[var(--vscode-textLink-foreground)]`}
title={l10n.t(LocalizationKey.dashboardHeaderRefreshDashboardLabel)}
onClick={refresh}
>
+5 -15
View File
@@ -18,21 +18,11 @@ export const Tab: React.FunctionComponent<ITabProps> = ({
return (
<button
className={`h-full flex items-center py-2 px-4 text-sm font-medium text-center border-b-2 border-transparent ${
getColors(
'hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300',
'text-[var(--vscode-tab-inactiveForeground)] hover:border-[var(--vscode-list-activeSelectionForeground)] hover:text-[var(--vscode-list-activeSelectionForeground)]'
)
} ${
location.pathname === `/${navigationType}`
? getColors(
'text-vulcan-500 dark:text-whisper-500 border-vulcan-500 dark:border-whisper-500',
'text-[var(--vscode-tab-activeForeground)] border-[var(--vscode-tab-activeForeground)]'
) : getColors(
'text-gray-500 dark:text-gray-400',
'text-[var(--vscode-tab-inactiveForeground)]'
)
}`}
className={`h-full flex items-center py-2 px-4 text-sm font-medium text-center border-b-2 border-transparent hover:border-[var(--vscode-tab-activeForeground)] hover:text-[var(--vscode-tab-activeForeground)] ${location.pathname === `/${navigationType}`
?
`text-[var(--vscode-tab-activeForeground)] border-[var(--vscode-tab-activeForeground)]` :
`text-[var(--vscode-tab-inactiveForeground)]`
}`}
type="button"
role="tab"
aria-controls="profile"
@@ -352,10 +352,14 @@ export const Item: React.FunctionComponent<IItemProps> = ({
const path = media.fsPath;
const extension = path.split('.').pop();
const colors = getColors(`text-gray-300 dark:text-vulcan-200`, `text-[var(--vscode-sideBarTitle-foreground)] opacity-80`);
const colors = `text-[var(--vscode-sideBarTitle-foreground)] opacity-80`;
let icon = <DocumentIcon className={`h-4/6 ${colors}`} />;
if (media.vsPath) {
return null;
}
if (isImageFile) {
return <PhotographIcon className={`h-1/2 ${colors}`} />;
}
@@ -25,7 +25,7 @@ export const Lightbox: React.FunctionComponent<ILightboxProps> = (
onClick={hideLightbox}
className={`fixed top-0 left-0 right-0 bottom-0 w-full h-full flex flex-wrap items-center justify-center z-50 ${getColors(
`bg-black bg-opacity-50`,
`bg-[var(--vscode-editor-background)] opacity-75`
`bg-[var(--frontmatter-lightbox-background)]`
)
}`}
>
@@ -33,7 +33,7 @@ export const Lightbox: React.FunctionComponent<ILightboxProps> = (
<img
src={lightbox}
alt={basename(lightbox)}
className={`w-1/2 h-auto rounded border shadow-2xl ${getColors(`border-vulcan-500 bg-vulcan-600`, `border-[var(--frontmatter-border)] bg-[var(--vscode-sideBar-background)]`)}`}
className={`w-1/2 h-auto rounded border shadow-2xl border-[var(--frontmatter-border)] bg-[var(--vscode-sideBar-background)]`}
/>
</div>
</div>
@@ -22,19 +22,11 @@ export const MenuButton: React.FunctionComponent<IMenuButtonProps> = ({
<Menu.Button
disabled={disabled}
className={`group inline-flex justify-center text-sm font-medium ${getColors(
'text-vulcan-500 hover:text-vulcan-600 dark:text-whisper-500 dark:hover:text-whisper-600',
'text-[var(--vscode-list-activeSelectionForeground)] hover:text-[var(--vscode-list-highlightForeground)]'
)
}`}
className={`group inline-flex justify-center text-sm font-medium text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]`}
>
{title}
<ChevronDownIcon
className={`flex-shrink-0 -mr-1 ml-1 h-5 w-5 ${getColors(
'text-gray-400 group-hover:text-gray-500 dark:text-whisper-600 dark:group-hover:text-whisper-700',
'text-[var(--vscode-list-activeSelectionForeground)] group-hover:text-[var(--vscode-list-highlightForeground)]'
)
}`}
className={`flex-shrink-0 -mr-1 ml-1 h-5 w-5 text-[var(--vscode-textLink-foreground)] group-hover:text-[var(--vscode-textLink-activeForeground)]`}
aria-hidden="true"
/>
</Menu.Button>
@@ -1,8 +1,8 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { ArrowRightIcon, ExternalLinkIcon, RefreshIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
import { PreviewCommands } from '../../../constants';
import { GeneralCommands, PreviewCommands } from '../../../constants';
import useThemeColors from '../../hooks/useThemeColors';
import { EventData } from '@estruyf/vscode/dist/models';
import * as l10n from '@vscode/l10n';
@@ -18,6 +18,7 @@ export const Preview: React.FunctionComponent<IPreviewProps> = ({
const iframeRef = useRef<HTMLIFrameElement>(null);
const [crntUrl, setCrntUrl] = useState<string | null>(null);
const { getColors } = useThemeColors();
const [localeReady, setLocaleReady] = useState<boolean>(false);
const onRefresh = () => {
if (iframeRef.current?.src) {
@@ -51,6 +52,15 @@ export const Preview: React.FunctionComponent<IPreviewProps> = ({
useEffect(() => {
Messenger.listen(msgListener);
messageHandler.request<any>(GeneralCommands.toVSCode.getLocalization).then((data) => {
if (data) {
l10n.config({
contents: data
});
}
setLocaleReady(true);
});
return () => {
Messenger.unlisten(msgListener);
};
@@ -74,31 +84,35 @@ export const Preview: React.FunctionComponent<IPreviewProps> = ({
className="w-full m-[1px] h-full border-1 border-transparent text-xs py-1 px-2 focus:border-color-blue-500 bg-[var(--vscode-tab-activeBackground)] text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)] focus:text-[var(--vscode-tab-activeForeground)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-[var(--vscode-focusBorder)"
/>
<div
className={`actions flex items-center space-x-2 px-2 ${getColors('text-vulcan-500 dark:text-whisper-100', 'text-[var(--vscode-list-activeSelectionForeground)]')
}`}
>
<button
title={l10n.t(LocalizationKey.dashboardPreviewButtonOpenTitle)}
onClick={navigateToUrl}
className={getColors(`hover:text-vulcan-500 dark:hover:text-whisper-100`, `hover:text-[var(--vscode-textLink-activeForeground)]`)}>
<ArrowRightIcon className="w-4 h-4" aria-hidden="true" />
</button>
{
localeReady && (
<div
className={`actions flex items-center space-x-2 px-2 ${getColors('text-vulcan-500 dark:text-whisper-100', 'text-[var(--vscode-list-activeSelectionForeground)]')
}`}
>
<button
title={l10n.t(LocalizationKey.dashboardPreviewButtonOpenTitle)}
onClick={navigateToUrl}
className={getColors(`hover:text-vulcan-500 dark:hover:text-whisper-100`, `hover:text-[var(--vscode-textLink-activeForeground)]`)}>
<ArrowRightIcon className="w-4 h-4" aria-hidden="true" />
</button>
<button
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" />
</button>
<button
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" />
</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" />
</button>
</div>
<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" />
</button>
</div>
)
}
</div>
<iframe
@@ -118,12 +118,12 @@ export const NewForm: React.FunctionComponent<INewFormProps> = ({
>
{l10n.t(LocalizationKey.dashboardSnippetsViewNewFormSnippetInputIsMediaSnippetCheckboxLabel)}
</label>
<p id="isMediaSnippet-description" className={getColors('text-vulcan-300 dark:text-whisper-500', `text-[var(--vscode-foreground)]`)}>
<p id="isMediaSnippet-description" className={`text-[var(--vscode-foreground)] text-left`}>
{l10n.t(LocalizationKey.dashboardSnippetsViewNewFormSnippetInputIsMediaSnippetCheckboxDescription)}
</p>
<p>
<button
className={getColors('text-teal-700 hover:text-teal-500', 'text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]')}
className={`text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground) text-left`}
onClick={openLink}
title={l10n.t(LocalizationKey.dashboardSnippetsViewNewFormSnippetInputDocsButtonTitle)}
>
@@ -1,9 +1,10 @@
import * as React from 'react';
import { CheckCircleIcon } from '@heroicons/react/outline';
import { CheckCircleIcon as CheckCircleIconSolid } from '@heroicons/react/solid';
import { CheckCircleIcon, PlusCircleIcon } from '@heroicons/react/outline';
import { CheckCircleIcon as CheckCircleIconSolid, PlusCircleIcon as PlusCircleIconSolid } from '@heroicons/react/solid';
export interface ISelectItemProps {
title: string;
icon?: "add" | "select";
buttonTitle: string;
isSelected: boolean;
onClick: () => void;
@@ -11,6 +12,7 @@ export interface ISelectItemProps {
export const SelectItem: React.FunctionComponent<ISelectItemProps> = ({
title,
icon = "select",
buttonTitle,
isSelected,
onClick
@@ -25,9 +27,17 @@ export const SelectItem: React.FunctionComponent<ISelectItemProps> = ({
title={buttonTitle}
>
{isSelected ? (
<CheckCircleIconSolid className={`h-4 w-4`} />
icon === "add" ? (
<PlusCircleIconSolid className={`h-4 w-4`} />
) : (
<CheckCircleIconSolid className={`h-4 w-4`} />
)
) : (
<CheckCircleIcon className={`h-4 w-4`} />
icon === "add" ? (
<PlusCircleIcon className={`h-4 w-4`} />
) : (
<CheckCircleIcon className={`h-4 w-4`} />
)
)}
<span>{title}</span>
</button>
@@ -26,11 +26,7 @@ export const Step: React.FunctionComponent<IStepProps> = ({
{status === Status.NotStarted && (
<span className="h-9 flex items-center" aria-hidden="true">
<span
className={`relative z-10 w-8 h-8 flex items-center justify-center border-2 rounded-full ${getColors(
'bg-white border-gray-300',
'bg-[var(--frontmatter-border)] border-[var(--frontmatter-border)]'
)
} ${onClick ? getColors('group-hover:text-gray-400', 'group-hover:text-[var(--vscode-button-foreground)] group-hover:border-[var(--vscode-button-hoverBackground)]') : ''
className={`relative z-10 w-8 h-8 flex items-center justify-center border-2 rounded-full bg-[var(--frontmatter-border)] border-[var(--frontmatter-border)] ${onClick ? getColors('group-hover:text-gray-400', 'group-hover:text-[var(--vscode-button-foreground)] group-hover:border-[var(--vscode-button-hoverBackground)]') : ''
}`}
>
<span
@@ -1,5 +1,5 @@
import * as React from 'react';
import { Messenger } from '@estruyf/vscode/dist/client';
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../../DashboardMessage';
import { Settings } from '../../models/Settings';
import { Status } from '../../models/Status';
@@ -7,7 +7,7 @@ import { Step } from './Step';
import { useMemo, useState } from 'react';
import { Menu } from '@headlessui/react';
import { MenuItem } from '../Menu';
import { ContentFolder, Framework, StaticFolder } from '../../../models';
import { ContentFolder, Framework, StaticFolder, Template } from '../../../models';
import { ChevronDownIcon } from '@heroicons/react/outline';
import { FrameworkDetectors } from '../../../constants/FrameworkDetectors';
import { join } from 'path';
@@ -15,6 +15,7 @@ import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { SelectItem } from './SelectItem';
import { Templates } from '../../../constants';
export interface IStepsToGetStartedProps {
settings: Settings;
@@ -51,6 +52,7 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
}: React.PropsWithChildren<IStepsToGetStartedProps>) => {
const [framework, setFramework] = useState<string | null>(null);
const [taxImported, setTaxImported] = useState<boolean>(false);
const [templates, setTemplates] = useState<Template[]>([]);
const { getColors } = useThemeColors();
const frameworks: Framework[] = FrameworkDetectors.map((detector: any) => detector.framework);
@@ -68,6 +70,14 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
Messenger.send(DashboardMessage.addAssetsFolder, folder);
}
const triggerTemplate = (template: Template) => {
messageHandler.request<boolean>(DashboardMessage.triggerTemplate, template).then((result) => {
if (result) {
reload();
}
});
}
const reload = () => {
const crntState: any = Messenger.getState() || {};
@@ -84,173 +94,207 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
setTaxImported(true);
};
const steps = [
{
id: `welcome-init`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedInitializeProjectName),
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedInitializeProjectDescription)}</>,
show: true,
status: settings.initialized ? Status.Completed : Status.NotStarted,
onClick: settings.initialized
? undefined
: () => {
Messenger.send(DashboardMessage.initializeProject);
}
},
{
id: `welcome-framework`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkName),
description: (
<div>
<div>
{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkDescription)}
</div>
const crntTemplates = useMemo(() => {
if (!templates || templates.length === 0 || !settings.crntFramework) {
return [];
}
<Menu as="div" className="relative inline-block text-left mt-4">
return templates.filter((t) => t.type === settings.crntFramework);
}, [templates, settings.crntFramework])
const steps = useMemo(() => (
[
{
id: `welcome-init`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedInitializeProjectName),
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedInitializeProjectDescription)}</>,
show: true,
status: settings.initialized ? Status.Completed : Status.NotStarted,
onClick: settings.initialized
? undefined
: () => {
Messenger.send(DashboardMessage.initializeProject);
}
},
{
id: `welcome-framework`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkName),
description: (
<div>
<div>
<Menu.Button className={`group flex justify-center p-2 rounded-md border ${getColors(
'text-vulcan-500 hover:text-vulcan-600 dark:text-whisper-500 dark:hover:text-whisper-600 border-vulcan-400 dark:border-white',
'text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]'
)
}`}>
{framework ? framework : l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkSelect)}
<ChevronDownIcon
className={`flex-shrink-0 -mr-1 ml-1 h-5 w-5 ${getColors(
'text-gray-400 group-hover:text-gray-500 dark:text-whisper-600 dark:group-hover:text-whisper-700',
''
)
}`}
aria-hidden="true"
/>
</Menu.Button>
{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkDescription)}
</div>
<Menu.Items
className={`w-40 origin-top-left absolute left-0 z-10 mt-2 rounded-md shadow-2xl ring-1 ring-opacity-5 focus:outline-none text-sm max-h-96 overflow-auto ${getColors(
'bg-white dark:bg-vulcan-500 ring-vulcan-400 dark:ring-white',
'bg-[var(--vscode-sideBar-background)] ring-[var(--frontmatter-border)]'
)
}`}
>
<div className="py-1">
<MenuItem
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkSelectOther)}
value={`other`}
isCurrent={!framework}
onClick={(value: string) => setFrameworkAndSendMessage(value)}
/>
<Menu as="div" className="relative inline-block text-left mt-4">
<div>
<Menu.Button className={`group flex justify-center p-2 rounded-md border ${getColors(
'text-vulcan-500 hover:text-vulcan-600 dark:text-whisper-500 dark:hover:text-whisper-600 border-vulcan-400 dark:border-white',
'text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]'
)
}`}>
{framework ? framework : l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkSelect)}
<ChevronDownIcon
className={`flex-shrink-0 -mr-1 ml-1 h-5 w-5 ${getColors(
'text-gray-400 group-hover:text-gray-500 dark:text-whisper-600 dark:group-hover:text-whisper-700',
''
)
}`}
aria-hidden="true"
/>
</Menu.Button>
</div>
<hr className={`border-[var(--frontmatter-border)]`} />
{frameworks.map((f) => (
<Menu.Items
className={`w-40 origin-top-left absolute left-0 z-10 mt-2 rounded-md shadow-2xl ring-1 ring-opacity-5 focus:outline-none text-sm max-h-96 overflow-auto ${getColors(
'bg-white dark:bg-vulcan-500 ring-vulcan-400 dark:ring-white',
'bg-[var(--vscode-sideBar-background)] ring-[var(--frontmatter-border)]'
)
}`}
>
<div className="py-1">
<MenuItem
key={f.name}
title={f.name}
value={f.name}
isCurrent={f.name === framework}
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkSelectOther)}
value={`other`}
isCurrent={!framework}
onClick={(value: string) => setFrameworkAndSendMessage(value)}
/>
))}
</div>
</Menu.Items>
</Menu>
</div>
),
show: true,
status: settings.crntFramework ? Status.Completed : Status.NotStarted,
onClick: undefined
},
{
id: `welcome-assets`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderName),
description: (
<div className='mt-4'>
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderDescription)}</div>
<div className="mt-1 space-y-1">
<SelectItem
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderPublicTitle)}
buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderPublicTitle)}
isSelected={settings.staticFolder === "public"}
onClick={() => addAssetFolder(`public`)} />
<SelectItem
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderAssetsTitle)}
buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderAssetsTitle)}
isSelected={settings.staticFolder === "src/assets"}
onClick={() => addAssetFolder({
"path": "src/assets",
"relative": true
})} />
<hr className={`border-[var(--frontmatter-border)]`} />
<p className='text-sm'>
<b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderOtherDescription)}</p>
{frameworks.map((f) => (
<MenuItem
key={f.name}
title={f.name}
value={f.name}
isCurrent={f.name === framework}
onClick={(value: string) => setFrameworkAndSendMessage(value)}
/>
))}
</div>
</Menu.Items>
</Menu>
</div>
</div>
),
show: settings.crntFramework === 'astro' || framework === 'astro',
status: !settings.staticFolder ? Status.NotStarted : Status.Completed,
},
{
id: `welcome-content-folders`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersName),
description: (
<>
<p>
{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersDescription)}
</p>
{settings?.dashboardState?.welcome?.contentFolders?.length > 0 && (
<div className="mt-4">
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersLabel)}</div>
<div className="mt-1 space-y-1">
{settings?.dashboardState?.welcome?.contentFolders?.map((folder: string) => (
<Folder
key={folder}
folder={folder}
addFolder={addFolder}
wsFolder={settings.wsFolder}
folders={settings.contentFolders}
/>
))}
</div>
),
show: true,
status: settings.crntFramework ? Status.Completed : Status.NotStarted,
onClick: undefined
},
{
id: `welcome-template`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTemplateName),
description: (
<div className='mt-4'>
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTemplateDescription)}</div>
<div className="mt-1 space-y-1">
{
crntTemplates && (crntTemplates || []).map(template => (
<SelectItem
key={template.name.toLowerCase().replace(/ /g, '-')}
title={template.name}
icon='add'
buttonTitle={template.name}
isSelected={false}
onClick={() => triggerTemplate(template)} />
))
}
</div>
)}
</div>
),
show: (crntTemplates || []).length > 0,
status: Status.Active,
},
{
id: `welcome-assets`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderName),
description: (
<div className='mt-4'>
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderDescription)}</div>
<div className="mt-1 space-y-1">
<SelectItem
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderPublicTitle)}
buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderPublicTitle)}
isSelected={settings.staticFolder === "public"}
onClick={() => addAssetFolder(`public`)} />
<p className={`mt-4 ${getColors('text-vulcan-300 dark:text-gray-400', '')}`}>
<b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersInformationDescription)}.
</p>
</>
),
show: true,
status:
settings.contentFolders && settings.contentFolders.length > 0
? Status.Completed
: Status.NotStarted
},
{
id: `welcome-import`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTagsName),
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTagsDescription)}</>,
show: true,
status: taxImported ? Status.Completed : Status.NotStarted,
onClick:
settings.contentFolders && settings.contentFolders.length > 0 ? importTaxonomy : undefined
},
{
id: `welcome-show-dashboard`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedShowDashboardName),
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedShowDashboardDescription)}</>,
show: true,
status:
settings.initialized && settings.contentFolders && settings.contentFolders.length > 0
? Status.Active
: Status.NotStarted,
onClick:
settings.initialized && settings.contentFolders && settings.contentFolders.length > 0
? reload
: undefined
}
];
<SelectItem
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderAssetsTitle)}
buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderAssetsTitle)}
isSelected={settings.staticFolder === "src/assets"}
onClick={() => addAssetFolder({
"path": "src/assets",
"relative": true
})} />
<p className='text-sm'>
<b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderOtherDescription)}</p>
</div>
</div>
),
show: settings.crntFramework === 'astro' || framework === 'astro',
status: settings.initialized && settings.staticFolder && settings.staticFolder !== "/" ? Status.Completed : Status.NotStarted,
},
{
id: `welcome-content-folders`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersName),
description: (
<>
<p>
{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersDescription)}
</p>
{settings?.dashboardState?.welcome?.contentFolders?.length > 0 && (
<div className="mt-4">
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersLabel)}</div>
<div className="mt-1 space-y-1">
{settings?.dashboardState?.welcome?.contentFolders?.map((folder: string) => (
<Folder
key={folder}
folder={folder}
addFolder={addFolder}
wsFolder={settings.wsFolder}
folders={settings.contentFolders}
/>
))}
</div>
</div>
)}
<p className={`mt-4 ${getColors('text-vulcan-300 dark:text-gray-400', '')}`}>
<b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersInformationDescription)}.
</p>
</>
),
show: true,
status:
settings.contentFolders && settings.contentFolders.length > 0
? Status.Completed
: Status.NotStarted
},
{
id: `welcome-import`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTagsName),
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTagsDescription)}</>,
show: true,
status: taxImported ? Status.Completed : Status.NotStarted,
onClick:
settings.contentFolders && settings.contentFolders.length > 0 ? importTaxonomy : undefined
},
{
id: `welcome-show-dashboard`,
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedShowDashboardName),
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedShowDashboardDescription)}</>,
show: true,
status:
settings.initialized && settings.contentFolders && settings.contentFolders.length > 0
? Status.Active
: Status.NotStarted,
onClick:
settings.initialized && settings.contentFolders && settings.contentFolders.length > 0
? reload
: undefined
}
]
), [settings, framework, taxImported, templates]);
React.useEffect(() => {
if (settings.crntFramework || settings.framework?.name) {
@@ -258,6 +302,23 @@ export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps>
}
}, [settings.crntFramework, settings.framework]);
React.useEffect(() => {
const fetchTemplates = async () => {
try {
const response = await fetch(Templates.url);
if (response.ok) {
const data = await response.json();
setTemplates(data);
}
} catch (e) {
setTemplates([]);
}
};
fetchTemplates();
}, []);
return (
<nav aria-label="Progress">
<ol role="list">
@@ -97,6 +97,10 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
}
}
if (typeof values === 'string') {
values = [values];
}
for (const value of values) {
if (!items.includes(value)) {
unmapped.push(value);
+3 -1
View File
@@ -4,6 +4,7 @@ import { Tab } from '../constants/Tab';
import { Page } from '../models/Page';
import { useRecoilState, useRecoilValue } from 'recoil';
import {
AllPagesAtom,
CategorySelector,
FolderSelector,
SearchSelector,
@@ -19,9 +20,10 @@ import { Messenger } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../DashboardMessage';
import { EventData } from '@estruyf/vscode/dist/models';
import { parseWinPath } from '../../helpers/parseWinPath';
import { format } from 'date-fns';
export default function usePages(pages: Page[]) {
const [pageItems, setPageItems] = useState<Page[]>([]);
const [pageItems, setPageItems] = useRecoilState(AllPagesAtom);
const [sortedPages, setSortedPages] = useState<Page[]>([]);
const [sorting, setSorting] = useRecoilState(SortingAtom);
const [tabInfo, setTabInfo] = useRecoilState(TabInfoAtom);
+13
View File
@@ -62,9 +62,22 @@ const preserveColor = (color: string | undefined) => {
return color;
}
const addBgOpacity = (color: string | undefined) => {
if (color) {
}
return color;
}
const updateCssVariables = () => {
const styles = getComputedStyle(document.documentElement);
// Lightbox
const background = styles.getPropertyValue('--vscode-editor-background');
// Adds 75% opacity to the background color
document.documentElement.style.setProperty('--frontmatter-lightbox-background', `${preserveColor(background)}BF`);
// Text
document.documentElement.style.setProperty('--frontmatter-text', 'var(--vscode-editor-foreground)');
document.documentElement.style.setProperty('--frontmatter-secondary-text', 'var(--vscode-editorHint-foreground)');
+1
View File
@@ -16,6 +16,7 @@ export interface Page {
fmTags: string[];
fmCategories: string[];
fmContentType: string;
fmDateFormat: string | undefined;
title: string;
slug: string;
+1
View File
@@ -33,6 +33,7 @@ export interface Settings {
contentTypes: ContentType[];
contentFolders: ContentFolder[];
crntFramework: string;
websiteUrl: string;
framework: Framework | null | undefined;
draftField: DraftField | null | undefined;
customSorting: SortingSetting[] | undefined;
@@ -0,0 +1,7 @@
import { atom } from 'recoil';
import { Page } from '../../models';
export const AllPagesAtom = atom<Page[]>({
key: 'AllPagesAtom',
default: []
});
+1
View File
@@ -1,4 +1,5 @@
export * from './AllContentFoldersAtom';
export * from './AllPagesAtom';
export * from './AllStaticFoldersAtom';
export * from './CategoryAtom';
export * from './DashboardViewAtom';
+30 -33
View File
@@ -4,10 +4,15 @@ import { COMMAND_NAME, TelemetryEvent } from './constants';
import { MarkdownFoldingProvider } from './providers/MarkdownFoldingProvider';
import { TagType } from './panelWebView/TagType';
import { PanelProvider } from './panelWebView/PanelProvider';
import { DashboardSettings, debounceCallback, Logger, Settings as SettingsHelper } from './helpers';
import {
DashboardSettings,
debounceCallback,
Logger,
parseWinPath,
Settings as SettingsHelper
} from './helpers';
import ContentProvider from './providers/ContentProvider';
import { PagesListener } from './listeners/dashboard';
import { DataListener, SettingsListener } from './listeners/panel';
import { NavigationType } from './dashboardWebView/models';
import { ModeSwitch } from './services/ModeSwitch';
import { PagesParser } from './services/PagesParser';
@@ -30,9 +35,9 @@ import {
StatusListener,
Chatbot
} from './commands';
import { join } from 'path';
let frontMatterStatusBar: vscode.StatusBarItem;
let statusDebouncer: { (fnc: any, time: number): void };
let pageUpdateDebouncer: { (fnc: any, time: number): void };
let editDebounce: { (fnc: any, time: number): void };
let collection: vscode.DiagnosticCollection;
@@ -45,7 +50,7 @@ export async function activate(context: vscode.ExtensionContext) {
// Make sure the EN language file is loaded
if (!vscode.l10n.uri) {
l10n.config({
fsPath: vscode.Uri.parse(`${extensionPath}/l10n/bundle.l10n.json`).fsPath
fsPath: vscode.Uri.file(join(parseWinPath(extensionPath), `/l10n/bundle.l10n.json`)).fsPath
});
} else {
l10n.config({
@@ -184,12 +189,6 @@ export async function activate(context: vscode.ExtensionContext) {
)
);
const toggleDraftCommand = COMMAND_NAME.toggleDraft;
const toggleDraft = vscode.commands.registerCommand(toggleDraftCommand, async () => {
await Article.toggleDraft();
triggerShowDraftStatus(`toggleDraft`);
});
// Register project folders
const registerFolder = vscode.commands.registerCommand(
COMMAND_NAME.registerFolder,
@@ -268,32 +267,30 @@ export async function activate(context: vscode.ExtensionContext) {
});
// Things to do when configuration changes
SettingsHelper.onConfigChange(() => {
Preview.init();
GitListener.init();
SettingsListener.getSettings();
DataListener.getFoldersAndFiles();
MarkdownFoldingProvider.triggerHighlighting(true);
ModeSwitch.register();
});
SettingsHelper.startListening();
// Create the status bar
frontMatterStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
frontMatterStatusBar.command = toggleDraftCommand;
subscriptions.push(frontMatterStatusBar);
statusDebouncer = debounceCallback();
let fmStatusBarItem = vscode.window.createStatusBarItem(
'fm-statusBarItem',
vscode.StatusBarAlignment.Right,
-100
);
fmStatusBarItem.command = COMMAND_NAME.dashboard;
fmStatusBarItem.text = `$(fm-logo)`;
fmStatusBarItem.tooltip = `Front Matter CMS`;
fmStatusBarItem.show();
// Register listeners that make sure the status bar updates
pageUpdateDebouncer = debounceCallback();
subscriptions.push(
vscode.window.onDidChangeActiveTextEditor(() =>
triggerShowDraftStatus(`onDidChangeActiveTextEditor`)
triggerPageUpdate(`onDidChangeActiveTextEditor`)
)
);
subscriptions.push(
vscode.window.onDidChangeTextEditorSelection((e) => {
if (e.kind === vscode.TextEditorSelectionChangeKind.Mouse) {
statusDebouncer(() => triggerShowDraftStatus(`onDidChangeTextEditorSelection`), 200);
pageUpdateDebouncer(() => triggerPageUpdate(`onDidChangeTextEditorSelection`), 200);
}
})
);
@@ -302,13 +299,13 @@ export async function activate(context: vscode.ExtensionContext) {
const filePath = TextDocumentChangeEvent.document.uri.fsPath;
if (filePath && !filePath.toLowerCase().startsWith(`extension-output`)) {
MarkdownFoldingProvider.triggerHighlighting();
statusDebouncer(() => triggerShowDraftStatus(`onDidChangeTextEditorSelection`), 200);
pageUpdateDebouncer(() => triggerPageUpdate(`onDidChangeTextEditorSelection`), 200);
}
})
);
// Automatically run the command
triggerShowDraftStatus(`triggerShowDraftStatus`);
triggerPageUpdate(`main`);
// Listener for file edit changes
subscriptions.push(vscode.workspace.onWillSaveTextDocument(handleAutoDateUpdate));
@@ -380,14 +377,14 @@ export async function activate(context: vscode.ExtensionContext) {
generateSlug,
createFromTemplate,
createTemplate,
toggleDraft,
registerFolder,
unregisterFolder,
createContent,
createByContentType,
createByTemplate,
collapseAll,
createFolder
createFolder,
fmStatusBarItem
);
console.log(`𝖥𝗋𝗈𝗇𝗍 𝖬𝖺𝗍𝗍𝖾𝗋 𝖢𝖬𝖲 𝖺𝖼𝗍𝗂𝗏𝖺𝗍𝖾𝖽! 𝖱𝖾𝖺𝖽𝗒 𝗍𝗈 𝗌𝗍𝖺𝗋𝗍 𝗐𝗋𝗂𝗍𝗂𝗇𝗀... 👩‍💻🧑‍💻👨‍💻`);
@@ -399,9 +396,9 @@ const handleAutoDateUpdate = (e: vscode.TextDocumentWillSaveEvent) => {
Article.autoUpdate(e);
};
const triggerShowDraftStatus = (location: string) => {
const triggerPageUpdate = (location: string) => {
Logger.info(`Triggering draft status update: ${location}`);
statusDebouncer(() => {
StatusListener.verify(frontMatterStatusBar, collection);
pageUpdateDebouncer(() => {
StatusListener.verify(collection);
}, 1000);
};
+2 -2
View File
@@ -23,7 +23,7 @@ import {
} from '../constants';
import { DumpOptions } from 'js-yaml';
import { FrontMatterParser, ParsedFrontMatter } from '../parsers';
import { Extension, Logger, Settings, SlugHelper } from '.';
import { Extension, Logger, Settings, SlugHelper, parseWinPath } from '.';
import { format, parse } from 'date-fns';
import { Notifications } from './Notifications';
import { Article } from '../commands';
@@ -110,7 +110,7 @@ export class ArticleHelper {
* @param article
*/
public static async updateByPath(path: string, article: ParsedFrontMatter) {
const file = await workspace.openTextDocument(Uri.parse(path));
const file = await workspace.openTextDocument(Uri.file(parseWinPath(path)));
if (file) {
const update = this.generateUpdate(file, article);
+51 -9
View File
@@ -349,6 +349,25 @@ export class ContentType {
return data;
}
/**
* Find the field by its name
* @param fields
* @param name
* @returns
*/
public static findFieldByName(fields: Field[], name: string): Field | undefined {
for (const field of fields) {
if (field.name === name) {
return field;
} else if (field.type === 'fields' && field.fields) {
const subField = this.findFieldByName(field.fields, name);
if (subField) {
return subField;
}
}
}
}
/**
* Find the field by its type
* @param fields
@@ -737,7 +756,8 @@ export class ContentType {
contentType,
titleValue,
templateData?.data || {},
newFilePath
newFilePath,
!!contentType.clearEmpty
);
data = ArticleHelper.updateDates(Object.assign({}, data));
@@ -785,6 +805,7 @@ export class ContentType {
titleValue: string,
data: any,
filePath: string,
clearEmpty: boolean,
isRoot: boolean = true
): Promise<any> {
if (obj.fields) {
@@ -805,12 +826,23 @@ export class ContentType {
);
} else if (isRoot) {
data[field.name] = titleValue;
} else {
} else if (!clearEmpty) {
data[field.name] = '';
}
} else {
if (field.type === 'fields') {
data[field.name] = await this.processFields(field, titleValue, {}, filePath, false);
data[field.name] = await this.processFields(
field,
titleValue,
{},
filePath,
clearEmpty,
false
);
if (clearEmpty && Object.keys(data[field.name]).length === 0) {
delete data[field.name];
}
} else {
const defaultValue = field.default;
@@ -841,30 +873,40 @@ export class ContentType {
case 'choice':
if (field.multiple) {
data[field.name] = [];
} else {
} else if (!clearEmpty) {
data[field.name] = '';
}
break;
case 'boolean':
data[field.name] = false;
if (!clearEmpty) {
data[field.name] = false;
}
break;
case 'number':
data[field.name] = 0;
if (!clearEmpty) {
data[field.name] = 0;
}
break;
case 'datetime':
data[field.name] = null;
if (!clearEmpty) {
data[field.name] = null;
}
break;
case 'list':
case 'tags':
case 'categories':
case 'taxonomy':
data[field.name] = [];
if (!clearEmpty) {
data[field.name] = [];
}
break;
case 'string':
case 'image':
case 'file':
default:
data[field.name] = '';
if (!clearEmpty) {
data[field.name] = '';
}
break;
}
}
+11 -2
View File
@@ -222,7 +222,12 @@ export class CustomScript {
let articleData = '';
if (os.type() === 'Windows_NT') {
const jsonData = JSON.stringify(article?.data);
articleData = `'${jsonData.replace(/"/g, `\"`)}'`;
if (script.command && script.command.toLowerCase() === "powershell") {
articleData = `'${jsonData.replace(/"/g, `\\"`)}'`;
} else {
articleData = `"${jsonData.replace(/"/g, `\\"`)}"`;
}
} else {
articleData = JSON.stringify(article?.data).replace(/'/g, '%27');
articleData = `'${articleData}'`;
@@ -360,7 +365,11 @@ export class CustomScript {
return;
}
const fullScript = `${command} ${scriptPath} ${args}`;
if (osType === 'Windows_NT' && command.toLowerCase() === "powershell") {
command = `${command} -File`;
}
const fullScript = `${command} "${scriptPath}" ${args}`;
Logger.info(`Executing: ${fullScript}`);
exec(fullScript, { cwd: wsPath }, (error, stdout) => {
+4 -2
View File
@@ -29,7 +29,8 @@ import {
SETTING_DASHBOARD_CONTENT_CARD_DATE,
SETTING_DASHBOARD_CONTENT_CARD_TITLE,
SETTING_DASHBOARD_CONTENT_CARD_STATE,
SETTING_DASHBOARD_CONTENT_CARD_DESCRIPTION
SETTING_DASHBOARD_CONTENT_CARD_DESCRIPTION,
SETTING_WEBSITE_URL
} from '../constants';
import {
DashboardViewType,
@@ -131,7 +132,8 @@ export class DashboardSettings {
dataTypes: Settings.get<DataType[]>(SETTING_DATA_TYPES),
snippets: Settings.get<Snippets>(SETTING_CONTENT_SNIPPETS),
snippetsWrapper: Settings.get<boolean>(SETTING_SNIPPETS_WRAPPER),
isBacker: await ext.getState<boolean | undefined>(CONTEXT.backer, 'global')
isBacker: await ext.getState<boolean | undefined>(CONTEXT.backer, 'global'),
websiteUrl: Settings.get<string>(SETTING_WEBSITE_URL)
} as ISettings;
return settings;
+8 -1
View File
@@ -331,8 +331,12 @@ export class Extension {
let storageUri: Uri | undefined = undefined;
if (type === 'global') {
storageUri = await this.createGlobalStorageIfNotExists();
// Clear workspace state
await this.ctx.globalState.update(propKey, undefined);
} else {
storageUri = await this.createLocalStorageIfNotExists();
// Clear workspace state
await this.ctx.workspaceState.update(propKey, undefined);
}
if (storageUri) {
@@ -429,7 +433,10 @@ export class Extension {
* @returns
*/
private isFileStorageNeeded(propKey: string) {
return propKey === ExtensionState.Dashboard.Pages.Cache;
return (
propKey === ExtensionState.Dashboard.Pages.Cache ||
propKey === ExtensionState.Dashboard.Pages.Index
);
}
/**
+8 -8
View File
@@ -122,14 +122,7 @@ export class FrameworkDetector {
relAssetPath = relAssetPath.substring(1);
}
}
// Support for HEXO image folder
else if (frameworkId === 'hexo') {
relAssetPath = parseWinPath(relAssetPath);
if (relAssetPath.startsWith('/')) {
relAssetPath = relAssetPath.substring(1);
}
}
// Support for the Astro assets folder
// Support for the Astro assets folder or when you need relative paths
else if (
staticFolder &&
staticFolderValue &&
@@ -147,6 +140,13 @@ export class FrameworkDetector {
relAssetPath = relative(fileDir, assetDir);
relAssetPath = join(relAssetPath, `${fileName.name}${fileName.ext}`);
}
// Support for HEXO image folder
else if (frameworkId === 'hexo') {
relAssetPath = parseWinPath(relAssetPath);
if (relAssetPath.startsWith('/')) {
relAssetPath = relAssetPath.substring(1);
}
}
return parseWinPath(relAssetPath);
}
+2
View File
@@ -77,6 +77,8 @@ export class ImageHelper {
} else if (workspaceFolderPath && existsSync(workspaceFolderPath)) {
return Uri.file(workspaceFolderPath);
}
return null;
}
/**
+5 -2
View File
@@ -1,4 +1,4 @@
import { SETTING_SPONSORS_AI_ENABLED } from './../constants/settings';
import { SETTING_SPONSORS_AI_ENABLED, SETTING_WEBSITE_URL } from './../constants/settings';
import { workspace } from 'vscode';
import { Extension, Settings, TaxonomyHelper } from '.';
import { Dashboard } from '../commands/Dashboard';
@@ -41,6 +41,7 @@ import {
ScriptType,
TaxonomyType
} from '../models';
import { Folders } from '../commands';
export class PanelSettings {
public static async get(): Promise<IPanelSettings> {
@@ -94,7 +95,9 @@ export class PanelSettings {
start: Settings.get<string>(SETTING_FRAMEWORK_START)
},
dataTypes: Settings.get<DataType[]>(SETTING_DATA_TYPES),
fieldGroups: Settings.get<FieldGroup[]>(SETTING_TAXONOMY_FIELD_GROUPS)
fieldGroups: Settings.get<FieldGroup[]>(SETTING_TAXONOMY_FIELD_GROUPS),
contentFolders: Folders.get(),
websiteUrl: Settings.get<string>(SETTING_WEBSITE_URL) || ''
};
}
+93 -33
View File
@@ -1,10 +1,10 @@
import { SETTING_EXTENSIBILITY_SCRIPTS, SETTING_PROJECTS } from './../constants/settings';
import { SETTING_PROJECTS } from './../constants/settings';
import { parseWinPath } from './parseWinPath';
import { Telemetry } from './Telemetry';
import { Notifications } from './Notifications';
import { commands, Uri, workspace, window } from 'vscode';
import * as vscode from 'vscode';
import { ContentType, CustomTaxonomy, Project, TaxonomyType } from '../models';
import { ContentType, CustomTaxonomy, Project } from '../models';
import {
SETTING_TAXONOMY_TAGS,
SETTING_TAXONOMY_CATEGORIES,
@@ -42,7 +42,11 @@ import { debounceCallback } from './DebounceCallback';
import { Logger } from './Logger';
import * as jsoncParser from 'jsonc-parser';
import { existsAsync, fetchWithTimeout, readFileAsync, writeFileAsync } from '../utils';
import { Cache } from '../commands';
import { Cache, Preview } from '../commands';
import { GitListener } from '../listeners/general';
import { DataListener } from '../listeners/panel';
import { MarkdownFoldingProvider } from '../providers/MarkdownFoldingProvider';
import { ModeSwitch } from '../services/ModeSwitch';
export class Settings {
public static globalFile = 'frontmatter.json';
@@ -50,15 +54,17 @@ export class Settings {
public static globalConfig: any;
private static config: vscode.WorkspaceConfiguration;
private static isInitialized: boolean = false;
private static listeners: any[] = [];
private static listeners: { id: string; callback: (global?: any) => void }[] = [];
private static fileCreationWatcher: vscode.FileSystemWatcher | undefined;
private static fileChangeWatcher: vscode.FileSystemWatcher | undefined;
private static fileSaveListener: vscode.Disposable;
private static fileDeleteListener: vscode.Disposable;
private static readConfigPromise: Promise<void> | undefined = undefined;
private static project: Project | undefined = undefined;
private static configDebouncer = debounceCallback();
public static async init() {
const allCommands = await commands.getCommands(true);
await Settings.readConfig();
const projects = Settings.getProjects();
@@ -87,14 +93,37 @@ export class Settings {
if (!Settings.isInitialized) {
Settings.isInitialized = true;
commands.registerCommand(COMMAND_NAME.reloadConfig, Settings.rebindWatchers);
if (!allCommands.includes(COMMAND_NAME.reloadConfig)) {
commands.registerCommand(COMMAND_NAME.reloadConfig, Settings.rebindWatchers);
}
}
if (!allCommands.includes(COMMAND_NAME.settingsRefresh)) {
commands.registerCommand(COMMAND_NAME.settingsRefresh, Settings.reloadConfig);
}
Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY);
Settings.onConfigChange(async () => {
Settings.attachListener('settings-init', async () => {
Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY);
});
Settings.onConfigChange();
}
/**
* Start listening to changes
*/
public static startListening() {
// Things to do when configuration changes
Settings.attachListener('settings-global', () => {
Preview.init();
GitListener.init();
DataListener.getFoldersAndFiles();
MarkdownFoldingProvider.triggerHighlighting(true);
ModeSwitch.register();
});
}
/**
@@ -164,21 +193,46 @@ export class Settings {
}
}
/**
* Attach a new listener for the setting changes
* @param id
* @param callback
* @returns
*/
public static attachListener(id: string, callback: (global?: any) => void) {
const listener = Settings.listeners.find((l) => l.id === id);
if (listener) {
listener.callback = callback;
return;
}
Settings.listeners.push({
id,
callback
});
}
/**
* Trigger all the listeners
*/
public static triggerListeners() {
for (const listener of Settings.listeners) {
Logger.info(`Triggering listener: ${listener.id}`);
listener.callback();
}
}
/**
* Check for config changes on global and local settings
* @param callback
*/
public static onConfigChange(callback: (global?: any) => void) {
public static onConfigChange() {
const projectConfig = Settings.projectConfigPath;
const configDebouncer = debounceCallback();
workspace.onDidChangeConfiguration(() => {
callback();
Settings.triggerListeners();
});
// Keep track of the listeners
Settings.listeners.push(callback);
if (projectConfig && !existsSync(projectConfig)) {
// No config file, no need to watch
Settings.createFileCreationWatcher();
@@ -199,25 +253,10 @@ export class Settings {
);
Settings.fileChangeWatcher.onDidChange(async () => {
Logger.info(`Config change detected - ${projectConfig} changed`);
configDebouncer(() => callback(), 200);
Settings.configDebouncer(() => Settings.triggerListeners(), 200);
});
}
const reloadConfig = async (debounced: boolean = true) => {
Logger.info(`Reloading config...`);
if (Settings.readConfigPromise === undefined) {
Settings.readConfigPromise = Settings.readConfig();
}
await Settings.readConfigPromise;
Logger.info(`Reloaded config...`);
if (debounced) {
configDebouncer(() => callback(), 200);
} else {
callback();
}
};
if (Settings.fileSaveListener) {
Settings.fileSaveListener.dispose();
}
@@ -227,7 +266,7 @@ export class Settings {
if (Settings.checkProjectConfig(filename)) {
Logger.info(`Config change detected - ${filename} saved`);
await reloadConfig();
await Settings.reloadConfig();
}
});
@@ -238,7 +277,7 @@ export class Settings {
Settings.fileDeleteListener = workspace.onDidDeleteFiles(async (e) => {
const needCallback = e?.files.find((f) => Settings.checkProjectConfig(f.fsPath));
if (needCallback) {
await reloadConfig(false);
await Settings.reloadConfig(false);
}
});
}
@@ -909,6 +948,7 @@ export class Settings {
Settings.fileCreationWatcher.onDidCreate(
(uri) => {
if (parseWinPath(uri.fsPath) === parseWinPath(Settings.projectConfigPath)) {
Settings.onConfigChange();
Settings.rebindWatchers();
// Stop listening to file creation events
Settings.fileCreationWatcher?.dispose();
@@ -927,10 +967,11 @@ export class Settings {
private static rebindWatchers() {
Logger.info(`Rebinding ${this.listeners.length} listeners`);
this.listeners.forEach((l) => {
Settings.onConfigChange(l);
l();
Settings.listeners.forEach((l) => {
Settings.attachListener(l.id, l.callback);
});
Settings.triggerListeners();
}
/**
@@ -985,4 +1026,23 @@ export class Settings {
return config;
}
/**
* Reload the config
* @param debounced
*/
private static async reloadConfig(debounced: boolean = true) {
Logger.info(`Reloading config...`);
if (Settings.readConfigPromise === undefined) {
Settings.readConfigPromise = Settings.readConfig();
}
await Settings.readConfigPromise;
Logger.info(`Reloaded config...`);
if (debounced) {
Settings.configDebouncer(() => Settings.triggerListeners(), 200);
} else {
Settings.triggerListeners();
}
}
}
+17 -5
View File
@@ -8,11 +8,23 @@ export class SnippetParser {
closingTags: string = ']]'
): string[] {
const template = SnippetParser.template(value);
return Mustache.parse(template, [openingTags, closingTags])
.filter((v) => v[0] === 'name' || v[0] === '&')
.map((v) => {
return v[1];
});
const parseTree = Mustache.parse(template, [openingTags, closingTags]);
const flattenVariablesFromParseTree = (acc: any, v: any) => {
if (v[0] === 'name') {
return acc.concat([v]);
} else if (v[0] === '&') {
return acc.concat([v]);
} else if (v[0] === '#') {
return acc.concat(v[4].reduce(flattenVariablesFromParseTree, []));
} else {
return acc;
}
};
const variables = parseTree.reduce(flattenVariablesFromParseTree, []).map((v: any) => v[1]);
return variables;
}
public static render(
+17 -2
View File
@@ -1,4 +1,4 @@
import { useState, useEffect, useCallback, useMemo } from 'react';
import { useState, useEffect } from 'react';
import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from '../constants/ContentType';
import { Settings } from '../dashboardWebView/models';
import { ContentType, PanelSettings } from '../models';
@@ -11,7 +11,22 @@ export default function useContentType(
useEffect(() => {
if (settings) {
const contentTypeName = (metadata.type as string) || DEFAULT_CONTENT_TYPE_NAME;
let contentTypeName = DEFAULT_CONTENT_TYPE_NAME;
if (metadata?.type) {
contentTypeName = metadata.type;
}
// Get the content type by the folder name
const pageFolders = settings.contentFolders;
let pageFolderMatches = pageFolders.filter((folder) => metadata.filePath.includes(folder.path));
// Sort by longest path
pageFolderMatches = pageFolderMatches.sort((a, b) => b.path.length - a.path.length);
if (pageFolderMatches.length > 0 && pageFolderMatches[0].contentTypes && pageFolderMatches[0].contentTypes.length === 1) {
contentTypeName = pageFolderMatches[0].contentTypes[0];
}
let ct = settings.contentTypes.find((ct) => ct.name === contentTypeName);
if (!ct) {
+9 -1
View File
@@ -13,11 +13,19 @@ export abstract class BaseListener {
* @param data
*/
public static sendMsg(command: DashboardCommand, payload: any) {
Logger.info(`Sending message to webview: ${command}`);
Logger.info(`Sending message to dashboard: ${command}`);
Dashboard.postWebviewMessage({
command,
payload
});
}
public static sendRequest(command: DashboardCommand, requestId: string, payload: any) {
Dashboard.postWebviewMessage({
command,
requestId,
payload
});
}
}
+3 -2
View File
@@ -243,7 +243,7 @@ export class PagesListener extends BaseListener {
const pagesIndex = Fuse.createIndex(['title', 'slug', 'description', 'fmBody', 'type'], pages);
await Extension.getInstance().setState(
ExtensionState.Dashboard.Pages.Index,
pagesIndex,
pagesIndex.toJSON(),
'workspace'
);
}
@@ -279,7 +279,8 @@ export class PagesListener extends BaseListener {
ExtensionState.Dashboard.Pages.Index,
'workspace'
);
const fuse = new Fuse(this.lastPages, fuseOptions, pagesIndex);
const fuseIndex = Fuse.parseIndex(pagesIndex);
const fuse = new Fuse(this.lastPages, fuseOptions, fuseIndex);
const results = fuse.search(data.query || '');
const pageResults = results.map((page) => page.item);
+93 -3
View File
@@ -1,5 +1,5 @@
import { join } from 'path';
import { commands, Uri } from 'vscode';
import { commands, FileType, Uri, workspace, window, ProgressLocation } from 'vscode';
import { Folders } from '../../commands/Folders';
import {
COMMAND_NAME,
@@ -10,9 +10,9 @@ import {
} from '../../constants';
import { DashboardCommand } from '../../dashboardWebView/DashboardCommand';
import { DashboardMessage } from '../../dashboardWebView/DashboardMessage';
import { DashboardSettings, Extension, Settings } from '../../helpers';
import { DashboardSettings, Extension, Notifications, Settings } from '../../helpers';
import { FrameworkDetector } from '../../helpers/FrameworkDetector';
import { Framework, PostMessageData, StaticFolder } from '../../models';
import { Framework, Template, PostMessageData, StaticFolder } from '../../models';
import { BaseListener } from './BaseListener';
import { Cache } from '../../commands/Cache';
import { Preview } from '../../commands';
@@ -21,6 +21,10 @@ import { DataListener } from '../panel';
import { MarkdownFoldingProvider } from '../../providers/MarkdownFoldingProvider';
import { ModeSwitch } from '../../services/ModeSwitch';
import { PagesListener } from './PagesListener';
import { existsAsync } from '../../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../localization';
import download from 'github-directory-downloader/esm';
export class SettingsListener extends BaseListener {
/**
@@ -46,6 +50,9 @@ export class SettingsListener extends BaseListener {
case DashboardMessage.addAssetsFolder:
this.addAssetsFolder(msg?.payload);
break;
case DashboardMessage.triggerTemplate:
this.triggerTemplate(msg?.requestId, msg?.payload);
break;
case DashboardMessage.switchProject:
this.switchProject(msg.payload);
break;
@@ -141,4 +148,87 @@ export class SettingsListener extends BaseListener {
commands.executeCommand(COMMAND_NAME.registerFolder, folderUri);
}
}
/**
* Adds the template files to the workspace
* @param template
*/
private static async triggerTemplate(requestId?: string, template?: Template) {
if (template && template.url) {
const wsFolder = Folders.getWorkspaceFolder();
if (!wsFolder) {
return;
}
await window.withProgress(
{
location: ProgressLocation.Notification,
title: 'Downloading and initializing the template...',
cancellable: false
},
async (progress) => {
try {
const ghFolder = await download(template.url, wsFolder.fsPath);
if (!ghFolder.downloaded) {
Notifications.error('Failed to download the template.');
return;
}
await Settings.init();
await SettingsListener.getSettings(true);
if (requestId) {
this.sendRequest(DashboardMessage.triggerTemplate as any, requestId, true);
Notifications.info(
l10n.t(
LocalizationKey.listenersDashboardSettingsListenerTriggerTemplateNotification
)
);
}
} catch (e) {
Notifications.error(`Failed to initialize the template.`);
}
}
);
}
}
/**
* Copies all the template files to the workspace
* @param files
* @param templateFileLocation
* @param extRelPath
* @returns
*/
private static async copyTemplateFiles(
files: [string, FileType][],
templateFileLocation: string,
extRelPath: string = ''
) {
const wsFolder = Folders.getWorkspaceFolder();
if (!wsFolder) {
return;
}
for (const file of files) {
const crntFolderPath = join(extRelPath, file[0]);
const extFilePath = join(templateFileLocation, crntFolderPath);
if (file[1] === FileType.Directory) {
const allFiles = await workspace.fs.readDirectory(Uri.file(extFilePath));
const wsFolderPath = join(wsFolder.fsPath || '', crntFolderPath);
await workspace.fs.createDirectory(Uri.file(wsFolderPath));
await this.copyTemplateFiles(allFiles, templateFileLocation, crntFolderPath);
} else {
const wsFilePath = join(wsFolder.fsPath || '', crntFolderPath);
await workspace.fs.copy(Uri.file(extFilePath), Uri.file(wsFilePath), {
overwrite: true
});
}
}
}
}
+41 -2
View File
@@ -1,10 +1,12 @@
import { GeneralCommands } from './../../constants/GeneralCommands';
import { Dashboard } from '../../commands/Dashboard';
import { PanelProvider } from '../../panelWebView/PanelProvider';
import { Extension } from '../../helpers';
import { ArticleHelper, Extension } from '../../helpers';
import { Logger } from '../../helpers/Logger';
import { commands, Uri } from 'vscode';
import { commands, Uri, window } from 'vscode';
import { PostMessageData } from '../../models';
import { Preview } from '../../commands';
import { urlJoin } from 'url-join-ts';
export abstract class BaseListener {
public static process(msg: PostMessageData) {
@@ -14,6 +16,9 @@ export abstract class BaseListener {
commands.executeCommand('vscode.open', Uri.parse(msg.payload));
}
break;
case GeneralCommands.toVSCode.openOnWebsite:
this.openOnWebsite(msg.payload);
break;
}
}
@@ -32,4 +37,38 @@ export abstract class BaseListener {
Dashboard.postWebviewMessage({ command: command as any, payload });
}
/**
* Open the page on the website
* @param param0
* @returns
*/
private static async openOnWebsite({
websiteUrl,
filePath
}: {
websiteUrl: string;
filePath?: string;
}) {
if (websiteUrl) {
const article = filePath
? await ArticleHelper.getFrontMatterByPath(filePath)
: ArticleHelper.getCurrent();
if (article) {
if (!filePath) {
const editor = window.activeTextEditor;
if (!editor) {
return;
}
filePath = editor.document.uri.fsPath;
}
const slug = await Preview.getContentSlug(article, filePath);
const fullUrl = urlJoin(websiteUrl, slug);
commands.executeCommand('vscode.open', fullUrl);
}
}
}
}
+40
View File
@@ -57,6 +57,9 @@ export class DataListener extends BaseListener {
case CommandToCode.stopServer:
this.stopServer();
break;
case CommandToCode.isServerStarted:
this.isServerStarted(msg.command, msg?.requestId);
break;
case CommandToCode.updatePlaceholder:
this.updatePlaceholder(msg?.payload?.field, msg?.payload?.value, msg?.payload?.title);
break;
@@ -232,6 +235,8 @@ export class DataListener extends BaseListener {
return;
}
const titleField = (Settings.get(SETTING_SEO_TITLE_FIELD) as string) || DefaultFields.Title;
const editor = window.activeTextEditor;
let article;
@@ -248,6 +253,10 @@ export class DataListener extends BaseListener {
const contentType = ArticleHelper.getContentType(article.data);
if (!value && field !== titleField && contentType.clearEmpty) {
value = undefined;
}
const dateFields = ContentType.findFieldsByTypeDeep(contentType.fields, 'datetime');
const imageFields = ContentType.findFieldsByTypeDeep(contentType.fields, 'image');
const fileFields = ContentType.findFieldsByTypeDeep(contentType.fields, 'file');
@@ -263,6 +272,7 @@ export class DataListener extends BaseListener {
}
});
// Check multi-image fields
const multiImageFieldsArray = imageFields.find((f: Field[]) => {
const lastField = f?.[f.length - 1];
if (lastField) {
@@ -270,6 +280,7 @@ export class DataListener extends BaseListener {
}
});
// Check multi-file fields
const multiFileFieldsArray = fileFields.find((f: Field[]) => {
const lastField = f?.[f.length - 1];
if (lastField) {
@@ -277,6 +288,7 @@ export class DataListener extends BaseListener {
}
});
// Check date fields
if (dateFieldsArray && dateFieldsArray.length > 0) {
for (const dateField of dateFieldsArray) {
if (field === dateField.name && value) {
@@ -322,6 +334,18 @@ export class DataListener extends BaseListener {
}
}
// Clear the field if it is empty
if (
value === undefined ||
(value instanceof Array && value.length === 0 && contentType.clearEmpty)
) {
delete parentObj[field];
}
if (Object.keys(parentObj).length === 0 && field !== titleField && contentType.clearEmpty) {
delete article.data[parents![0]];
}
if (editor) {
ArticleHelper.update(editor, article);
} else if (filePath) {
@@ -502,6 +526,8 @@ export class DataListener extends BaseListener {
localServerTerminal.sendText(command);
localServerTerminal.show(false);
}
this.sendMsg(Command.serverStarted, true);
}
}
@@ -513,6 +539,20 @@ export class DataListener extends BaseListener {
if (localServerTerminal) {
localServerTerminal.dispose();
}
this.sendMsg(Command.serverStarted, false);
}
/**
* Checks if the server is started
*/
private static isServerStarted(command: string, requestId?: string) {
if (!command || !requestId) {
return;
}
const localServerTerminal = DataListener.findServerTerminal();
this.sendRequest(command, requestId, !!localServerTerminal);
}
/**
+13 -9
View File
@@ -70,17 +70,21 @@ export class MediaListener extends BaseListener {
}
}
private static generateUrl(data: string) {
private static generateUrl(
data: string | { original: string; absPath: string; webviewUrl: string }
) {
const filePath = window.activeTextEditor?.document.uri.fsPath;
const imgUrl = ImageHelper.relToAbs(filePath || '', data);
if (imgUrl) {
const viewUrl = PanelProvider.getInstance().getWebview()?.asWebviewUri(imgUrl);
if (viewUrl) {
this.sendMsg(Command.sendMediaUrl, {
original: data,
url: viewUrl.toString()
});
if (typeof data === 'string') {
const imgUrl = ImageHelper.relToAbs(filePath || '', data);
if (imgUrl) {
const viewUrl = PanelProvider.getInstance().getWebview()?.asWebviewUri(imgUrl);
if (viewUrl) {
this.sendMsg(Command.sendMediaUrl, {
original: data,
url: viewUrl.toString()
});
}
}
}
}
+17 -1
View File
@@ -87,6 +87,10 @@ export enum LocalizationKey {
* Sorry, something went wrong.
*/
commonErrorMessage = 'common.error.message',
/**
* Open on website
*/
commonOpenOnWebsite = 'common.openOnWebsite',
/**
* Developer mode
*/
@@ -791,6 +795,14 @@ export enum LocalizationKey {
* Once all actions are completed, the dashboard can be loaded.
*/
dashboardStepsStepsToGetStartedShowDashboardDescription = 'dashboard.steps.stepsToGetStarted.showDashboard.description',
/**
* Use a configuration template
*/
dashboardStepsStepsToGetStartedTemplateName = 'dashboard.steps.stepsToGetStarted.template.name',
/**
* Select a template to prefill the frontmatter.json file with the recommended settings.
*/
dashboardStepsStepsToGetStartedTemplateDescription = 'dashboard.steps.stepsToGetStarted.template.description',
/**
* Add {0} to taxonomy settings
*/
@@ -1335,5 +1347,9 @@ export enum LocalizationKey {
/**
* Continue in the media dashboard to select the image you want to insert.
*/
panelViewPanelMediaInsert = 'panel.viewPanel.mediaInsert'
panelViewPanelMediaInsert = 'panel.viewPanel.mediaInsert',
/**
* Template files copied.
*/
listenersDashboardSettingsListenerTriggerTemplateNotification = 'listeners.dashboard.settingsListener.triggerTemplate.notification'
}
+4 -1
View File
@@ -1,5 +1,5 @@
import { FileStat } from 'vscode';
import { DraftField, GitSettings } from '.';
import { ContentFolder, DraftField, GitSettings } from '.';
import { Choice } from './Choice';
import { DashboardData } from './DashboardData';
import { DataType } from './DataType';
@@ -29,6 +29,8 @@ export interface PanelSettings {
fieldGroups: FieldGroup[] | undefined;
commaSeparatedFields: string[];
aiEnabled: boolean;
contentFolders: ContentFolder[];
websiteUrl: string;
}
export interface FieldGroup {
@@ -52,6 +54,7 @@ export interface ContentType {
template?: string;
postScript?: string;
filePrefix?: string;
clearEmpty?: boolean;
}
export type FieldType =
+8
View File
@@ -0,0 +1,8 @@
export interface Template {
name: string;
description: string;
url: string;
version: string;
author: string;
type: string;
}
+1
View File
@@ -24,4 +24,5 @@ export * from './SortingSetting';
export * from './StaticFolder';
export * from './TaxonomyData';
export * from './TaxonomyType';
export * from './Template';
export * from './VersionInfo';
+2 -1
View File
@@ -10,5 +10,6 @@ export enum Command {
sendMediaUrl = 'sendMediaUrl',
updatePlaceholder = 'updatePlaceholder',
dataFileEntries = 'dataFileEntries',
updatedSlug = 'updatedSlug'
updatedSlug = 'updatedSlug',
serverStarted = 'server-started'
}
+2 -1
View File
@@ -43,5 +43,6 @@ export enum CommandToCode {
aiSuggestTaxonomy = 'ai-suggest-taxonomy',
aiSuggestDescription = 'ai-suggest-description',
searchByType = 'search-by-type',
processMediaData = 'process-media-data'
processMediaData = 'process-media-data',
isServerStarted = 'is-server-started'
}
+1 -1
View File
@@ -127,7 +127,7 @@ export class PanelProvider implements WebviewViewProvider, Disposable {
}
}, this);
Settings.onConfigChange(() => {
Settings.attachListener('panel-listener', () => {
SettingsListener.getSettings();
});
}
+2
View File
@@ -17,6 +17,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { usePrevious } from './hooks/usePrevious';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
import { InitializeAction } from './components/InitializeAction';
export interface IViewPanelProps { }
@@ -92,6 +93,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
return (
<div className="frontmatter">
<InitializeAction settings={settings} />
{
isDevMode && (
<div className="developer__bar">
+3
View File
@@ -7,6 +7,7 @@ import { SlugAction } from './SlugAction';
import { StartServerButton } from './StartServerButton';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../localization';
import { OpenOnWebsiteAction } from './Actions/OpenOnWebsiteAction';
export interface IActionsProps {
metadata: any;
@@ -28,6 +29,8 @@ const Actions: React.FunctionComponent<IActionsProps> = ({
{settings?.preview?.host && <Preview slug={metadata.slug} />}
<OpenOnWebsiteAction baseUrl={settings.websiteUrl} slug={metadata.slug} />
<StartServerButton settings={settings} />
{settings && settings.scripts && settings.scripts.length > 0 && (
@@ -0,0 +1,33 @@
import { messageHandler } from '@estruyf/vscode/dist/client';
import * as React from 'react';
import { ActionButton } from '../ActionButton';
import * as l10n from "@vscode/l10n"
import { LocalizationKey } from '../../../localization';
import { GeneralCommands } from '../../../constants';
export interface IOpenOnWebsiteActionProps {
baseUrl: string;
slug: string;
}
export const OpenOnWebsiteAction: React.FunctionComponent<IOpenOnWebsiteActionProps> = ({
baseUrl,
slug
}: React.PropsWithChildren<IOpenOnWebsiteActionProps>) => {
const open = () => {
messageHandler.send(GeneralCommands.toVSCode.openOnWebsite, {
websiteUrl: baseUrl,
});
};
if (!baseUrl || !slug) {
return null;
}
return (
<ActionButton
title={l10n.t(LocalizationKey.commonOpenOnWebsite)}
onClick={open} />
);
};
@@ -0,0 +1 @@
export * from './OpenOnWebsiteAction';
+2 -14
View File
@@ -14,6 +14,7 @@ import { GitAction } from './Git/GitAction';
import { useMemo } from 'react';
import * as l10n from "@vscode/l10n"
import { LocalizationKey } from '../../localization';
import { InitializeAction } from './InitializeAction';
export interface IBaseViewProps {
settings: PanelSettings | undefined;
@@ -30,10 +31,6 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({
Messenger.send(CommandToCode.openDashboard);
};
const initProject = () => {
Messenger.send(CommandToCode.initProject);
};
const createContent = () => {
Messenger.send(CommandToCode.createContent);
};
@@ -75,16 +72,7 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({
return (
<div className="frontmatter">
<div className={`ext_actions`}>
{!settings?.isInitialized && (
<div className={`initialize_actions`}>
<button
title={l10n.t(LocalizationKey.panelBaseViewInitialize)}
onClick={initProject}
type={`button`}>
{l10n.t(LocalizationKey.panelBaseViewInitialize)}
</button>
</div>
)}
<InitializeAction settings={settings} />
{settings?.isInitialized && (
<>
@@ -77,15 +77,15 @@ export const ContentTypeValidator: React.FunctionComponent<IContentTypeValidator
<div className="hint__buttons">
<VSCodeButton appearance={`secondary`} onClick={generateContentType}>
<VSCodeButton style={{ "--border-width": 0 }} appearance={`secondary`} onClick={generateContentType}>
{l10n.t(LocalizationKey.panelContentTypeContentTypeValidatorButtonCreate)}
</VSCodeButton>
<VSCodeButton appearance={`secondary`} onClick={addMissingFields}>
<VSCodeButton style={{ "--border-width": 0 }} appearance={`secondary`} onClick={addMissingFields}>
{l10n.t(LocalizationKey.panelContentTypeContentTypeValidatorButtonAdd)}
</VSCodeButton>
<VSCodeButton appearance={`secondary`} onClick={setContentType}>
<VSCodeButton style={{ "--border-width": 0 }} appearance={`secondary`} onClick={setContentType}>
{l10n.t(LocalizationKey.panelContentTypeContentTypeValidatorButtonChange)}
</VSCodeButton>
</div>
@@ -0,0 +1,32 @@
import * as React from 'react';
import { PanelSettings } from '../../models';
import * as l10n from "@vscode/l10n"
import { LocalizationKey } from '../../localization';
import { Messenger } from '@estruyf/vscode/dist/client';
import { CommandToCode } from '../CommandToCode';
export interface IInitializeActionProps {
settings: PanelSettings | undefined;
}
export const InitializeAction: React.FunctionComponent<IInitializeActionProps> = ({ settings }: React.PropsWithChildren<IInitializeActionProps>) => {
const initProject = () => {
Messenger.send(CommandToCode.initProject);
};
if (settings?.isInitialized) {
return null;
}
return (
<div className={`initialize_actions`}>
<button
title={l10n.t(LocalizationKey.panelBaseViewInitialize)}
onClick={initProject}
type={`button`}>
{l10n.t(LocalizationKey.panelBaseViewInitialize)}
</button>
</div>
);
};
@@ -1,10 +1,12 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import * as React from 'react';
import { PanelSettings } from '../../models';
import { CommandToCode } from '../CommandToCode';
import useStartCommand from '../hooks/useStartCommand';
import { LocalizationKey } from '../../localization';
import * as l10n from "@vscode/l10n"
import { EventData } from '@estruyf/vscode/dist/models';
import { Command } from '../Command';
export interface IStartServerButtonProps {
settings: PanelSettings | undefined;
@@ -13,6 +15,7 @@ export interface IStartServerButtonProps {
export const StartServerButton: React.FunctionComponent<IStartServerButtonProps> = ({
settings
}: React.PropsWithChildren<IStartServerButtonProps>) => {
const [isStarted, setIsStarted] = React.useState(false);
const { startCommand } = useStartCommand(settings);
const startLocalServer = (command: string) => {
@@ -23,20 +26,44 @@ export const StartServerButton: React.FunctionComponent<IStartServerButtonProps>
Messenger.send(CommandToCode.stopServer);
};
const messageListener = (message: MessageEvent<EventData<any>>) => {
const { command, payload } = message.data;
if (command === Command.serverStarted) {
setIsStarted(payload);
}
};
React.useEffect(() => {
Messenger.listen(messageListener);
messageHandler.request<boolean>(CommandToCode.isServerStarted).then((isStarted) => {
setIsStarted(isStarted);
});
return () => {
Messenger.unlisten(messageListener);
};
}, []);
return startCommand ? (
<>
<button
title={l10n.t(LocalizationKey.panelStartServerbuttonStart)}
type={`button`}
onClick={() => startLocalServer(startCommand)}>
{l10n.t(LocalizationKey.panelStartServerbuttonStart)}
</button>
<button
title={l10n.t(LocalizationKey.panelStartServerbuttonStop)}
type={`button`}
onClick={() => stopLocalServer()}>
{l10n.t(LocalizationKey.panelStartServerbuttonStop)}
</button>
{
!isStarted ? (
<button
title={l10n.t(LocalizationKey.panelStartServerbuttonStart)}
type={`button`}
onClick={() => startLocalServer(startCommand)}>
{l10n.t(LocalizationKey.panelStartServerbuttonStart)}
</button>
) : (
<button
title={l10n.t(LocalizationKey.panelStartServerbuttonStop)}
type={`button`}
onClick={() => stopLocalServer()}>
{l10n.t(LocalizationKey.panelStartServerbuttonStop)}
</button>
)}
</>
) : null;
};
+3 -2
View File
@@ -68,7 +68,7 @@ export const Engines = {
// Check if there are values to remove
for (const key in docYaml.toJSON()) {
if (typeof obj[key] === undefined) {
if (typeof obj[key] === 'undefined') {
docYaml.delete(key);
}
}
@@ -77,7 +77,8 @@ export const Engines = {
return yaml.stringify(updatedValue, {
lineWidth: 5000,
defaultStringType: 'PLAIN'
defaultStringType: 'PLAIN',
keepUndefined: false
});
}
}
+16 -10
View File
@@ -1,7 +1,7 @@
import { STATIC_FOLDER_PLACEHOLDER } from './../constants/StaticFolderPlaceholder';
import { parseWinPath } from './../helpers/parseWinPath';
import { dirname, extname, join } from 'path';
import { StatusBarAlignment, Uri, window, Webview } from 'vscode';
import { StatusBarAlignment, Uri, window } from 'vscode';
import { Dashboard } from '../commands/Dashboard';
import { Folders } from '../commands/Folders';
import {
@@ -9,7 +9,8 @@ import {
DEFAULT_CONTENT_TYPE_NAME,
ExtensionState,
SETTING_SEO_DESCRIPTION_FIELD,
SETTING_SEO_TITLE_FIELD
SETTING_SEO_TITLE_FIELD,
SETTING_DATE_FORMAT
} from '../constants';
import { Page } from '../dashboardWebView/models';
import {
@@ -23,7 +24,7 @@ import {
Settings
} from '../helpers';
import { existsAsync } from '../utils';
import { Article } from '../commands';
import { Article, Cache } from '../commands';
export class PagesParser {
public static allPages: Page[] = [];
@@ -65,6 +66,7 @@ export class PagesParser {
public static async reset() {
this.parser = undefined;
PagesParser.allPages = [];
await Cache.clear(false);
}
/**
@@ -167,8 +169,16 @@ export class PagesParser {
(Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string) || DefaultFields.Description;
const dateField = ArticleHelper.getPublishDateField(article) || DefaultFields.PublishingDate;
const contentType = ArticleHelper.getContentType(article.data);
let dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
const ctDateField = ContentType.findFieldByName(contentType.fields, dateField);
if (ctDateField && ctDateField.dateFormat) {
dateFormat = ctDateField.dateFormat;
}
const dateFieldValue = article?.data[dateField]
? DateHelper.tryParse(article?.data[dateField])
? DateHelper.tryParse(article?.data[dateField], dateFormat)
: undefined;
const modifiedField = ArticleHelper.getModifiedDateField(article) || null;
@@ -206,8 +216,9 @@ export class PagesParser {
fmPreviewImage: '',
fmTags: [],
fmCategories: [],
fmContentType: DEFAULT_CONTENT_TYPE_NAME,
fmContentType: contentType.name || DEFAULT_CONTENT_TYPE_NAME,
fmBody: article?.content || '',
fmDateFormat: dateFormat,
// Make sure these are always set
title: escapedTitle,
description: escapedDescription,
@@ -216,11 +227,6 @@ export class PagesParser {
draft: article?.data.draft
};
const contentType = ArticleHelper.getContentType(article.data);
if (contentType) {
page.fmContentType = contentType.name;
}
let previewFieldParents = ContentType.findPreviewField(contentType.fields);
if (previewFieldParents.length === 0) {
const previewField = contentType.fields.find(
+3 -2
View File
@@ -1,12 +1,13 @@
import { Uri, l10n } from 'vscode';
import { Extension, Logger } from '../helpers';
import { Extension, Logger, parseWinPath } from '../helpers';
import { readFileAsync } from './readFileAsync';
import { join } from 'path';
export const getLocalizationFile = async () => {
try {
const localeFilePath =
l10n.uri?.fsPath ||
Uri.parse(`${Extension.getInstance().extensionPath}/l10n/bundle.l10n.json`).fsPath;
Uri.file(join(parseWinPath(Extension.getInstance().extensionPath.fsPath), `/l10n/bundle.l10n.json`)).fsPath;
const fileContents = await readFileAsync(localeFilePath, 'utf-8');
return fileContents;