Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
be158d4
Update docs
estruyf Jul 3, 2025
76b103c
Merge branch 'beta' of github.com:estruyf/vscode-front-matter into beta
estruyf Jul 3, 2025
9940504
Refactor date change handling in DateTimeField to ensure proper timez…
estruyf Jul 14, 2025
43a6a22
Fix typo #969
estruyf Jul 15, 2025
a6188b0
Add entry for version 10.10.0 to CHANGELOG with typo fix on welcome s…
estruyf Jul 15, 2025
0c7e3fb
Enhancement: Support for numbers (int) in Snippets
estruyf Sep 8, 2025
bb53596
Update CHANGELOG for version 10.10.0: Add enhancements and fixes sect…
estruyf Sep 8, 2025
d11dbc9
Initial plan
Copilot Sep 8, 2025
f3df0f6
Initial plan
Copilot Sep 8, 2025
beef6f3
Implement first paragraph keyword check for SEO validation
Copilot Sep 8, 2025
e4147ee
Implement Structure view for dashboard with folder hierarchy display
Copilot Sep 8, 2025
73e58c7
Add multi-language localization support for Structure view
Copilot Sep 8, 2025
219c4bd
Merge branch 'copilot/fix-965' into beta
estruyf Sep 9, 2025
c8ebac3
Update CHANGELOG for version 10.10.0: Add SEO keyword support enhance…
estruyf Sep 9, 2025
65fc9f3
Fix Item rendering for Structure view type
Copilot Sep 9, 2025
b62d1e8
Fix folder hierarchy rendering in Structure view
Copilot Sep 9, 2025
61398c4
Merge branch 'copilot/fix-937' of github.com:estruyf/vscode-front-mat…
estruyf Sep 9, 2025
d4c5ca1
Fix folder path normalization in Structure view for proper nesting
Copilot Sep 9, 2025
cb42bd4
Merge branches 'copilot/fix-937' and 'copilot/fix-937' of github.com:…
estruyf Sep 9, 2025
cda217a
Enhance StructureView to normalize folder paths and improve page assi…
estruyf Sep 9, 2025
24c26ac
Refactor StructureView and Overview components for improved readabili…
estruyf Sep 9, 2025
aa0ee47
Merge branch 'copilot/fix-937' into beta
estruyf Sep 9, 2025
7fac27b
Enhancement: Dashboard "Structure" for Docs
estruyf Sep 9, 2025
8def864
Merge branch 'beta' into copilot/fix-937
estruyf Sep 10, 2025
206198e
Add click-to-create content in specific folders for Structure view
Copilot Sep 12, 2025
1977347
Implement right-click context menu for Structure view with create con…
Copilot Sep 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Change Log

## [10.10.0] - 2025-xx-xx

### 🎨 Enhancements

- [#937](https://github.com/estruyf/vscode-front-matter/issues/937): Dashboard "Structure" view for documentation sites
- [#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

### 🐞 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
Expand Down
4 changes: 2 additions & 2 deletions README.beta.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ In version v2 we released the re-designed sidebar panel with improved SEO suppor
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`
- 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).
Expand All @@ -129,7 +129,7 @@ If you have the courage to test out the beta features, we made available a beta
- 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`
- 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).
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ In version v2 we released the re-designed sidebar panel with improved SEO suppor
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`
- 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).
Expand All @@ -127,7 +127,7 @@ If you have the courage to test out the beta features, we made available a beta
- 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`
- 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).
Expand Down
1 change: 1 addition & 0 deletions l10n/bundle.l10n.de.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"dashboard.header.tabs.taxonomies": "Taxonomien",
"dashboard.header.viewSwitch.toGrid": "Zur Rasteransicht wechseln",
"dashboard.header.viewSwitch.toList": "Zur Listenansicht wechseln",
"dashboard.header.viewSwitch.toStructure": "Zur Strukturansicht wechseln",
"dashboard.layout.sponsor.support.msg": "Unterstützen Sie Front Matter",
"dashboard.layout.sponsor.review.label": "Bewerten",
"dashboard.layout.sponsor.review.msg": "Bewerten Sie Front Matter",
Expand Down
1 change: 1 addition & 0 deletions l10n/bundle.l10n.fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"dashboard.header.tabs.taxonomies": "Taxonomies",
"dashboard.header.viewSwitch.toGrid": "Afficher en grille",
"dashboard.header.viewSwitch.toList": "Afficher en liste",
"dashboard.header.viewSwitch.toStructure": "Afficher en structure",
"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",
Expand Down
1 change: 1 addition & 0 deletions l10n/bundle.l10n.ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@

"dashboard.header.viewSwitch.toGrid": "グリッド表示",
"dashboard.header.viewSwitch.toList": "リスト表示",
"dashboard.header.viewSwitch.toStructure": "構造表示",

"dashboard.layout.sponsor.support.msg": "Front Matterをサポートする",
"dashboard.layout.sponsor.review.label": "評価する",
Expand Down
4 changes: 3 additions & 1 deletion l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@

"dashboard.header.viewSwitch.toGrid": "Change to grid",
"dashboard.header.viewSwitch.toList": "Change to list",
"dashboard.header.viewSwitch.toStructure": "Change to structure",

"dashboard.layout.sponsor.support.msg": "Support Front Matter",
"dashboard.layout.sponsor.review.label": "Review",
Expand Down Expand Up @@ -332,7 +333,7 @@
"dashboard.steps.stepsToGetStarted.tags.name": "Import all tags and categories (optional)",
"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.git.name": "Do you want to enable Git synchronization?",
"dashboard.steps.stepsToGetStarted.git.description": "Enable Git synchronization to eaily sync your changes with your repository.",
"dashboard.steps.stepsToGetStarted.git.description": "Enable Git synchronization to easily sync your changes with your repository.",
"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",
Expand Down Expand Up @@ -504,6 +505,7 @@
"panel.seoKeywords.density": "Keyword density",
"panel.seoKeywordInfo.validInfo.label": "Heading(s)",
"panel.seoKeywordInfo.validInfo.content": "Content",
"panel.seoKeywordInfo.validInfo.firstParagraph": "First paragraph",
"panel.seoKeywordInfo.density.tooltip": "Recommended frequency: 0.75% - 1.5%",

"panel.seoKeywords.title": "Keywords",
Expand Down
1 change: 1 addition & 0 deletions l10n/bundle.l10n.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@

"dashboard.header.viewSwitch.toGrid": "切换到网格视图",
"dashboard.header.viewSwitch.toList": "切换到列表视图",
"dashboard.header.viewSwitch.toStructure": "切换到结构视图",

"dashboard.layout.sponsor.support.msg": "支持 Front Matter",
"dashboard.layout.sponsor.review.label": "评价",
Expand Down
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,11 @@
"title": "%command.frontMatter.createContent%",
"category": "Front Matter"
},
{
"command": "frontMatter.structure.createContentInFolder",
"title": "Create Content in Folder",
"category": "Front Matter"
},
{
"command": "frontMatter.createTag",
"title": "%command.frontMatter.createTag%",
Expand Down Expand Up @@ -2484,6 +2489,11 @@
{
"command": "workbench.action.webview.openDeveloperTools",
"when": "frontMatter:isDevelopment"
},
{
"command": "frontMatter.structure.createContentInFolder",
"when": "webview == frontMatterDashboard && webviewItem == folder",
"group": "1_structure@1"
}
],
"editor/title": [
Expand Down
2 changes: 2 additions & 0 deletions src/constants/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const COMMAND_NAME = {
createContent: getCommandName('createContent'),
createByContentType: getCommandName('createByContentType'),
createByTemplate: getCommandName('createByTemplate'),
createContentInFolder: getCommandName('createContentInFolder'),
structureCreateContentInFolder: getCommandName('structure.createContentInFolder'),
createTemplate: getCommandName('createTemplate'),
initTemplate: getCommandName('initTemplate'),
collapseSections: getCommandName('collapseSections'),
Expand Down
1 change: 1 addition & 0 deletions src/dashboardWebView/DashboardMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export enum DashboardMessage {
createContent = 'createContent',
createByContentType = 'createByContentType',
createByTemplate = 'createByTemplate',
createContentInFolder = 'createContentInFolder',
refreshPages = 'refreshPages',
searchPages = 'searchPages',
openFile = 'openFile',
Expand Down
68 changes: 68 additions & 0 deletions src/dashboardWebView/components/Common/NumberField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { XCircleIcon } from '@heroicons/react/24/solid';
import * as React from 'react';

export interface INumberFieldProps {
name: string;
value?: string;
placeholder?: string;
description?: string;
icon?: JSX.Element;
disabled?: boolean;
autoFocus?: boolean;
onChange?: (value: string) => void;
onReset?: () => void;
}

export const NumberField: React.FunctionComponent<INumberFieldProps> = ({
name,
value,
placeholder,
description,
icon,
autoFocus,
disabled,
onChange,
onReset
}: React.PropsWithChildren<INumberFieldProps>) => {
return (
<>
<div className="relative flex justify-center">
{
icon && (
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
{icon}
</div>
)
}

<input
type="number"
name={name}
className={`block w-full py-2 ${icon ? "pl-10" : "pl-2"} pr-2 sm:text-sm appearance-none disabled:opacity-50 rounded bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] border-[var(--frontmatter-border)] focus:border-[var(--vscode-focusBorder)] focus:outline-0`}
style={{
boxShadow: "none"
}}
placeholder={placeholder || ""}
value={value}
autoFocus={!!autoFocus}
onChange={(e) => onChange && onChange(e.target.value)}
disabled={!!disabled}
/>

{(value && onReset) && (
<button onClick={onReset} className="absolute inset-y-0 right-0 pr-3 flex items-center text-[var(--vscode-input-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]">
<XCircleIcon className={`h-5 w-5`} aria-hidden="true" />
</button>
)}
</div>

{
description && (
<p className="text-xs text-[var(--vscode--settings-headerForeground)] opacity-75 mt-2 mx-2">
{description}
</p>
)
}
</>
);
};
2 changes: 2 additions & 0 deletions src/dashboardWebView/components/Contents/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export const List: React.FunctionComponent<IListProps> = ({
className = `grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 2xl:grid-cols-5 gap-4`;
} else if (view === DashboardViewType.List) {
className = `-mx-4`;
} else if (view === DashboardViewType.Structure) {
className = `structure-view`;
}

return (
Expand Down
12 changes: 9 additions & 3 deletions src/dashboardWebView/components/Contents/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { GroupOption } from '../../constants/GroupOption';
import { GroupingSelector, PageAtom, PagedItems, ViewSelector } from '../../state';
import { Item } from './Item';
import { List } from './List';
import { StructureView } from './StructureView';
import usePagination from '../../hooks/usePagination';
import { LocalizationKey, localize } from '../../../localization';
import { PinnedItemsAtom } from '../../state/atom/PinnedItems';
Expand Down Expand Up @@ -145,16 +146,21 @@ export const Overview: React.FunctionComponent<IOverviewProps> = ({
/>
{settings && settings?.contentFolders?.length > 0 ? (
<p className={`text-xl font-medium`}>{localize(LocalizationKey.dashboardContentsOverviewNoMarkdown)}</p>

) : (
<p className={`text-lg font-medium`}>{localize(LocalizationKey.dashboardContentsOverviewNoFolders)}</p>

)}
</div>
</div>
);
}

// Handle Structure view first - it overrides all other display modes
if (view === DashboardViewType.Structure) {
return <StructureView pages={pages} />;
}

if (grouping !== GroupOption.none) {
return (
<>
Expand Down Expand Up @@ -196,7 +202,7 @@ export const Overview: React.FunctionComponent<IOverviewProps> = ({
<h1 className='text-xl flex space-x-2 items-center mb-4'>
<PinIcon className={`-rotate-45`} />
<span>{localize(LocalizationKey.dashboardContentsOverviewPinned)}</span>

</h1>
<List>
{pinnedPages.map((page, idx) => (
Expand Down
79 changes: 79 additions & 0 deletions src/dashboardWebView/components/Contents/StructureItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useRecoilValue } from 'recoil';
import { MarkdownIcon } from '../../../panelWebView/components/Icons/MarkdownIcon';
import { Page } from '../../models/Page';
import { SettingsSelector } from '../../state';
import { DateField } from '../Common/DateField';
import { ContentActions } from './ContentActions';
import { useMemo } from 'react';
import { Status } from './Status';
import * as React from 'react';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import useCard from '../../hooks/useCard';
import { ItemSelection } from '../Common/ItemSelection';
import { openFile } from '../../utils';
import useSelectedItems from '../../hooks/useSelectedItems';
import { cn } from '../../../utils/cn';

export interface IStructureItemProps extends Page { }

export const StructureItem: React.FunctionComponent<IStructureItemProps> = ({
...pageData
}: React.PropsWithChildren<IStructureItemProps>) => {
const { selectedFiles } = useSelectedItems();
const settings = useRecoilValue(SettingsSelector);
const draftField = useMemo(() => settings?.draftField, [settings]);
const { escapedTitle } = useCard(pageData, settings?.dashboardState?.contents?.cardFields);

const isSelected = useMemo(() => selectedFiles.includes(pageData.fmFilePath), [selectedFiles, pageData.fmFilePath]);

const onOpenFile = React.useCallback(() => {
openFile(pageData.fmFilePath);
}, [pageData.fmFilePath]);

return (
<div className="relative">
<div
className={cn(
`flex items-center space-x-3 py-1 px-2 rounded cursor-pointer hover:bg-[var(--vscode-list-hoverBackground)] text-[var(--vscode-editor-foreground)]`,
isSelected && `bg-[var(--vscode-list-activeSelectionBackground)]`
)}
>
<ItemSelection filePath={pageData.fmFilePath} show />

<MarkdownIcon className="w-4 h-4 text-[var(--vscode-symbolIcon-fileForeground)] flex-shrink-0" />

<button
title={escapedTitle ? l10n.t(LocalizationKey.commonOpenWithValue, escapedTitle) : l10n.t(LocalizationKey.commonOpen)}
onClick={onOpenFile}
className="flex-1 text-left truncate font-medium"
>
{escapedTitle}
</button>

<div className="flex items-center space-x-2 flex-shrink-0">
{pageData.date && (
<DateField
value={pageData.date}
format={pageData.fmDateFormat}
className="text-xs text-[var(--vscode-descriptionForeground)]"
/>
)}

{draftField && draftField.name && typeof pageData[draftField.name] !== "undefined" && (
<Status draft={pageData[draftField.name]} published={pageData.fmPublished} />
)}

<ContentActions
path={pageData.fmFilePath}
relPath={pageData.fmRelFileWsPath}
contentType={pageData.fmContentType}
scripts={settings?.scripts}
onOpen={onOpenFile}
listView
/>
</div>
</div>
</div>
);
};
Loading