CodePrez
diff --git a/src/components/Slide.tsx b/src/components/Slide.tsx index 8b297af..6276a89 100644 --- a/src/components/Slide.tsx +++ b/src/components/Slide.tsx @@ -1,9 +1,30 @@ -export const Slide = ({ children }: any) => { +import { useEffect } from "react"; +import "../assets/css/Slide.css" + +type Props = { + children: string | React.ReactElement[]; + slideScale: "preview" | "sidebar" | "slideViewer", + className?: string +} + +export const Slide = ({ children, slideScale, className }: Props) => { + + if(typeof children == "string") { return ( - +' + ) + } else { + return ( + '' + + hljs.highlight(str, { + language: lang, + ignoreIllegals: true, + }).value + + '
play_arrow
' +
+ hljs.highlight(str, {
+ language: lang,
+ ignoreIllegals: true,
+ }).value +
+ "
"
+ );
+ }
+ } catch (__) {}
+ }
+
+ return (
+ '' +
+ md.utils.escapeHtml(str) +
+ "
"
+ );
+ },
+ }
+
+ const md = MarkdownIt(markdownOptions);
+
+ //Include images
+ md.renderer.rules.image = (tokens, idx, options, env, self) => imageRendererRules({tokens, idx, options, env, self, presentationPath});
+
+ //Include code via file
+ md.renderer.rules.link_open = (tokens, idx, options, env, self) => linkRendererRules({tokens, idx, options, env, self, presentationPath})
+
+ return md;
+}
+
+const imageRendererRules = ({tokens, idx, options, env, self, presentationPath}: RendererRulesArguments) => {
+ const token = tokens[idx];
+
+ const src = token.attrGet("src");
+
+ const regexForSrc = /\.\/assets/gm;
+
+ const srcWithPresentationPath = (src?.match(regexForSrc)) ? path.join("codeprez:/", presentationPath, src) : src
+ token.attrSet('src', srcWithPresentationPath || "")
+
+ return self.renderToken(tokens, idx, options)
+}
+
+const linkRendererRules = ({tokens, idx, options, env, self, presentationPath}: RendererRulesArguments) => {
+ const token = tokens[idx];
+
+ const href = token.attrGet("href")
+ const regexPathFile = /^\.\/(.+\.\w+)/gm;
+ const relativeCodeFilePath = href?.match(regexPathFile) ?? [];
+
+ if(relativeCodeFilePath.length) {
+ const codeFilePath = path.join(presentationPath, relativeCodeFilePath[0] ?? "")
+ return codeFileRendererRules({codeFilePath: codeFilePath, href});
+ } else {
+ return self.renderToken(tokens, idx, options);
+ }
+
+}
+
+const codeFileRendererRules = ({codeFilePath, href}: CodeFileRendererRulesArguments) => {
+
+ const regexLineNumber = /#(\d+)-(\d+)/;
+ const regexFileExtension = /\.(\w+)(?:#\d+-\d+)?$/;
+
+ const lineNumbers = href?.match(regexLineNumber) ?? [];
+ const startNumber = lineNumbers[1];
+ const endNumber = lineNumbers[2];
+
+ const fileExtension = href?.match(regexFileExtension) ?? [];
+
+ const file = fs.readFileSync(codeFilePath, { encoding: 'utf8' });
+ const lines = file.split("\n").slice(Number(startNumber)-1, Number(endNumber));
+
+ const codeToDisplay = (lineNumbers.length) ? lines.join("\n") : file;
+
+ // I must use a concatenate string instead of `` because of tabulation and break line
+ return (
+ "" +
+ hljs.highlight(codeToDisplay, {
+ language: fileExtension[1] || "",
+ ignoreIllegals: true,
+ }).value +
+ "
"
+ )
+}
diff --git a/src/main/openAndCloseCodePrezFiles.ts b/src/main/openAndCloseCodePrezFiles.ts
index 8b1aac7..786910f 100644
--- a/src/main/openAndCloseCodePrezFiles.ts
+++ b/src/main/openAndCloseCodePrezFiles.ts
@@ -22,6 +22,8 @@ const decompressCodePrezArchive = async (
export const openCodePrezArchive = async (archivePath: string) => {
const presentationPath = path.join(tempPath, "codeprez"); //useful for assets, style.css and env
+ deleteCodePrezTempFolder();
+
const files = await decompressCodePrezArchive(
archivePath,
presentationPath
@@ -38,13 +40,20 @@ export const openCodePrezArchive = async (archivePath: string) => {
?.data.toString();
const presentationConfig = JSON.parse(plainPresentationConfig ?? "{}");
- return { presentationConfig, presentationFileContent, presentationPath };
+ const presentationStyle = files
+ .find((file) => file.path == "style.css")
+ ?.data.toString();
+
+ return { presentationConfig, presentationFileContent, presentationPath, presentationStyle };
};
-export const deleteCodePrezTempFolder = () => {
+export const deleteCodePrezTempFolder = async () => {
const presentationPath = path.join(tempPath, "codeprez");
- fs.rmdir(presentationPath, (err) => {
- console.error(err);
- });
+ try {
+ fs.rmSync(presentationPath, { recursive: true });
+ } catch(e) {
+ console.error(e);
+ return;
+ }
};
diff --git a/src/preload/preload.ts b/src/preload/preload.ts
index 2b1c208..e657dc8 100644
--- a/src/preload/preload.ts
+++ b/src/preload/preload.ts
@@ -12,6 +12,8 @@ export interface CreationCodePrezProps {
export type ContextBridgeApi = {
getPresentationData: (setPresentationData: Function) => void,
+ setAppToFullScreen: () => void,
+ setAppToMaximized: () => void,
sendExecuteCommand: (command: string) => void,
openFileDialog: (type: "md" | "css" | "env" | "assets", callback: Function) => null;
createCodePrez: ({ mdFilePath, cssFilePath, envDirectoryPath, assetsDirectoryPath, title, duration, authors }: CreationCodePrezProps) => null;
@@ -22,6 +24,12 @@ contextBridge.exposeInMainWorld("api", {
ipcRenderer.send("open-presentation", { type: "codeprez" });
ipcRenderer.once("set-codeprez-data", (event, data) => setPresentationData(data))
},
+ setAppToFullScreen: () => {
+ ipcRenderer.send("fullscreen-app")
+ },
+ setAppToMaximized: () => {
+ ipcRenderer.send("maximized-app")
+ },
sendExecuteCommand: (command: string) => {
ipcRenderer.send("execute-command", { command })
},
diff --git a/src/renderer/components/SlideShow.tsx b/src/renderer/components/SlideShow.tsx
new file mode 100644
index 0000000..24962a1
--- /dev/null
+++ b/src/renderer/components/SlideShow.tsx
@@ -0,0 +1,35 @@
+import { useState, useEffect } from "react";
+import { useLocation, useNavigate } from 'react-router-dom';
+import { Slide } from '../../components/Slide';
+import "../../assets/css/SlideViewer.css"
+
+type Props = {
+ config?: PresentationConfig,
+ content: string[],
+ style?: string,
+ slideScale: "slideViewer" | "preview" | "sidebar"
+}
+
+export const SlideShow = (props: Props) => {
+ const {config, content, style, slideScale} = props;
+
+ return (
+ <>
+ ' +
- hljs.highlight(str, {
- language: lang,
- ignoreIllegals: true,
- }).value +
- "
"
- );
- } catch (__) {}
- }
-
- return (
- '' +
- md.utils.escapeHtml(str) +
- "
"
- );
- },
- });
-}
+export {}
\ No newline at end of file
diff --git a/src/types.d.ts b/src/types.d.ts
index 2b96695..9c46e07 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -2,6 +2,7 @@ type PresentationData = {
presentationConfig: PresentationConfig;
presentationFileContent: string[] | string;
presentationPath: string;
+ presentationStyle: string;
};
type PresentationConfig = {
diff --git a/yarn.lock b/yarn.lock
index 8aa8581..d917b88 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2063,6 +2063,24 @@
dependencies:
"@types/node" "*"
+"@types/linkify-it@*":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9"
+ integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==
+
+"@types/markdown-it@^12.2.3":
+ version "12.2.3"
+ resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-12.2.3.tgz#0d6f6e5e413f8daaa26522904597be3d6cd93b51"
+ integrity sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==
+ dependencies:
+ "@types/linkify-it" "*"
+ "@types/mdurl" "*"
+
+"@types/mdurl@*":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
+ integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==
+
"@types/mime@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10"