From cf66b5a48dc63467e2be51343281057d5deea3d9 Mon Sep 17 00:00:00 2001 From: Igor Shymko Date: Sun, 14 Sep 2014 15:39:16 +0300 Subject: [PATCH] deliver markdown to browser over websockets --- README.md | 6 ++++ markdown-preview-mode.el | 65 +++++++++++++++++++++++++--------------- preview.html | 40 ++++++++++++++----------- style.css | 1 + 4 files changed, 70 insertions(+), 42 deletions(-) create mode 100644 style.css diff --git a/README.md b/README.md index 2a90868..634e20f 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,9 @@ Depends on: * markdown-mode * websocket.el + +table header 1 | header 2 | head 3 +--------------|---------|------ +cell1 | cell2 | cell3 +cell1 | cell2 | cell3 +cell1 | cell2 | [cell3](#asdfsadf) diff --git a/markdown-preview-mode.el b/markdown-preview-mode.el index 869619d..4facd85 100644 --- a/markdown-preview-mode.el +++ b/markdown-preview-mode.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2014 -;; Author: Kostafey +;; Author: Igor Shymko ;; URL: https://github.com/ancane/markdown-preview-mode ;; Keywords: markdown, preview ;; Package-Requires: ((websocket "1.3")) @@ -34,10 +34,20 @@ (defvar mdpm:websocket-port 7379) (defvar mdpm:websocket-server nil) -(defvar mdpm:websocket-clients nil) +(defvar mdpm:local-client nil) +(defvar mdpm:remote-clients nil) (defvar mdpm:directory (file-name-directory load-file-name)) -;; (setq mdpm:websocket-server (get-process "websocket server on port 7379")) +(defun mdpm:open-browser-preview () + (browse-url (concat mdpm:directory "preview.html"))) + +(defun mdpm:stop-websocket-server () + (when mdpm:local-client + (websocket-close mdpm:local-client)) + (when mdpm:websocket-server + (delete-process mdpm:websocket-server) + (setq mdpm:websocket-server nil + mdpm:remote-clients nil))) (defun mdpm:start-websocket-server () (when (not mdpm:websocket-server) @@ -46,39 +56,46 @@ mdpm:websocket-port :on-message (lambda (websocket frame) (mapc (lambda (ws) - ;; send frame only if ws != websocket - (websocket-send-text - ws - (websocket-frame-payload frame)))) - mdpm:websocket-clients) + (websocket-send-text ws + (websocket-frame-payload frame))) + mdpm:remote-clients)) :on-open (lambda (websocket) - (push websocket mdpm:websocket-clients)) + (push websocket mdpm:remote-clients) + ) :on-close (lambda (websocket) - (delete websocket mdpm:websocket-clients))))) - (add-hook 'kill-emacs-hook 'mdpm:stop-websocket-server) - (mdpm:open-browser)) + (delete websocket mdpm:remote-clients) + ) + )) + (add-hook 'kill-emacs-hook 'mdpm:stop-websocket-server) + (mdpm:open-browser-preview))) -(defun mdpm:open-browser () - (browse-url (concat mdpm:directory "preview.html"))) +(defun mdpm:start-local-client () + (when (not mdpm:local-client) + (setq mdpm:local-client + (websocket-open + (format "ws://localhost:%d" mdpm:websocket-port) + :on-error (lambda (ws type err) + (message "error connecting")) + :on-close (lambda (websocket) + (setq mdpm:local-client nil)))))) -(defun mdpm:stop-websocket-server () - (when mdpm:websocket-server - (delete-process mdpm:websocket-server) - (setq mdpm:websocket-server nil - mdpm:websocket-clients nil))) - -(defun mdpm:send ()) +(defun mdpm:send-preview () + (markdown markdown-output-buffer-name) + (with-current-buffer (get-buffer markdown-output-buffer-name) + (websocket-send-text mdpm:local-client (buffer-substring-no-properties (point-min) (point-max)))) + ) (defun mdpm:start () (mdpm:start-websocket-server) - (add-hook 'after-save-hook 'mdpm:send nil t)) + (mdpm:start-local-client) + (add-hook 'after-save-hook 'mdpm:send-preview nil t)) (defun mdpm:stop () - (remove-hook 'after-save-hook 'mdpm:send)) + (remove-hook 'after-save-hook 'mdpm:send-preview)) (defun markdown-preview-open-browser () (interactive) - (mdpm:open-browser)) + (mdpm:open-browser-preview)) (defun markdown-preview-kill-websocket-server () (interactive) diff --git a/preview.html b/preview.html index a58d33b..0a3eb8f 100644 --- a/preview.html +++ b/preview.html @@ -4,25 +4,29 @@ Markdown preview + + diff --git a/style.css b/style.css new file mode 100644 index 0000000..3401a5a --- /dev/null +++ b/style.css @@ -0,0 +1 @@ +article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary {display: block;}audio,canvas,video {display: inline-block;}audio:not([controls]) {display: none;height: 0;}[hidden] {display: none;}html {font-family: sans-serif;-webkit-text-size-adjust: 100%;-ms-text-size-adjust: 100%;}body {margin: 0;}a:focus {outline: thin dotted;}a:active,a:hover {outline: 0;}h1 {font-size: 2em;}abbr[title] {border-bottom: 1px dotted;}b,strong {font-weight: bold;}dfn {font-style: italic;}mark {background: #ff0;color: #000;}code,kbd,pre,samp {font-family: monospace, serif;font-size: 1em;}pre {white-space: pre-wrap;word-wrap: break-word;}q {quotes: "\201C" "\201D" "\2018" "\2019";}small {font-size: 80%;}sub,sup {font-size: 75%;line-height: 0;position: relative;vertical-align: baseline;}sup {top: -0.5em;}sub {bottom: -0.25em;}img {border: 0;}svg:not(:root) {overflow: hidden;}figure {margin: 0;}fieldset {border: 1px solid #c0c0c0;margin: 0 2px;padding: 0.35em 0.625em 0.75em;}legend {border: 0;padding: 0;}button,input,select,textarea {font-family: inherit;font-size: 100%;margin: 0;}button,input {line-height: normal;}button,html input[type="button"],input[type="reset"],input[type="submit"] {-webkit-appearance: button;cursor: pointer;}button[disabled],input[disabled] {cursor: default;}input[type="checkbox"],input[type="radio"] {box-sizing: border-box;padding: 0;}input[type="search"] {-webkit-appearance: textfield;-moz-box-sizing: content-box;-webkit-box-sizing: content-box;box-sizing: content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration {-webkit-appearance: none;}button::-moz-focus-inner,input::-moz-focus-inner {border: 0;padding: 0;}textarea {overflow: auto;vertical-align: top;}table {border-collapse: collapse;border-spacing: 0;}@import url(//fonts.googleapis.com/css?family=Inconsolata);@import url(//fonts.googleapis.com/css?family=PT+Sans);@import url(//fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700);html {font-family: 'PT Sans', sans-serif;}pre,code {font-family: 'Inconsolata', sans-serif;}h1,h2,h3,h4,h5,h6 {font-family: 'PT Sans Narrow', sans-serif;font-weight: 700;}html {background-color: #002b36;color: #839496;margin: 1em;}code {background-color: #073642;padding: 2px;}a {color: #b58900;}a:visited {color: #cb4b16;}a:hover {color: #cb4b16;}h1 {color: #d33682;}h2,h3,h4,h5,h6 {color: #859900;}pre {background-color: #002b36;color: #839496;border: 1pt solid #586e75;padding: 1em;box-shadow: 5pt 5pt 8pt #073642;}pre code {background-color: #002b36;}h1 {font-size: 2.8em;}h2 {font-size: 2.4em;}h3 {font-size: 1.8em;}h4 {font-size: 1.4em;}h5 {font-size: 1.3em;}h6 {font-size: 1.15em;}.tag {background-color: #073642;color: #d33682;padding: 0 0.2em;}.todo,.next,.done {color: #002b36;background-color: #dc322f;padding: 0 0.2em;}.tag {-webkit-border-radius: 0.35em;-moz-border-radius: 0.35em;border-radius: 0.35em;}.TODO {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;background-color: #2aa198;}.NEXT {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;background-color: #268bd2;}.ACTIVE {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;background-color: #268bd2;}.DONE {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;background-color: #859900;}.WAITING {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;foreground-color: #cb4b16;}.HOLD {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;foreground-color: #d33682;}.NOTE {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;foreground-color: #d33682;}.CANCELLED {-webkit-border-radius: 0.2em;-moz-border-radius: 0.2em;border-radius: 0.2em;foreground-color: #859900;}