Compare commits

..

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] 3489876ed8 Fix: Respect dateFormat of all datetime fields (incl. publishDate) during auto-save
Co-authored-by: estruyf <2900833+estruyf@users.noreply.github.com>
2026-03-14 10:49:14 +00:00
copilot-swe-agent[bot] cde03e8fcf Fix: Prevent unwanted automatic updates to publishDate field on save
Co-authored-by: estruyf <2900833+estruyf@users.noreply.github.com>
2026-03-14 10:39:51 +00:00
copilot-swe-agent[bot] 90f181a05c Initial plan 2026-03-14 10:28:48 +00:00
33 changed files with 131 additions and 547 deletions
+11 -22
View File
@@ -6,14 +6,13 @@ on:
workflow_dispatch:
env:
PACKAGE_NAME: "fm-localized"
MS_URL: "https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-\
front-matter-beta"
VSX_URL: "https://open-vsx.org/extension/eliostruyf/vscode-front-matter-beta"
PACKAGE_NAME: 'fm-localized'
MS_URL: 'https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter-beta'
VSX_URL: 'https://open-vsx.org/extension/eliostruyf/vscode-front-matter-beta'
jobs:
localization:
name: "Localization"
name: 'Localization'
runs-on: ubuntu-latest
steps:
@@ -28,11 +27,11 @@ jobs:
PACKAGE_NAME: ${{ env.PACKAGE_NAME }}
release-ms:
name: "Release to VSCode Marketplace"
name: 'Release to VSCode Marketplace'
runs-on: ubuntu-latest
needs: localization
environment:
name: "MS - BETA"
name: 'MS - BETA'
url: ${{ env.MS_URL }}
steps:
@@ -44,7 +43,7 @@ jobs:
with:
node-version: 20
registry-url: https://registry.npmjs.org/
cache: "npm"
cache: 'npm'
- name: Install the dependencies
run: npm ci
@@ -53,24 +52,14 @@ jobs:
run: node scripts/beta-release.js $GITHUB_RUN_ID
- name: Publish
run: npx @vscode/vsce publish -p ${{ secrets.VSCE_PAT }} --baseImagesUrl
https://raw.githubusercontent.com/estruyf/vscode-front-matter/dev
- name: Package VSIX
run: npx @vscode/vsce package
- name: Upload VSIX artifact
uses: actions/upload-artifact@v6
with:
name: vscode-demo-time-alpha.vsix
path: "*.vsix"
run: npx @vscode/vsce publish -p ${{ secrets.VSCE_PAT }} --baseImagesUrl https://raw.githubusercontent.com/estruyf/vscode-front-matter/dev
release-vsx:
name: "Release to Open VSX"
name: 'Release to Open VSX'
runs-on: ubuntu-latest
needs: localization
environment:
name: "Open VSX - BETA"
name: 'Open VSX - BETA'
url: ${{ env.VSX_URL }}
steps:
@@ -82,7 +71,7 @@ jobs:
with:
node-version: 20
registry-url: https://registry.npmjs.org/
cache: "npm"
cache: 'npm'
- name: Install the dependencies
run: npm ci
+2 -5
View File
@@ -6,7 +6,7 @@ src/**
vsc-extension-quickstart.md
**/tsconfig.json
**/tsconfig.e2e.json
**/*.map
**/*.ts
webpack.config.js
node_modules
@@ -29,7 +29,4 @@ webpack
README.beta.md
e2e
storage
pnpm-lock.yaml
.env
tailwind.panel.js
LOCALIZATION.md
pnpm-lock.yaml
+5 -15
View File
@@ -1,40 +1,30 @@
# Change Log
## [10.10.1] - 2026-04-23
### 🐞 Fixes
- [#1023](https://github.com/estruyf/vscode-front-matter/issues/1023): Fix validation errors for image, file, and keywords fields
- [#1024](https://github.com/estruyf/vscode-front-matter/issues/1024): Re-add the `frontMatter.copilot.enabled` setting to allow users to disable the GitHub Copilot integration
- Fix Git detection when Git is configured via VS Code `git.path` and not installed globally on the system
## [10.10.0] - 2026-04-03 - [Release notes](https://beta.frontmatter.codes/updates/v10.10.0)
## [10.10.0] - 2025-xx-xx
- Removed the chatbot command and all related code and references
- [#983](https://github.com/estruyf/vscode-front-matter/issues/983): Removal of the `frontMatter.sponsors.ai.enabled` features
### 🎨 Enhancements
- [#545](https://github.com/estruyf/vscode-front-matter/issues/545): Add smart rename action to sync filename with front matter data
- [#937](https://github.com/estruyf/vscode-front-matter/issues/937): Dashboard "Structure" view for documentation sites *WIP*
- [#965](https://github.com/estruyf/vscode-front-matter/issues/965): Added SEO support for the keyword in the first paragraph
- [#973](https://github.com/estruyf/vscode-front-matter/issues/973): Support for number fields in the snippets
- [#990](https://github.com/estruyf/vscode-front-matter/issues/990): Schema and validation for front matter in markdown files. It can be turned off by the `frontMatter.validation.enabled` setting.
- [#1005](https://github.com/estruyf/vscode-front-matter/issues/1005): Support the integrated VSCode browser for the preview command
- [#1017](https://github.com/estruyf/vscode-front-matter/issues/1017): Allow adding new values for custom taxonomy fields
### 🐞 Fixes
- [#950](https://github.com/estruyf/vscode-front-matter/issues/950): Fix for template is not applied to new content type when created
- [#958](https://github.com/estruyf/vscode-front-matter/issues/958): Fix variable frontmatter leads to error
- [#964](https://github.com/estruyf/vscode-front-matter/issues/964): Fix settings page for dark themes
- [#969](https://github.com/estruyf/vscode-front-matter/issues/969): Fix typo on welcome screen
- [#972](https://github.com/estruyf/vscode-front-matter/issues/972): Fix content view sorting for Modified Date not working as expected
- [#979](https://github.com/estruyf/vscode-front-matter/issues/979): Fix unwanted automatic updates in the publishDate field of TOML front matter
- [#984](https://github.com/estruyf/vscode-front-matter/issues/984): Fix in `frontMatter.global.timezone` is invalid
- [#1004](https://github.com/estruyf/vscode-front-matter/issues/1004): Fix for `mediaDB.json` containing full paths on Windows instead of relative paths
- [#1006](https://github.com/estruyf/vscode-front-matter/issues/1006): Fix output channel colorizer schema to only apply to the Front Matter output channel
### 🐞 Fixes
- [#969](https://github.com/estruyf/vscode-front-matter/issues/969): Fix typo on welcome screen
## [10.9.0] - 2025-07-01 - [Release notes](https://beta.frontmatter.codes/updates/v10.9.0)
### 🎨 Enhancements
+49 -108
View File
@@ -4,29 +4,7 @@
</a>
</h1>
<h2 align="center">Front Matter - A Headless CMS for Visual Studio Code</h2>
> **📢 2026 Open Source Priorities Update**
>
> I love working with and creating open source products, but after careful
> evaluation and working with a coach, I've decided to focus my efforts on
> creating a better revenue stream. As open-source isn't providing me a
> sustainable income, I need to focus my time and effort more strategically on
> how to make my work sustainable.
>
> **Front Matter CMS will continue to be maintained** as I use it daily.
> However, major changes will only happen if there's a personal reason, a
> company commitment, or significant community support. Feature requests may
> take longer to be addressed.
>
> I'm shifting focus to open source projects that I can learn from or that have
> different outcomes, like **Demo Time**, which I use when presenting at
> conferences. If you or your company would like to sponsor my work on Front
> Matter CMS or other projects, I'd love to discuss how we can collaborate to
> make it even better!
>
> This is not about Front Matter CMS going away, but rather about managing
> expectations around feature development timelines.
<h2 align="center">Front Matter a CMS running straight in Visual Studio Code</h2>
<p align="center">
<a href="https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter" title="Check it out on the Visual Studio Marketplace">
@@ -50,17 +28,11 @@
## ❓ What is Front Matter?
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. Jump right into editing
and creating content with Front Matter and be able to preview it straight in VS
Code.
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. Jump right into editing and creating content with Front Matter and be able to preview it straight in VS Code.
The extension supports various static-site generators and frameworks like Hugo,
Jekyll, Hexo, NextJs, Gatsby, and more.
The extension supports various static-site generators and frameworks like Hugo, Jekyll, Hexo, NextJs, Gatsby, and more.
A couple of our extension highlights that hopefully get you interested in giving
Front Matter a try:
A couple of our extension highlights that hopefully get you interested in giving Front Matter a try:
- Content, data, and media management
- Search, filter, sort, etc. all your content
@@ -69,40 +41,30 @@ Front Matter a try:
- Preview your site/content straight in Visual Studio Code
- SEO checks for title, description, and keywords
- Extensibility
- As we know, we cannot support all use cases. We provide a way to extend the
functionality of the extension to your needs
- As we know, we cannot support all use cases. We provide a way to extend the functionality of the extension to your needs
- and many more features ...
> Missing something? Let us know by opening an issue on the
> [GitHub repository](https://github.com/estruyf/vscode-front-matter/issues/new/choose)
> Missing something? Let us know by opening an issue on the [GitHub repository](https://github.com/estruyf/vscode-front-matter/issues/new/choose)
<p align="center">
<img src="https://frontmatter.codes/assets/marketplace/v6.0.0/content-preview.png" alt="Site preview" style="display: inline-block" />
</p>
> If you see something missing in your article creation flow, please feel free
> to reach out.
> If you see something missing in your article creation flow, please feel free to reach out.
**Version 10**
In version 10, we introduced the new i18n/multilingual support for your content.
You can now manage your content in multiple languages, more information can be
found in the
[multilingual](https://frontmatter.codes/docs/content-creation/multilingual)
section of our documentation.
In version 10, we introduced the new i18n/multilingual support for your content. You can now manage your content in multiple languages, more information can be found in the [multilingual](https://frontmatter.codes/docs/content-creation/multilingual) section of our documentation.
![Multilingual support](https://beta.frontmatter.codes/releases/v10.0.0/multilingual-content.png)
**Version 9**
The extension is now available in multiple languages: English, German, and
Japanese. Want to add your language? Check out the
[localization the extension](https://frontmatter.codes/docs/contributing#translating-the-extension).
The extension is now available in multiple languages: English, German, and Japanese. Want to add your language? Check out the [localization the extension](https://frontmatter.codes/docs/contributing#translating-the-extension).
**Version 8**
The taxonomy dashboard got introduced on which you can manage your tags,
categories, and custom taxonomy.
The taxonomy dashboard got introduced on which you can manage your tags, categories, and custom taxonomy.
![Taxonomy dashboard](https://frontmatter.codes/assets/marketplace/v8.1.0/taxonomy-dashboard.png)
@@ -114,24 +76,17 @@ Snippets support for Front Matter has been added!
**Version 6**
In this version, we introduced the new data files/folders dashboard. You can
find more information about the release in our
[v6.0.0 release notes](https://frontmatter.codes/updates/v6.0.0).
In this version, we introduced the new data files/folders dashboard. You can find more information about the release in our [v6.0.0 release notes](https://frontmatter.codes/updates/v6.0.0).
<p align="center">
<img src="https://frontmatter.codes/assets/marketplace/v6.0.0/data-dashboard.png" alt="Data dashboard" style="display: inline-block" />
</p>
> Data files/folders are pieces of content that do not belong to any markdown
> content, but live on their own. Most of the time, these data files are used to
> store additional information about your project/blog/website that will be used
> to render the content.
> Data files/folders are pieces of content that do not belong to any markdown content, but live on their own. Most of the time, these data files are used to store additional information about your project/blog/website that will be used to render the content.
**Version 5**
The new media dashboard redesign got introduced + support for setting metadata
on media files
[v5.0.0 release notes](https://frontmatter.codes/updates/v5.0.0).
The new media dashboard redesign got introduced + support for setting metadata on media files [v5.0.0 release notes](https://frontmatter.codes/updates/v5.0.0).
<p align="center">
<img src="https://frontmatter.codes/assets/marketplace/v5.9.0/media-dashboard.png" alt="Data dashboard" style="display: inline-block" />
@@ -139,21 +94,15 @@ on media files
**Version 4**
Support for Team level settings, content-types, and image support. Get to know
more at: [v4.0.0 release notes](https://frontmatter.codes/updates/v4_0_0).
Support for Team level settings, content-types, and image support. Get to know more at: [v4.0.0 release notes](https://frontmatter.codes/updates/v4_0_0).
**Version 3**
In version v3 we introduced the welcome and dashboard webview. The welcome view
allows to get you started using the extension, and the dashboard allows you to
manage all your markdown pages in one place. This makes it easy to search,
filter, sort, and more.
In version v3 we introduced the welcome and dashboard webview. The welcome view allows to get you started using the extension, and the dashboard allows you to manage all your markdown pages in one place. This makes it easy to search, filter, sort, and more.
**Version 2**
In version v2 we released the re-designed sidebar panel with improved SEO
support. This extension makes it the only extension to manage your Markdown
pages for your static sites in Visual Studio Code.
In version v2 we released the re-designed sidebar panel with improved SEO support. This extension makes it the only extension to manage your Markdown pages for your static sites in Visual Studio Code.
<p align="center" style="margin-top: 2rem;">
<a href="https://www.producthunt.com/posts/front-matter?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-front-matter" target="_blank">
@@ -165,47 +114,33 @@ pages for your static sites in Visual Studio Code.
You can get the extension via:
- The VS Code marketplace:
[VS Code Marketplace - Front Matter](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter).
- The extension CLI: `ext install eliostruyf.vscode-front-matter`
- Or by clicking on the following link: <a href="" title="open extension in VS
Code" data-vscode="vscode:extension/eliostruyf.vscode-front-matter">open
extension in VS Code</a>
- The VS Code marketplace: [VS Code Marketplace - Front Matter](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter).
- The extension CLI: `code --install-extension eliostruyf.vscode-front-matter`
- Or by clicking on the following link: <a href="" title="open extension in VS Code" data-vscode="vscode:extension/eliostruyf.vscode-front-matter">open extension in VS Code</a>
> **Info**: The docs can be found on
> [frontmatter.codes](https://frontmatter.codes).
> **Info**: The docs can be found on [frontmatter.codes](https://frontmatter.codes).
### 🧪 Beta version
If you have the courage to test out the beta features, we made available a beta
version as well. You can install this via:
If you have the courage to test out the beta features, we made available a beta version as well. You can install this via:
- Uninstall the main Front Matter version
- Install the beta version
- VS Code marketplace:
[VS Code Marketplace - Front Matter BETA](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter-beta).
- The extension CLI: `ext install eliostruyf.vscode-front-matter-beta`
- Or by clicking on the following link: <a href="" title="open extension in VS
Code"
data-vscode="vscode:extension/eliostruyf.vscode-front-matter-beta">open
extension in VS Code</a>
- VS Code marketplace: [VS Code Marketplace - Front Matter BETA](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter-beta).
- The extension CLI: `code --install-extension eliostruyf.vscode-front-matter-beta`
- Or by clicking on the following link: <a href="" title="open extension in VS Code" data-vscode="vscode:extension/eliostruyf.vscode-front-matter-beta">open extension in VS Code</a>
> **Info**: The BETA docs can be found on
> [beta.frontmatter.codes](https://beta.frontmatter.codes).
> **Info**: The BETA docs can be found on [beta.frontmatter.codes](https://beta.frontmatter.codes).
## 📖 Documentation
All documentation can be found on
[frontmatter.codes](https://frontmatter.codes).
All documentation can be found on [frontmatter.codes](https://frontmatter.codes).
Documentation repository:
[GitHub - Front Matter DOCs](https://github.com/FrontMatter/web-documentation-nextjs)
Documentation repository: [GitHub - Front Matter DOCs](https://github.com/FrontMatter/web-documentation-nextjs)
## 💪 Contributing
Pull requests are welcome. Please open an issue first to discuss what you would
like to change, or which problem you would like to fix. This makes it easier for
us to follow-up and plan for future releases.
Pull requests are welcome. Please open an issue first to discuss what you would like to change, or which problem you would like to fix. This makes it easier for us to follow-up and plan for future releases.
You can always help us improve the extension in varous ways like:
@@ -218,8 +153,7 @@ You can always help us improve the extension in varous ways like:
- Tutorials
- etc.
Eager to start contributing? Great 🤩, you can contribute to the following
projects:
Eager to start contributing? Great 🤩, you can contribute to the following projects:
- [Extension](https://github.com/estruyf/vscode-front-matter)
- [Documentation](https://github.com/FrontMatter/web-documentation-nextjs)
@@ -227,16 +161,13 @@ projects:
## 👀 Show the work you are using Front Matter
Are you using Front Matter and are you interested in showing for which websites
you use it? You can show your work by opening a
[showcase issue](https://github.com/estruyf/vscode-front-matter/issues/new?assignees=&labels=&template=showcase.md&title=Showcase%3A+).
Are you using Front Matter and are you interested in showing for which websites you use it? You can show your work by opening a [showcase issue](https://github.com/estruyf/vscode-front-matter/issues/new?assignees=&labels=&template=showcase.md&title=Showcase%3A+).
You can open showcase issues for the following things:
- Show the website for which you use Front Matter;
- Share an article/video/webcast/... that explains how you use Front Matter;
- Got something else to share? Open an issue and we can see where it fits on our
website.
- Got something else to share? Open an issue and we can see where it fits on our website.
## 👉 Contributors 🤘
@@ -254,23 +185,33 @@ You can open showcase issues for the following things:
<br />
<p align="center" title="Support by run.events">
<a href="https://run.events/?utm_source=frontmatter&utm_campaign=oss">
<img src="https://frontmatter.codes/assets/sponsors/runevents-purple.webp" alt="run.events - Event Management Platform" height="50px" />
</a>
</p>
<br />
<p align="center" title="Powered by Netlify">
<a href="https://www.netlify.com?utm_source=vscode-frontmatter&utm_campaign=oss">
<img src="https://frontmatter.codes/assets/sponsors/netlify-dark.png" alt="Deploys by Netlify" height="51px" />
</a>
</p>
<br />
<p align="center">
<a href="http://bejs.io/" title="Supported by the BEJS Community">
<img src="https://frontmatter.codes/assets/sponsors/bejs-community.png" alt="Supported by the BEJS Community" height="50px"/>
</a>
</p>
## 📊 Telemetry
The Front Matter CMS extension only uses telemetry on application crashes. The
extension respects the `telemetry.enableTelemetry` setting which you can learn
more about in the
[Visual Studio Code FAQ](https://aka.ms/vscode-remote/telemetry).
The Front Matter CMS extension only uses telemetry on application crashes. The extension respects the `telemetry.enableTelemetry` setting which you can learn more about in the [Visual Studio Code FAQ](https://aka.ms/vscode-remote/telemetry).
For crash reports in the webviews, we make use of Sentry to help us understand
what went wrong. This data is only used to fix issues and improve the extension.
You can find more information about the Sentry implementation in the following
files:
For crash reports in the webviews, we make use of Sentry to help us understand what went wrong. This data is only used to fix issues and improve the extension. You can find more information about the Sentry implementation in the following files:
- [Sentry config](https://github.com/estruyf/vscode-front-matter/blob/63e296d62f11be73ac86d9e823084247952a7ddc/src/utils/sentryInit.ts)
-9
View File
@@ -524,8 +524,6 @@
"panel.slugAction.title": "Optimize slug",
"panel.smartRenameAction.title": "Smart rename",
"panel.spinner.loading": "Loading...",
"panel.startServerbutton.start": "Start server",
@@ -552,13 +550,6 @@
"commands.article.rename.fileName.title": "Rename: {0}",
"commands.article.rename.fileName.prompt": "File name",
"commands.article.smartRename.alreadyInSync": "The filename is already in sync with the front matter",
"commands.article.smartRename.success": "File renamed from \"{0}\" to \"{1}\"",
"commands.article.smartRename.unableToGenerate": "Unable to generate a new filename from the front matter",
"commands.article.smartRename.fileExists.error": "A file with the name \"{0}\" already exists",
"dashboard.contents.contentActions.menuItem.smartRename": "Smart rename",
"commands.cache.cleared": "Cache cleared",
"commands.chatbot.title": "Ask me anything",
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "vscode-front-matter-beta",
"version": "10.10.1",
"version": "10.9.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "vscode-front-matter-beta",
"version": "10.10.1",
"version": "10.9.0",
"license": "MIT",
"devDependencies": {
"@actions/core": "^1.10.0",
+2 -7
View File
@@ -3,7 +3,7 @@
"displayName": "Front Matter CMS",
"description": "Front Matter is a CMS that runs within Visual Studio Code. It gives you the power and control of a full-blown CMS while also providing you the flexibility and speed of the static site generator of your choice like: Hugo, Jekyll, Docusaurus, NextJs, Gatsby, and many more...",
"icon": "assets/frontmatter-teal-128x128.png",
"version": "10.10.1",
"version": "10.9.0",
"preview": false,
"publisher": "eliostruyf",
"galleryBanner": {
@@ -2128,11 +2128,6 @@
"type": "string",
"default": "gpt-4o-mini",
"markdownDescription": "%setting.frontMatter.copilot.family.markdownDescription%"
},
"frontMatter.copilot.enabled": {
"type": "boolean",
"default": true,
"markdownDescription": "%setting.frontMatter.copilot.enabled.markdownDescription%"
}
}
},
@@ -2861,7 +2856,7 @@
]
},
"scripts": {
"dev": "npm run clean && npm run localization:generate && npm-run-all --parallel watch:*",
"dev:ext": "npm run clean && npm run localization:generate && npm-run-all --parallel watch:*",
"vscode:prepublish": "npm run clean && npm run localization:generate && npm-run-all --parallel prod:*",
"build:ext": "npm run clean && npm-run-all --parallel dev:build:*",
"watch:ext": "webpack --mode development --watch --config ./webpack/extension.config.js",
+1 -2
View File
@@ -292,6 +292,5 @@
"setting.frontMatter.git.disableOnBranches.markdownDescription": "Specify the branches on which you want to disable the Git actions. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.git.disableonbranches) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.git.disableonbranches%22%5D)",
"setting.frontMatter.git.requiresCommitMessage.markdownDescription": "Specify if you want to require a commit message when publishing your changes for a specified branch. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.git.requirescommitmessage) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.git.requirescommitmessage%22%5D)",
"setting.frontMatter.copilot.family.markdownDescription": "Specify the LLM family of the Copilot you want to use. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.copilot.family) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.copilot.family%22%5D)",
"setting.frontMatter.copilot.enabled.markdownDescription": "Specify if you want to enable GitHub Copilot AI suggestions (requires GitHub Copilot extension). [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.copilot.enabled) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.copilot.enabled%22%5D)"
"setting.frontMatter.copilot.family.markdownDescription": "Specify the LLM family of the Copilot you want to use. [Docs](https://frontmatter.codes/docs/settings/overview#frontmatter.copilot.family) - [View in VS Code](command:simpleBrowser.show?%5B%22https://frontmatter.codes/docs/settings/overview%23frontmatter.copilot.family%22%5D)"
}
+14 -31
View File
@@ -37,7 +37,7 @@ import { COMMAND_NAME, DefaultFields } from '../constants';
import { DashboardData, SnippetInfo, SnippetRange } from '../models/DashboardData';
import { DateHelper } from '../helpers/DateHelper';
import { parseWinPath } from '../helpers/parseWinPath';
import { FrontMatterParser, ParsedFrontMatter } from '../parsers';
import { ParsedFrontMatter } from '../parsers';
import { MediaListener } from '../listeners/panel';
import { NavigationType } from '../dashboardWebView/models';
import { SNIPPET } from '../constants/Snippet';
@@ -149,47 +149,31 @@ export class Article {
return;
}
const documentText = document.getText();
const isToml = FrontMatterParser.getLanguageFromContent(documentText) === 'toml';
const cloneArticle = Object.assign({}, article);
let contentType;
const dateField = isToml
? ((contentType = await ArticleHelper.getContentType(article)),
contentType.fields.find((f) => f.isModifiedDate))
: await ArticleHelper.getModifiedDateField(article);
if (isToml) {
Logger.verbose(
`Article:setLastModifiedDateInner:TOML - updating all datetime fields to preserve format`
);
}
// Fetch content type once and derive modified date field from it
const contentType = await ArticleHelper.getContentType(article);
const dateField = contentType.fields.find((f) => f.isModifiedDate);
Logger.verbose(`Article:setLastModifiedDateInner:DateField - ${JSON.stringify(dateField)}`);
try {
const fieldName = dateField?.name || DefaultFields.LastModified;
const fieldValue = Article.formatDate(new Date(), dateField?.dateFormat);
cloneArticle.data[fieldName] = fieldValue;
Logger.verbose(
`Article:setLastModifiedDateInner:DateField name - ${fieldName} - value - ${fieldValue}`
);
if (isToml && contentType) {
// TOML parser returns datetime literals as Date objects.
// Reformat them using each field dateFormat to preserve expected output on save.
for (const field of contentType.fields) {
if (field.type === 'datetime' && field.name !== fieldName) {
const value = cloneArticle.data[field.name];
if (value instanceof Date) {
cloneArticle.data[field.name] = Article.formatDate(value, field.dateFormat);
Logger.verbose(
`Article:setLastModifiedDateInner:Reformat field - ${field.name} - value - ${
cloneArticle.data[field.name]
}`
);
}
// Reformat other datetime fields that contain Date objects (e.g. from TOML parsing)
// using their configured dateFormat, so the format is preserved on save
for (const field of contentType.fields) {
if (field.type === 'datetime' && field.name !== fieldName) {
const value = cloneArticle.data[field.name];
if (value instanceof Date) {
cloneArticle.data[field.name] = Article.formatDate(value, field.dateFormat);
Logger.verbose(
`Article:setLastModifiedDateInner:Reformat field - ${field.name} - value - ${cloneArticle.data[field.name]}`
);
}
}
}
@@ -200,7 +184,6 @@ export class Article {
Notifications.error(
l10n.t(LocalizationKey.commandsArticleSetDateError, `${CONFIG_KEY}${SETTING_DATE_FORMAT}`)
);
return;
}
}
-1
View File
@@ -117,7 +117,6 @@ export const SETTING_SNIPPETS_WRAPPER = 'snippets.wrapper.enabled';
export const SETTING_WEBSITE_URL = 'website.host';
export const SETTING_COPILOT_FAMILY = 'copilot.family';
export const SETTING_COPILOT_ENABLED = 'copilot.enabled';
export const SETTING_LOGGING = 'logging';
-1
View File
@@ -32,7 +32,6 @@ export enum DashboardMessage {
pinItem = 'pinItem',
unpinItem = 'unpinItem',
rename = 'rename',
smartRename = 'smartRename',
moveFile = 'moveFile',
// Media Dashboard
@@ -5,8 +5,7 @@ import {
TrashIcon,
LanguageIcon,
EllipsisHorizontalIcon,
ArrowRightCircleIcon,
ArrowPathIcon
ArrowRightCircleIcon
} from '@heroicons/react/24/outline';
import * as React from 'react';
import { CustomScript, I18nConfig } from '../../../models';
@@ -74,12 +73,7 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
const onRename = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
messageHandler.send(DashboardMessage.rename, path);
}, [path]);
const onSmartRename = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
messageHandler.send(DashboardMessage.smartRename, path);
}, [path]);
}, [path])
const onOpenWebsite = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
@@ -150,11 +144,6 @@ export const ContentActions: React.FunctionComponent<IContentActionsProps> = ({
<span>{l10n.t(LocalizationKey.commonRename)}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={onSmartRename}>
<ArrowPathIcon className={`mr-2 h-4 w-4`} aria-hidden={true} />
<span>{l10n.t(LocalizationKey.dashboardContentsContentActionsMenuItemSmartRename)}</span>
</DropdownMenuItem>
{
settings?.websiteUrl && (
<DropdownMenuItem onClick={onOpenWebsite}>
@@ -67,7 +67,7 @@ export const CommonSettings: React.FunctionComponent<ICommonSettingsProps> = (pr
}, [settings?.lastUpdated]);
return (
<div className='w-full divide-y divide-[var(--frontmatter-border)] text-[var(--frontmatter-text)]'>
<div className='w-full divide-y divide-[var(--frontmatter-border)]'>
<div className='py-4'>
<h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsOpenOnStartup)}</h2>
@@ -71,7 +71,7 @@ export const IntegrationsView: React.FunctionComponent<IIntegrationsViewProps> =
}, []);
return (
<div className='w-full divide-y divide-[var(--frontmatter-border)] text-[var(--frontmatter-text)]'>
<div className='w-full divide-y divide-[var(--frontmatter-border)]'>
<div className='py-4 space-y-4'>
<h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsIntegrationsViewDeeplTitle)}</h2>
@@ -52,7 +52,7 @@ export const SettingsView: React.FunctionComponent<ISettingsViewProps> = (_: Rea
{
id: "view-2",
content: (
<div className='py-4 text-[var(--frontmatter-text)]'>
<div className='py-4'>
<h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsContentFolders)}</h2>
<ContentFolders
@@ -67,7 +67,7 @@ export const SettingsView: React.FunctionComponent<ISettingsViewProps> = (_: Rea
temp.push({
id: "view-3",
content: (
<div className='py-4 text-[var(--frontmatter-text)]'>
<div className='py-4'>
<h2 className='text-xl mb-2'>{l10n.t(LocalizationKey.settingsContentTypes)}</h2>
<AstroContentTypes
@@ -19,7 +19,7 @@ export const SelectItem: React.FunctionComponent<ISelectItemProps> = ({
}: React.PropsWithChildren<ISelectItemProps>) => {
return (
<div
className={`text-sm flex items-center ${isSelected ? 'text-[var(--vscode-textLink-foreground)]' : 'text-[var(--frontmatter-text)]'}`}
className={`text-sm flex items-center ${isSelected ? 'text-[var(--vscode-textLink-foreground)]' : ''}`}
>
<button
onClick={onClick}
+3 -141
View File
@@ -236,146 +236,6 @@ export class ArticleHelper {
});
}
/**
* Smart rename a file based on its front matter title and publish date.
* Regenerates the expected filename using the same logic as content creation.
* @param filePath - The path of the file to be renamed.
*/
public static async smartRename(filePath?: string) {
if (!filePath) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
filePath = editor.document.uri.fsPath;
}
filePath = parseWinPath(filePath);
const fileUri = Uri.file(filePath);
const article = await ArticleHelper.getFrontMatterByPath(filePath);
if (!article || !article.data) {
Notifications.error(
l10n.t(LocalizationKey.commandsArticleRenameFileNotExistsError)
);
return;
}
const titleField = getTitleField();
const title: string = article.data[titleField];
if (!title) {
Notifications.warning(
l10n.t(LocalizationKey.commandsArticleSmartRenameUnableToGenerate)
);
return;
}
const contentType = await ArticleHelper.getContentType(article);
const articleDate = await ArticleHelper.getDate(article);
let filePrefix = Settings.get<string>(SETTING_TEMPLATES_PREFIX);
filePrefix = await ArticleHelper.getFilePrefix(
filePrefix,
filePath,
contentType,
title,
articleDate
);
const sanitizedName = ArticleHelper.sanitize(title);
const parsed = parseFile(filePath);
const folderPath = dirname(fileUri.fsPath);
let newFileName: string;
if (contentType?.pageBundle) {
// For page bundles, the folder name should be updated
if (filePrefix && typeof filePrefix === 'string') {
if (filePrefix.endsWith('/')) {
newFileName = `${filePrefix}${sanitizedName}`;
} else {
newFileName = `${filePrefix}-${sanitizedName}`;
}
} else {
newFileName = sanitizedName;
}
const parentFolder = dirname(folderPath);
const currentFolderName = parseFile(folderPath).base;
if (currentFolderName === newFileName) {
Notifications.info(
l10n.t(LocalizationKey.commandsArticleSmartRenameAlreadyInSync)
);
return;
}
const newFolderPath = join(parentFolder, newFileName);
if (await existsAsync(newFolderPath)) {
Notifications.error(
l10n.t(LocalizationKey.commandsArticleSmartRenameFileExistsError, newFileName)
);
return;
}
await workspace.fs.rename(Uri.file(folderPath), Uri.file(newFolderPath), {
overwrite: false
});
Notifications.info(
l10n.t(
LocalizationKey.commandsArticleSmartRenameSuccess,
currentFolderName,
newFileName
)
);
} else {
// For regular files, rename the file
let newFileBase = `${sanitizedName}${parsed.ext}`;
if (filePrefix && typeof filePrefix === 'string') {
if (filePrefix.endsWith('/')) {
newFileBase = `${filePrefix}${newFileBase}`;
} else {
newFileBase = `${filePrefix}-${newFileBase}`;
}
}
if (parsed.base === newFileBase) {
Notifications.info(
l10n.t(LocalizationKey.commandsArticleSmartRenameAlreadyInSync)
);
return;
}
const newFileUri = Uri.joinPath(Uri.file(folderPath), newFileBase);
if (await existsAsync(newFileUri.fsPath)) {
Notifications.error(
l10n.t(LocalizationKey.commandsArticleSmartRenameFileExistsError, newFileBase)
);
return;
}
// Close the document if it's open in an editor before renaming
const openEditors = vscode.window.visibleTextEditors.filter(
(e) => parseWinPath(e.document.uri.fsPath) === filePath
);
for (const editor of openEditors) {
await editor.document.save();
}
await workspace.fs.rename(fileUri, newFileUri, {
overwrite: false
});
Notifications.info(
l10n.t(
LocalizationKey.commandsArticleSmartRenameSuccess,
parsed.base,
newFileBase
)
);
}
}
/**
* Generate the update to be applied to the article.
* @param article
@@ -642,7 +502,9 @@ export class ArticleHelper {
*/
public static async updateDates(article: ParsedFrontMatter) {
const contentType = await ArticleHelper.getContentType(article);
const dateFields = contentType.fields.filter((field) => field.type === 'datetime');
const dateFields = contentType.fields.filter(
(field) => field.type === 'datetime' && !field.isPublishDate
);
for (const dateField of dateFields) {
if (article?.data[dateField.name]) {
+11 -23
View File
@@ -26,11 +26,11 @@ export interface JSONSchema {
/**
* Generates JSON Schema from Front Matter Content Type definitions
*
*
* This utility converts Front Matter content type definitions into JSON Schema format
* which can then be used for validation. It handles all field types supported by
* Front Matter CMS including nested fields, blocks, and field groups.
*
*
* Field Type Mappings:
* - string, slug, image, file, customField → string
* - number → number (with optional min/max)
@@ -42,7 +42,7 @@ export interface JSONSchema {
* - block → array of objects with oneOf for field groups
* - json → any valid JSON type
* - dataFile, contentRelationship → string or array
*
*
* Features:
* - Required field validation
* - Type validation
@@ -50,7 +50,7 @@ export interface JSONSchema {
* - Number range validation (min/max)
* - Nested object support
* - Block field support with multiple field group options
*
*
* Usage:
* ```typescript
* const schema = ContentTypeSchemaGenerator.generateSchema(contentType);
@@ -123,18 +123,10 @@ export class ContentTypeSchemaGenerator {
switch (field.type) {
case 'string':
case 'slug':
case 'customField':
schema.type = 'string';
break;
case 'image':
case 'file':
if (field.multiple) {
schema.type = 'array';
schema.items = { type: 'string' };
} else {
schema.type = 'string';
}
case 'customField':
schema.type = 'string';
break;
case 'number':
@@ -181,7 +173,7 @@ export class ContentTypeSchemaGenerator {
schema.items = {
type: 'string'
};
// Get available tags and add as enum for validation
const availableTags = await TaxonomyHelper.get(TaxonomyType.Tag);
if (availableTags && availableTags.length > 0) {
@@ -195,7 +187,7 @@ export class ContentTypeSchemaGenerator {
schema.items = {
type: 'string'
};
// Get available categories and add as enum for validation
const availableCategories = await TaxonomyHelper.get(TaxonomyType.Category);
if (availableCategories && availableCategories.length > 0) {
@@ -209,7 +201,7 @@ export class ContentTypeSchemaGenerator {
schema.items = {
type: 'string'
};
// Get custom taxonomy options if taxonomyId is specified
if (field.taxonomyId) {
const customTaxonomies = Settings.get<CustomTaxonomy[]>(SETTING_TAXONOMY_CUSTOM);
@@ -315,9 +307,7 @@ export class ContentTypeSchemaGenerator {
* @param choices Array of choice strings or objects
* @returns Array of choice values
*/
private static extractChoiceValues(
choices: (string | { id?: string | null; title: string })[]
): string[] {
private static extractChoiceValues(choices: (string | { id?: string | null; title: string })[]): string[] {
return choices.map((choice) => {
if (typeof choice === 'string') {
return choice;
@@ -340,9 +330,7 @@ export class ContentTypeSchemaGenerator {
}
const fieldGroupIds = Array.isArray(field.fieldGroup) ? field.fieldGroup : [field.fieldGroup];
const fieldGroups = Settings.get(SETTING_TAXONOMY_FIELD_GROUPS) as
| { id: string; fields: Field[] }[]
| undefined;
const fieldGroups = Settings.get(SETTING_TAXONOMY_FIELD_GROUPS) as { id: string; fields: Field[] }[] | undefined;
if (!fieldGroups || fieldGroups.length === 0) {
return schemas;
+3 -3
View File
@@ -214,7 +214,7 @@ export class MediaHelpers {
if (selectedFolder) {
if (await existsAsync(selectedFolder)) {
foldersFromSelection = (await readdirAsync(selectedFolder, { withFileTypes: true }))
.filter((dir) => dir.isDirectory() && !dir.name.startsWith('.'))
.filter((dir) => dir.isDirectory())
.map((dir) => parseWinPath(join(selectedFolder, dir.name)));
}
}
@@ -225,7 +225,7 @@ export class MediaHelpers {
const contentPath = contentFolder.path;
if (contentPath && (await existsAsync(contentPath))) {
const subFolders = (await readdirAsync(contentPath, { withFileTypes: true }))
.filter((dir) => dir.isDirectory() && !dir.name.startsWith('.'))
.filter((dir) => dir.isDirectory())
.map((dir) => parseWinPath(join(contentPath, dir.name)));
allContentFolders = [...allContentFolders, ...subFolders];
}
@@ -243,7 +243,7 @@ export class MediaHelpers {
if (staticPath && (await existsAsync(staticPath))) {
allFolders = (await readdirAsync(staticPath, { withFileTypes: true }))
.filter((dir) => dir.isDirectory() && !dir.name.startsWith('.'))
.filter((dir) => dir.isDirectory())
.map((dir) => parseWinPath(join(staticPath, dir.name)));
}
+1 -3
View File
@@ -1,8 +1,7 @@
import {
SETTING_GLOBAL_TIMEZONE,
SETTING_PANEL_ACTIONS_DISABLED,
SETTING_WEBSITE_URL,
SETTING_COPILOT_ENABLED
SETTING_WEBSITE_URL
} from './../constants/settings';
import { workspace } from 'vscode';
import { ContentType, Extension, Logger, Settings, TaxonomyHelper } from '.';
@@ -52,7 +51,6 @@ export class PanelSettings {
try {
return {
aiEnabled: Settings.get<boolean>(SETTING_COPILOT_ENABLED) !== false,
copilotEnabled: await Copilot.isInstalled(),
git: await GitListener.getSettings(),
seo: {
+1 -5
View File
@@ -1,10 +1,8 @@
import { QuickPickItem, QuickPickItemKind, window } from 'vscode';
import { Folders } from '../commands/Folders';
import { SETTING_COPILOT_ENABLED } from '../constants';
import { ContentType } from './ContentType';
import { Notifications } from './Notifications';
import { Logger } from './Logger';
import { Settings } from './SettingsHelper';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
import { ContentFolder } from '../models';
@@ -39,14 +37,12 @@ export class Questions {
* @returns
*/
public static async ContentTitle(showWarning = true): Promise<string | undefined> {
const copilotEnabled = Settings.get<boolean>(SETTING_COPILOT_ENABLED) !== false;
let title: string | undefined = '';
const isCopilotInstalled = await Copilot.isInstalled();
let aiTitles: string[] | undefined;
// Only show AI suggestions if both the setting is enabled and Copilot is installed
if (copilotEnabled && isCopilotInstalled) {
if (isCopilotInstalled) {
title = await window.showInputBox({
title: l10n.t(LocalizationKey.helpersQuestionsContentTitleAiInputTitle),
prompt: l10n.t(LocalizationKey.helpersQuestionsContentTitleAiInputPrompt),
-3
View File
@@ -74,9 +74,6 @@ export class PagesListener extends BaseListener {
case DashboardMessage.moveFile:
await this.moveFile(msg.payload);
break;
case DashboardMessage.smartRename:
ArticleHelper.smartRename(msg.payload);
break;
}
}
+12 -38
View File
@@ -26,7 +26,7 @@ import {
import { GeneralCommands } from './../../constants/GeneralCommands';
import simpleGit, { SimpleGit } from 'simple-git';
import { Folders } from '../../commands/Folders';
import { Event, commands, extensions, workspace } from 'vscode';
import { Event, commands, extensions } from 'vscode';
import { GitAPIState, GitRepository, PostMessageData } from '../../models';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../localization';
@@ -69,21 +69,16 @@ export class GitListener {
const gitActions = Settings.get<boolean>(SETTING_GIT_ENABLED);
if (gitActions) {
Logger.verbose('GitListener:getSettings:end:enabled');
try {
return {
isGitRepo: gitActions ? await GitListener.isGitRepository() : false,
actions: gitActions || false,
disabledBranches: gitActions
? Settings.get<string[]>(SETTING_GIT_DISABLED_BRANCHES) || []
: [],
requiresCommitMessage: gitActions
? Settings.get<string[]>(SETTING_GIT_REQUIRES_COMMIT_MSG) || []
: []
};
} catch (e) {
Logger.error((e as Error).message);
return;
}
return {
isGitRepo: gitActions ? await GitListener.isGitRepository() : false,
actions: gitActions || false,
disabledBranches: gitActions
? Settings.get<string[]>(SETTING_GIT_DISABLED_BRANCHES) || []
: [],
requiresCommitMessage: gitActions
? Settings.get<string[]>(SETTING_GIT_REQUIRES_COMMIT_MSG) || []
: []
};
}
Logger.verbose('GitListener:getSettings:end:disabled');
@@ -343,7 +338,7 @@ export class GitListener {
const options = {
baseDir: submoduleFolder || wsFolder?.fsPath || '',
binary: GitListener.getGitBinary(),
binary: 'git',
maxConcurrentProcesses: 6
};
@@ -356,27 +351,6 @@ export class GitListener {
}
}
/**
* Resolves the Git binary path from VS Code settings.
* Falls back to the default `git` command when no custom path is configured.
*/
private static getGitBinary(): string {
const gitPath = workspace.getConfiguration('git').get<string | string[]>('path');
if (Array.isArray(gitPath)) {
const firstValidPath = gitPath.find((path) => typeof path === 'string' && path.trim());
if (firstValidPath) {
return firstValidPath;
}
}
if (typeof gitPath === 'string' && gitPath.trim()) {
return gitPath;
}
return 'git';
}
/**
* Initializes the VS Code Git provider and sets up event listeners for repository changes.
* @returns {Promise<void>} A promise that resolves when the Git provider is initialized.
-3
View File
@@ -25,9 +25,6 @@ export class ArticleListener extends BaseListener {
case CommandToCode.publish:
Article.toggleDraft();
break;
case CommandToCode.smartRename:
ArticleHelper.smartRename();
break;
}
}
+1 -26
View File
@@ -26,8 +26,7 @@ import {
SETTING_DATE_FORMAT,
SETTING_GLOBAL_ACTIVE_MODE,
SETTING_GLOBAL_MODES,
SETTING_TAXONOMY_CONTENT_TYPES,
SETTING_COPILOT_ENABLED
SETTING_TAXONOMY_CONTENT_TYPES
} from '../../constants';
import { Article, Preview } from '../../commands';
import { FrontMatterParser, ParsedFrontMatter } from '../../parsers';
@@ -125,15 +124,6 @@ export class DataListener extends BaseListener {
return;
}
// Check if Copilot is enabled and installed
const copilotEnabled = Settings.get<boolean>(SETTING_COPILOT_ENABLED) !== false;
const isCopilotInstalled = await Copilot.isInstalled();
if (!copilotEnabled || !isCopilotInstalled) {
this.sendRequestError(command, requestId, 'Copilot is not enabled or installed');
return;
}
const aiTitles = await Copilot.suggestTitles(title);
title = await Questions.pickTitleSuggestions(title, aiTitles || [], true);
@@ -155,21 +145,6 @@ export class DataListener extends BaseListener {
return;
}
// Check if Copilot is enabled and installed
const copilotEnabled = Settings.get<boolean>(SETTING_COPILOT_ENABLED) !== false;
const isCopilotInstalled = await Copilot.isInstalled();
if (!copilotEnabled || !isCopilotInstalled) {
const extPath = Extension.getInstance().extensionPath;
const panel = PanelProvider.getInstance(extPath);
panel.getWebview()?.postMessage({
command,
requestId,
error: l10n.t(LocalizationKey.servicesCopilotGetChatResponseError)
} as MessageHandlerData<string>);
return;
}
const article = ArticleHelper.getActiveFile();
if (!article) {
return;
-21
View File
@@ -4,10 +4,7 @@ import { BaseListener } from './BaseListener';
import { authentication, window } from 'vscode';
import { ArticleHelper, Extension, Settings, TaxonomyHelper } from '../../helpers';
import { BlockFieldData, CustomTaxonomyData, PostMessageData, TaxonomyType } from '../../models';
import { SETTING_COPILOT_ENABLED } from '../../constants';
import { DataListener } from '.';
import { SettingsListener as PanelSettingsListener } from '.';
import { SettingsListener as DashboardSettingsListener } from '../dashboard';
import { SponsorAi } from '../../services/SponsorAI';
import { PanelProvider } from '../../panelWebView/PanelProvider';
import { MessageHandlerData } from '@estruyf/vscode';
@@ -85,21 +82,6 @@ export class TaxonomyListener extends BaseListener {
return;
}
// Check if Copilot is enabled and installed
const copilotEnabled = Settings.get<boolean>(SETTING_COPILOT_ENABLED) !== false;
const isCopilotInstalled = await Copilot.isInstalled();
if (!copilotEnabled || !isCopilotInstalled) {
const extPath = Extension.getInstance().extensionPath;
const panel = PanelProvider.getInstance(extPath);
panel.getWebview()?.postMessage({
command,
requestId,
error: l10n.t(LocalizationKey.servicesCopilotGetChatResponseError)
} as MessageHandlerData<string[]>);
return;
}
const article = ArticleHelper.getActiveFile();
if (!article) {
return;
@@ -297,9 +279,6 @@ export class TaxonomyListener extends BaseListener {
}
await Settings.updateCustomTaxonomy(data.id, data.option);
PanelSettingsListener.getSettings();
DashboardSettingsListener.getSettings(true);
}
/**
-24
View File
@@ -1696,10 +1696,6 @@ export enum LocalizationKey {
* Optimize slug
*/
panelSlugActionTitle = 'panel.slugAction.title',
/**
* Smart rename
*/
panelSmartRenameActionTitle = 'panel.smartRenameAction.title',
/**
* Loading...
*/
@@ -1776,26 +1772,6 @@ export enum LocalizationKey {
* File name
*/
commandsArticleRenameFileNamePrompt = 'commands.article.rename.fileName.prompt',
/**
* The filename is already in sync with the front matter
*/
commandsArticleSmartRenameAlreadyInSync = 'commands.article.smartRename.alreadyInSync',
/**
* File renamed from "{0}" to "{1}"
*/
commandsArticleSmartRenameSuccess = 'commands.article.smartRename.success',
/**
* Unable to generate a new filename from the front matter
*/
commandsArticleSmartRenameUnableToGenerate = 'commands.article.smartRename.unableToGenerate',
/**
* A file with the name "{0}" already exists
*/
commandsArticleSmartRenameFileExistsError = 'commands.article.smartRename.fileExists.error',
/**
* Smart rename
*/
dashboardContentsContentActionsMenuItemSmartRename = 'dashboard.contents.contentActions.menuItem.smartRename',
/**
* Cache cleared
*/
-2
View File
@@ -28,7 +28,6 @@ export interface PanelSettings {
dataTypes: DataType[] | undefined;
fieldGroups: FieldGroup[] | undefined;
commaSeparatedFields: string[];
aiEnabled: boolean;
copilotEnabled: boolean;
contentFolders: ContentFolder[];
websiteUrl: string;
@@ -39,7 +38,6 @@ export type PanelAction =
| 'openDashboard'
| 'createContent'
| 'optimizeSlug'
| 'smartRename'
| 'preview'
| 'openOnWebsite'
| 'startStopServer'
+1 -2
View File
@@ -48,6 +48,5 @@ export enum CommandToCode {
searchByType = 'search-by-type',
processMediaData = 'process-media-data',
isServerStarted = 'is-server-started',
runFieldAction = 'run-field-action',
smartRename = 'smart-rename'
runFieldAction = 'run-field-action'
}
-5
View File
@@ -4,7 +4,6 @@ import { Collapsible } from './Collapsible';
import { CustomScript } from './CustomScript';
import { Preview } from './Preview';
import { SlugAction } from './SlugAction';
import { SmartRenameAction } from './SmartRenameAction';
import { StartServerButton } from './StartServerButton';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../localization';
@@ -53,10 +52,6 @@ const Actions: React.FunctionComponent<IActionsProps> = ({
allActions.push(<SlugAction key="optimizeSlug" />);
}
if (metadata?.title && !disableActions.includes(`smartRename`)) {
allActions.push(<SmartRenameAction key="smartRename" />);
}
if (settings?.preview?.host && !disableActions.includes(`preview`)) {
if ((metadata && typeof metadata.slug !== "undefined") || !metadata) {
allActions.push(<Preview key="preview" />);
@@ -1,25 +0,0 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import * as React from 'react';
import { CommandToCode } from '../CommandToCode';
import { ActionButton } from './ActionButton';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../localization';
export interface ISmartRenameActionProps { }
const SmartRenameAction: React.FunctionComponent<
ISmartRenameActionProps
> = () => {
const smartRename = () => {
Messenger.send(CommandToCode.smartRename);
};
return (
<ActionButton onClick={smartRename} title={l10n.t(LocalizationKey.panelSmartRenameActionTitle)}>
{l10n.t(LocalizationKey.panelSmartRenameActionTitle)}
</ActionButton>
);
};
SmartRenameAction.displayName = 'SmartRenameAction';
export { SmartRenameAction };
+4 -1
View File
@@ -40,7 +40,10 @@ export const Engines = {
return toml.parse(value);
},
stringify: (value: any) => {
return toml.stringify(value);
const result = toml.stringify(value);
// Preserve the original datetime format by removing unnecessary zero milliseconds
// e.g. 2025-09-12T10:00:00.000Z -> 2025-09-12T10:00:00Z
return result.replace(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})\.000([Z+-][\d:]*)?\b/g, '$1$2');
}
},
yaml: {
+1 -1
View File
@@ -201,7 +201,7 @@ export class PagesParser {
const modifiedField = await ArticleHelper.getModifiedDateField(article);
const modifiedFieldValue =
modifiedField?.name && article?.data[modifiedField.name]
? DateHelper.tryParse(article?.data[modifiedField.name], modifiedField.dateFormat)?.getTime()
? DateHelper.tryParse(article?.data[modifiedField.name])?.getTime()
: undefined;
const staticFolder = Folders.getStaticFolderRelativePath();