mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-07-06 18:01:24 +02:00
Merge branch 'poc/preview' into release/v7.2.0
This commit is contained in:
+55
-51
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
export const PreviewCommands = {
|
||||
toVSCode: {
|
||||
open: `preview.open`
|
||||
},
|
||||
fromVSCode: {}
|
||||
};
|
||||
@@ -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';
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user