Browse Source

Live markdown updates (as you type), removed render button/ctrl+enter.

gwillz 2 years ago
parent
commit
09389665c9
6 changed files with 21 additions and 42 deletions
  1. 0 1
      public/tutorial.md
  2. 2 9
      src/editor.tsx
  3. 6 3
      src/markdown.tsx
  4. 12 19
      src/presentation.tsx
  5. 1 0
      src/store.ts
  6. 0 10
      src/toolbar.tsx

+ 0 - 1
public/tutorial.md

@@ -168,7 +168,6 @@ like this: `https://dl.dropboxusercontent.com/s/.../filename.md?raw=1`.
 |------------|------------------------|
 | Ctrl+O     | Open file dialog       |
 | Ctrl+F1    | Start presentation     |
-| Ctrl+Enter | Render document        |
 | Ctrl+Home  | Scroll both views up   |
 | Ctrl+End   | Scroll both views down |
 | Ctrl+1     | Focus editor           |

+ 2 - 9
src/editor.tsx

@@ -8,9 +8,6 @@ import { State as Store, Action, ActionTypes } from './store';
 const TAB = "    ";
 
 function keyBinding(e: React.KeyboardEvent): string | null {
-    if (e.key == "Enter" && e.ctrlKey) {
-        return 'editor-render';
-    }
     if (e.key == "s" && e.ctrlKey) {
         e.preventDefault();
         return 'editor-save';
@@ -83,18 +80,14 @@ export class EditorView extends React.PureComponent<Props, State> {
             clearTimeout(this.timer);
             this.timer = setTimeout(() => {
                 this.props.dispatch({ type: 'EDIT', content });
-            }, 350);
+            }, 600);
         }
         
-        this.setState({ 
-            draft,
-            content,
-        });
+        this.setState({ draft, content });
     }
     
     private handleCommand = (command: string) => {
         switch (command) {
-            case 'editor-render':
             case 'editor-save':
             case 'editor-open':
                 return 'handled';

+ 6 - 3
src/markdown.tsx

@@ -6,7 +6,7 @@ import {store} from './store'
 
 type Props = {
     className?: string;
-    noScrollTo?: boolean;
+    scrollTo?: boolean;
     content: string;
 }
 
@@ -23,7 +23,10 @@ const markdown = new showdown.Converter({
 let PLUGINS_LOADED = false;
 
 ;(async function() {
-    const plugins = await import('./showdown-plugins' /* webpackChunkName: 'plugins' */);
+    const plugins = await import(
+        './showdown-plugins'
+        /* webpackChunkName: 'plugins' */
+    );
     
     plugins.default.forEach(plugin => {
         markdown.addExtension(plugin, plugin.name);
@@ -89,7 +92,7 @@ export class Markdown extends React.Component<Props> {
     // This will scroll to the last rendered slide. Although this
     // isn't be best behaviour, it's pretty close to what we want.
     componentDidUpdate() {
-        if (this.props.noScrollTo) return;
+        if (!this.props.scrollTo) return;
         
         clearTimeout(Markdown.last_rendered);
         Markdown.last_rendered = setTimeout(() => {

+ 12 - 19
src/presentation.tsx

@@ -8,10 +8,10 @@ import { connect, DispatchProp } from 'react-redux';
 const FILTER_NOTES = /\s*\[\/\/\]:\s*#\s*\(([^\n]+)\)/g;
 
 
-function recurseRegex(expr: RegExp, src: string, index = 0) {
+function bigRegex(expr: RegExp, src: string) {
     let result = [];
     while (true) {
-        let match = FILTER_NOTES.exec(src);
+        let match = expr.exec(src);
         if (!match) break;
         result.push(match[1]);
     }
@@ -27,16 +27,17 @@ type State = {
     slides: string[];
     notes: string[];
     active: number;
+    scrollTo: boolean;
 }
 
-export class PresentView extends React.Component<Props, State> {
+export class PresentView extends React.PureComponent<Props, State> {
     state: State = {
         slides: [],
         notes: [],
         active: 0,
+        scrollTo: false,
     }
     
-    private noScrollTo = true;
     private lastSelection = "";
     private element: HTMLElement | null;
     
@@ -64,10 +65,6 @@ export class PresentView extends React.Component<Props, State> {
                 this.doRender();
                 break;
                 
-            case "Enter":
-                this.doRender();
-                break;
-                
             case '2': 
                 this.element && this.element.focus();
                 break;
@@ -93,15 +90,15 @@ export class PresentView extends React.Component<Props, State> {
         }
     }
     
-    public doRender() {
+    public doRender(scrollTo = false) {
         const slides = this.props.content.split(/\n\s*---+\s*\n/);
         const notes = slides.map(slide => (
-            recurseRegex(FILTER_NOTES, slide, 1)
+            bigRegex(FILTER_NOTES, slide)
             .map(note => " + " + note)
             .join('\n')
         ));
         
-        this.setState({ slides, notes });
+        this.setState({ slides, notes, scrollTo });
     }
     
     public goFullscreen() {
@@ -140,22 +137,19 @@ export class PresentView extends React.Component<Props, State> {
         if (props.action === this.props.action) return;
         switch (this.props.action) {
             case "FULLSCREEN":
-                this.noScrollTo = true;
                 this.goFullscreen();
-                this.doRender();
                 this.props.dispatch({type: 'ACK'});
                 break;
                 
-                case "RENDER":
-                this.noScrollTo = false;
-                this.doRender();
+            case "RENDER":
+            case "EDIT":
+                this.doRender(true);
                 this.props.dispatch({type: 'ACK'});
                 break;
                 
             case "OPEN":
             case "LOAD":
                 if (props.content === this.props.content) return;
-                this.noScrollTo = true;
                 this.doRender();
                 break;
         }
@@ -184,12 +178,11 @@ export class PresentView extends React.Component<Props, State> {
                         active: i == this.state.active,
                     })}>
                         <Markdown
-                            noScrollTo={this.noScrollTo}
+                            scrollTo={this.state.scrollTo}
                             content={slide}
                         />
                     </div>
                     <Markdown
-                        noScrollTo
                         className={styles('notes')}
                         content={this.state.notes[i]}
                     />

+ 1 - 0
src/store.ts

@@ -120,6 +120,7 @@ function reducer(state = INIT_STATE, action: Action) {
         case "EDIT":
             return {
                 ...state,
+                action: action.type,
                 content: action.content,
                 files: state.currentFile ? {
                     ...state.files,

+ 0 - 10
src/toolbar.tsx

@@ -30,10 +30,6 @@ export class Toolbar extends React.PureComponent<Props> {
         });
     }
     
-    handlePreview = () => {
-        this.props.dispatch({type: "RENDER"});
-    }
-    
     handlePresent = () => {
         this.props.dispatch({type: "FULLSCREEN"});
     }
@@ -51,7 +47,6 @@ export class Toolbar extends React.PureComponent<Props> {
     }
     
     handlePrint = () => {
-        this.props.dispatch({type: "RENDER"});
         setTimeout(() => window.print(), 250);
     }
     
@@ -84,11 +79,6 @@ export class Toolbar extends React.PureComponent<Props> {
                 />
                 <div className={styles('toolbar-line')}/>
                 <Button 
-                    icon="play"
-                    title="Render Preview (Ctrl+Enter)"
-                    onClick={this.handlePreview}
-                />
-                <Button 
                     icon="print"
                     title="Print with notes (Ctrl+P)"
                     onClick={this.handlePrint}