Merge branch 'release/v7.2.0' into dev

This commit is contained in:
Elio Struyf
2022-04-12 17:07:46 +02:00
16 changed files with 363 additions and 73 deletions
+12
View File
@@ -1,5 +1,17 @@
# Change Log
## [7.2.0] - 2022-04-xx
### 🎨 Enhancements
- [#263](https://github.com/estruyf/vscode-front-matter/issues/263): WYSIWYG string field option
- [#314](https://github.com/estruyf/vscode-front-matter/issues/314): New preview actions to open the page in the browser and refresh the preview
- [#322](https://github.com/estruyf/vscode-front-matter/issues/322): Show parent folder name when file is an index page (`index.md` / `_index.md`)
### ⚡️ Optimizations
- [#316](https://github.com/estruyf/vscode-front-matter/issues/316): Surpress file parsing errors when closing the dashboard
## [7.1.2] - 2022-04-11
### 🐞 Fixes
+78 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vscode-front-matter-beta",
"version": "7.1.2",
"version": "7.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -642,6 +642,15 @@
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true
},
"@types/quill": {
"version": "1.3.10",
"resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
"integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
"dev": true,
"requires": {
"parchment": "^1.1.2"
}
},
"@types/range-parser": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
@@ -1432,6 +1441,12 @@
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
"dev": true
},
"clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
"dev": true
},
"clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@@ -2286,6 +2301,12 @@
}
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"dev": true
},
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
@@ -2301,6 +2322,12 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"fast-diff": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
"dev": true
},
"fast-glob": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
@@ -4224,6 +4251,12 @@
"tslib": "^1.10.0"
}
},
"parchment": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
"dev": true
},
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -4606,6 +4639,39 @@
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
"dev": true
},
"quill": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
"dev": true,
"requires": {
"clone": "^2.1.1",
"deep-equal": "^1.0.1",
"eventemitter3": "^2.0.3",
"extend": "^3.0.2",
"parchment": "^1.1.4",
"quill-delta": "^3.6.2"
},
"dependencies": {
"eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=",
"dev": true
}
}
},
"quill-delta": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
"dev": true,
"requires": {
"deep-equal": "^1.0.1",
"extend": "^3.0.2",
"fast-diff": "1.1.2"
}
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -4707,6 +4773,17 @@
"warning": "^4.0.2"
}
},
"react-quill": {
"version": "2.0.0-beta.4",
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0-beta.4.tgz",
"integrity": "sha512-KyAHvAlPjP4xLElKZJefMth91Z6FbbXRvq9OSu6xN3KBaoasLP9p+3dcxg4Ywr4tBlpMGXcPszYSAgd5CpJ45Q==",
"dev": true,
"requires": {
"@types/quill": "^1.3.10",
"lodash": "^4.17.4",
"quill": "^1.3.7"
}
},
"react-sortable-hoc": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz",
+7 -1
View File
@@ -3,7 +3,7 @@
"displayName": "Front Matter",
"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, Hexo, NextJs, Gatsby, and many more...",
"icon": "assets/frontmatter-teal-128x128.png",
"version": "7.1.2",
"version": "7.2.0",
"preview": false,
"publisher": "eliostruyf",
"galleryBanner": {
@@ -802,6 +802,11 @@
"default": false,
"description": "Is a single line field"
},
"wysiwyg": {
"type": "boolean",
"default": false,
"description": "Is a WYSIWYG field (HTML output)"
},
"multiple": {
"type": "boolean",
"default": false,
@@ -1802,6 +1807,7 @@
"react-datepicker": "4.2.1",
"react-dom": "17.0.1",
"react-dropzone": "^11.3.4",
"react-quill": "^2.0.0-beta.4",
"react-sortable-hoc": "^2.0.0",
"react-toastify": "^8.1.0",
"recoil": "^0.4.1",
+55 -51
View File
@@ -1,14 +1,15 @@
import { Telemetry } from './../helpers/Telemetry';
import { SETTING_PREVIEW_HOST, SETTING_PREVIEW_PATHNAME, CONTEXT, TelemetryEvent } from './../constants';
import { SETTING_PREVIEW_HOST, SETTING_PREVIEW_PATHNAME, CONTEXT, TelemetryEvent, PreviewCommands } from './../constants';
import { ArticleHelper } from './../helpers/ArticleHelper';
import { join } from "path";
import { commands, env, Uri, ViewColumn, window } from "vscode";
import { Settings } from '../helpers';
import { Extension, Settings } from '../helpers';
import { PreviewSettings } from '../models';
import { format } from 'date-fns';
import { DateHelper } from '../helpers/DateHelper';
import { Article } from '.';
import { urlJoin } from 'url-join-ts';
import { WebviewHelper } from '@estruyf/vscode';
export class Preview {
@@ -81,59 +82,62 @@ export class Preview {
const cspSource = webView.webview.cspSource;
webView.webview.html = `<!DOCTYPE html>
<head>
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; frame-src ${localhostUrl} ${cspSource} http: https:; img-src ${localhostUrl} ${cspSource} http: https:; script-src ${localhostUrl} ${cspSource} 'unsafe-inline'; style-src ${localhostUrl} ${cspSource} 'self' 'unsafe-inline' http: https:;"
/>
<style>
html,body {
margin: 0;
padding: 0;
background: white;
height: 100%;
width: 100%;
}
body {
margin: 0;
padding: 0;
webView.webview.onDidReceiveMessage(message => {
switch (message.command) {
case PreviewCommands.toVSCode.open:
if (message.data) {
commands.executeCommand('vscode.open', message.data);
}
return;
}
});
iframe {
width: 100%;
height: calc(100% - 30px);
border: 0;
margin-top: 30px;
}
.slug {
width: 100%;
position: fixed;
height: 30px;
display: flex;
align-items: center;
background-color: var(--vscode-editor-background);
border-bottom: 1px solid var(--vscode-focusBorder);
}
const dashboardFile = "dashboardWebView.js";
const localPort = `9000`;
const localServerUrl = `localhost:${localPort}`;
input {
color: var(--vscode-editor-foreground);
padding: 0.25rem 0.5rem;
background: none;
border: 0;
width: 100%;
}
</style>
</head>
<body>
<div class="slug">
<input type="text" value="${urlJoin(localhostUrl.toString(), slug || '')}" disabled />
</div>
<iframe src="${urlJoin(localhostUrl.toString(), slug || '')}" >
</body>
</html>`;
const nonce = WebviewHelper.getNonce();
const ext = Extension.getInstance();
const isProd = ext.isProductionMode;
const version = ext.getVersion();
const isBeta = ext.isBetaVersion();
const extensionUri = ext.extensionPath;
const csp = [
`default-src 'none';`,
`img-src ${localhostUrl} ${cspSource} http: https:;`,
`script-src ${isProd ? `'nonce-${nonce}'` : `http://${localServerUrl} http://0.0.0.0:${localPort}`} 'unsafe-eval'`,
`style-src ${cspSource} 'self' 'unsafe-inline' http: https:`,
`connect-src https://o1022172.ingest.sentry.io ${isProd ? `` : `ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`}`,
`frame-src ${localhostUrl} ${cspSource} http: https:;`,
];
let scriptUri = "";
if (isProd) {
scriptUri = webView.webview.asWebviewUri(Uri.joinPath(extensionUri, 'dist', dashboardFile)).toString();
} else {
scriptUri = `http://${localServerUrl}/${dashboardFile}`;
}
webView.webview.html = `
<!DOCTYPE html>
<html lang="en" style="width:100%;height:100%;margin:0;padding:0;">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="${csp.join('; ')}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Front Matter Preview</title>
</head>
<body style="width:100%;height:100%;margin:0;padding:0;overflow:hidden">
<div id="app" data-type="preview" data-url="${urlJoin(localhostUrl.toString(), slug || '')}" data-isProd="${isProd}" data-environment="${isBeta ? "BETA" : "main"}" data-version="${version.usedVersion}" style="width:100%;height:100%;margin:0;padding:0;"></div>
<script ${isProd ? `nonce="${nonce}"` : ""} src="${scriptUri}"></script>
</body>
</html>
`;
Telemetry.send(TelemetryEvent.openPreview);
}
+8
View File
@@ -0,0 +1,8 @@
export const PreviewCommands = {
toVSCode: {
open: `preview.open`
},
fromVSCode: {}
};
+1
View File
@@ -9,6 +9,7 @@ export * from './GeneralCommands';
export * from './Links';
export * from './LocalStore';
export * from './Navigation';
export * from './PreviewCommands';
export * from './TelemetryEvent';
export * from './charCode';
export * from './charMap';
@@ -0,0 +1,69 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { ExternalLinkIcon, RefreshIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { useRef } from 'react';
import { PreviewCommands } from '../../../constants';
export interface IPreviewProps {
url: string | null;
}
export const Preview: React.FunctionComponent<IPreviewProps> = ({url}: React.PropsWithChildren<IPreviewProps>) => {
const iframeRef = useRef<HTMLIFrameElement>(null);
const onRefresh = () => {
if (iframeRef.current?.src) {
iframeRef.current.src = iframeRef.current.src;
}
};
const openInBrowser = () => {
Messenger.send(PreviewCommands.toVSCode.open, url);
};
return (
<div className='w-full h-full bg-white'>
<div
className="slug fixed w-full top-0 flex items-center"
style={{
height: "30px",
background: "var(--vscode-editor-background)",
borderBottom: "1px solid var(--vscode-focusBorder)"
}}
>
<input
type="text"
value={url || ""}
className="w-full h-full border-0 bg-transparent text-xs py-1 px-2"
style={{
color: "var(--vscode-editor-foreground)"
}}
disabled />
<div
className="actions absolute right-0 top-0 bottom-0 flex items-center space-x-2 px-2"
style={{
background: "var(--vscode-editor-background)",
}}
>
<button title="Refresh" onClick={onRefresh}>
<RefreshIcon className='w-4 h-4' aria-hidden="true" />
</button>
<button title="Open" onClick={openInBrowser} className="mr-2">
<ExternalLinkIcon className='w-4 h-4' aria-hidden="true" />
</button>
</div>
</div>
<iframe
ref={iframeRef}
src={url || ""}
className={`w-full border-0`}
style={{
height: "calc(100% - 30px)",
marginTop: "30px"
}}></iframe>
</div>
);
};
@@ -0,0 +1 @@
export * from './Preview';
+8 -1
View File
@@ -6,6 +6,7 @@ import * as Sentry from "@sentry/react";
import { Integrations } from "@sentry/tracing";
import { SENTRY_LINK } from "../constants";
import './styles.css';
import { Preview } from "./components/Preview";
declare const acquireVsCodeApi: <T = unknown>() => {
getState: () => T;
@@ -19,6 +20,8 @@ if (elm) {
const version = elm?.getAttribute("data-version");
const environment = elm?.getAttribute("data-environment");
const isProd = elm?.getAttribute("data-isProd");
const type = elm?.getAttribute("data-type");
const url = elm?.getAttribute("data-url");
if (isProd === "true") {
Sentry.init({
@@ -31,7 +34,11 @@ if (elm) {
});
}
render(<RecoilRoot><Dashboard showWelcome={!!welcome} /></RecoilRoot>, elm);
if (type === "preview") {
render(<Preview url={url} />, elm);
} else {
render(<RecoilRoot><Dashboard showWelcome={!!welcome} /></RecoilRoot>, elm);
}
}
// Webpack HMR
+4
View File
@@ -174,6 +174,10 @@ export class PagesListener extends BaseListener {
}
} catch (error: any) {
if ((error as Error)?.message.toLowerCase() === "webview is disposed") {
continue;
}
Logger.error(`PagesListener::getPagesData: ${file.filePath} - ${error.message}`);
Notifications.error(`File error: ${file.filePath} - ${error?.message || error}`);
}
+1
View File
@@ -56,6 +56,7 @@ export interface Field {
type: FieldType;
choices?: string[] | Choice[];
single?: boolean;
wysiwyg?: boolean;
multiple?: boolean;
isPreviewImage?: boolean;
hidden?: boolean;
@@ -6,12 +6,15 @@ export interface ITextFieldProps {
label: string;
value: string | null;
singleLine: boolean | undefined;
wysiwyg: boolean | undefined;
limit: number | undefined;
rows?: number;
onChange: (txtValue: string) => void;
}
export const TextField: React.FunctionComponent<ITextFieldProps> = ({singleLine, limit, label, value, rows, onChange}: React.PropsWithChildren<ITextFieldProps>) => {
const WysiwygField = React.lazy(() => import('./WysiwygField'));
export const TextField: React.FunctionComponent<ITextFieldProps> = ({singleLine, wysiwyg, limit, label, value, rows, onChange}: React.PropsWithChildren<ITextFieldProps>) => {
const [ text, setText ] = React.useState<string | null>(value);
React.useEffect(() => {
@@ -37,25 +40,31 @@ export const TextField: React.FunctionComponent<ITextFieldProps> = ({singleLine,
<PencilIcon style={{ width: "16px", height: "16px" }} /> <span style={{ lineHeight: "16px"}}>{label}</span>
</div>
</VsLabel>
{
singleLine ? (
<input
className={`metadata_field__input`}
value={text || ""}
onChange={(e) => onTextChange(e.currentTarget.value)}
style={{
border: isValid ? "1px solid var(--vscode-inputValidation-infoBorder)" : "1px solid var(--vscode-inputValidation-warningBorder)"
}} />
wysiwyg ? (
<React.Suspense fallback={(<div>Loading field</div>)}>
<WysiwygField text={text || ""} onChange={onTextChange} />
</React.Suspense>
) : (
<textarea
className={`metadata_field__textarea`}
rows={rows || 2}
value={text || ""}
onChange={(e) => onTextChange(e.currentTarget.value)}
style={{
border: isValid ? "1px solid var(--vscode-inputValidation-infoBorder)" : "1px solid var(--vscode-inputValidation-warningBorder)"
}} />
singleLine ? (
<input
className={`metadata_field__input`}
value={text || ""}
onChange={(e) => onTextChange(e.currentTarget.value)}
style={{
border: isValid ? "1px solid var(--vscode-inputValidation-infoBorder)" : "1px solid var(--vscode-inputValidation-warningBorder)"
}} />
) : (
<textarea
className={`metadata_field__textarea`}
rows={rows || 2}
value={text || ""}
onChange={(e) => onTextChange(e.currentTarget.value)}
style={{
border: isValid ? "1px solid var(--vscode-inputValidation-infoBorder)" : "1px solid var(--vscode-inputValidation-warningBorder)"
}} />
)
)
}
@@ -153,6 +153,7 @@ export const WrapperField: React.FunctionComponent<IWrapperFieldProps> = ({
label={field.title || field.name}
singleLine={field.single}
limit={limit}
wysiwyg={field.wysiwyg}
rows={3}
onChange={(value) => onSendUpdate(field.name, value, parentFields)}
value={fieldValue as string || null} />
@@ -0,0 +1,28 @@
import * as React from 'react';
const ReactQuill = require('react-quill');
import 'react-quill/dist/quill.snow.css';
export interface IWysiwygFieldProps {
text: string;
onChange: (txtValue: string) => void;
}
const WysiwygField: React.FunctionComponent<IWysiwygFieldProps> = ({ text, onChange }: React.PropsWithChildren<IWysiwygFieldProps>) => {
const modules = {
toolbar: [
[{ 'header': [1, 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'],
[{'list': 'ordered'}, {'list': 'bullet'}],
['clean']
]
};
return (
<ReactQuill
modules={modules}
value={text || ""}
onChange={onChange} />
);
};
export default WysiwygField;
+1 -1
View File
@@ -19,7 +19,7 @@ const FileItem: React.FunctionComponent<IFileItemProps> = ({ name, folderName, p
};
const itemName = useMemo(() => {
if (folderName && name === 'index.md') {
if (folderName && name.includes("index.")) {
return folderName;
}
+62
View File
@@ -251,4 +251,66 @@
.sr-only {
display: none;
}
/* Quill changes */
.ql-toolbar.ql-snow,
.ql-container.ql-snow {
border-color: var(--vscode-inputValidation-infoBorder) !important;
}
.ql-toolbar.ql-snow {
padding: var(--input-padding-vertical) var(--input-padding-horizontal) !important;
}
.ql-snow .ql-picker {
color: var(--vscode-settings-headerForeground) !important;
}
.ql-snow .ql-fill {
fill: var(--vscode-settings-headerForeground) !important;
}
.ql-snow .ql-stroke {
stroke: var(--vscode-settings-headerForeground) !important;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
border-color: var(--vscode-inputValidation-infoBorder) !important;
}
.ql-snow .ql-picker-options {
background: var(--vscode-input-background) !important;
color: var(--vscode-input-foreground) !important;
border-color: var(--vscode-inputValidation-infoBorder) !important;
}
.ql-editor {
background-color: var(--vscode-input-background) !important;
padding: var(--input-padding-vertical) var(--input-padding-horizontal) !important;
}
.ql-snow.ql-toolbar button:hover,
.ql-snow .ql-toolbar button:hover,
.ql-snow.ql-toolbar button:focus,
.ql-snow .ql-toolbar button:focus,
.ql-snow.ql-toolbar button.ql-active,
.ql-snow .ql-toolbar button.ql-active,
.ql-snow.ql-toolbar .ql-picker-label:hover,
.ql-snow .ql-toolbar .ql-picker-label:hover,
.ql-snow.ql-toolbar .ql-picker-label.ql-active,
.ql-snow .ql-toolbar .ql-picker-label.ql-active,
.ql-snow.ql-toolbar .ql-picker-item:hover,
.ql-snow .ql-toolbar .ql-picker-item:hover,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected {
color: var(--vscode-button-background) !important;
}
.ql-snow.ql-toolbar button:hover .ql-stroke, .ql-snow .ql-toolbar button:hover .ql-stroke, .ql-snow.ql-toolbar button:focus .ql-stroke, .ql-snow .ql-toolbar button:focus .ql-stroke, .ql-snow.ql-toolbar button.ql-active .ql-stroke, .ql-snow .ql-toolbar button.ql-active .ql-stroke, .ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke, .ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke, .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke, .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke, .ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke, .ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke, .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke, .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke, .ql-snow.ql-toolbar button:hover .ql-stroke-miter, .ql-snow .ql-toolbar button:hover .ql-stroke-miter, .ql-snow.ql-toolbar button:focus .ql-stroke-miter, .ql-snow .ql-toolbar button:focus .ql-stroke-miter, .ql-snow.ql-toolbar button.ql-active .ql-stroke-miter, .ql-snow .ql-toolbar button.ql-active .ql-stroke-miter, .ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter, .ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter, .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, .ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter, .ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter, .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter, .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter {
stroke: var(--vscode-button-background) !important;
}
.ql-snow.ql-toolbar button:hover .ql-fill, .ql-snow .ql-toolbar button:hover .ql-fill, .ql-snow.ql-toolbar button:focus .ql-fill, .ql-snow .ql-toolbar button:focus .ql-fill, .ql-snow.ql-toolbar button.ql-active .ql-fill, .ql-snow .ql-toolbar button.ql-active .ql-fill, .ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill, .ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill, .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill, .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill, .ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill, .ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill, .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill, .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill, .ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill, .ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill, .ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill, .ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill, .ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill, .ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill, .ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, .ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, .ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, .ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill, .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill {
fill: var(--vscode-button-background) !important;
}