Skip to content

Commit

Permalink
Markdown preview (#224)
Browse files Browse the repository at this point in the history
  • Loading branch information
thomiceli committed Apr 2, 2024
1 parent 2bf0e9b commit fc9a75c
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 3 deletions.
1 change: 1 addition & 0 deletions internal/i18n/locales/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ gist.new.add-file: Add file
gist.new.create-public-button: Create public gist
gist.new.create-unlisted-button: Create unlisted gist
gist.new.create-private-button: Create private gist
gist.new.preview: Preview

gist.edit.editing: Editing
gist.edit.change-visibility: Make
Expand Down
6 changes: 6 additions & 0 deletions internal/render/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ func MarkdownFile(file *git.File) (RenderedFile, error) {
Type: "Markdown",
}, err
}
func MarkdownString(content string) (string, error) {
var buf bytes.Buffer
err := newMarkdown().Convert([]byte(content), &buf)

return buf.String(), err
}

func newMarkdown() goldmark.Markdown {
return goldmark.New(
Expand Down
2 changes: 1 addition & 1 deletion internal/utils/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func validateReservedKeywords(fl validator.FieldLevel) bool {
name := fl.Field().String()

restrictedNames := map[string]struct{}{}
for _, restrictedName := range []string{"assets", "register", "login", "logout", "settings", "admin-panel", "all", "search", "init", "healthcheck"} {
for _, restrictedName := range []string{"assets", "register", "login", "logout", "settings", "admin-panel", "all", "search", "init", "healthcheck", "preview"} {
restrictedNames[restrictedName] = struct{}{}
}

Expand Down
11 changes: 11 additions & 0 deletions internal/web/gist.go
Original file line number Diff line number Diff line change
Expand Up @@ -890,3 +890,14 @@ func checkbox(ctx echo.Context) error {

return plainText(ctx, 200, "ok")
}

func preview(ctx echo.Context) error {
content := ctx.FormValue("content")

previewStr, err := render.MarkdownString(content)
if err != nil {
return errorRes(500, "Error rendering markdown", err)
}

return plainText(ctx, 200, previewStr)
}
1 change: 1 addition & 0 deletions internal/web/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ func NewServer(isDev bool) *Server {

g1.GET("/", create, logged)
g1.POST("/", processCreate, logged)
g1.GET("/preview", preview, logged)

g1.GET("/healthcheck", healthcheck)

Expand Down
39 changes: 39 additions & 0 deletions public/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,45 @@ document.addEventListener("DOMContentLoaded", () => {
],
});

let mdpreview = dom.querySelector(".md-preview") as HTMLElement;

// event if the filename ends with .md; trigger event
dom.querySelector<HTMLInputElement>(".form-filename")!.onkeyup = (e) => {
let filename = (e.target as HTMLInputElement).value;
if (filename.endsWith(".md")) {
mdpreview!.classList.remove("hidden");
} else {
mdpreview!.classList.add("hidden");
}
};

// @ts-ignore
const baseUrl = window.opengist_base_url || '';
let previewShown = false;
mdpreview.onclick = () => {
previewShown = !previewShown;
let divpreview = dom.querySelector("div.preview") as HTMLElement;
let cmeditor = dom.querySelector(".cm-editor") as HTMLElement;

if (!previewShown) {
divpreview!.classList.add("hidden");
cmeditor!.classList.remove("hidden-important");
return;
} else {
fetch(`${baseUrl}/preview?` + new URLSearchParams({
content: editor.state.doc.toString()
}), {
method: 'GET',
credentials: 'same-origin',
}).then(r => r.text()).then(r => {
let divpreview = dom.querySelector("div.preview") as HTMLElement;
divpreview!.innerHTML = r;
divpreview!.classList.remove("hidden");
cmeditor!.classList.add("hidden-important");
})
}
}

dom.querySelector<HTMLInputElement>(".editor-indent-type")!.onchange = (e) => {
let newTabType = (e.target as HTMLInputElement).value;
setIndentType(editor, !["tab", "space"].includes(newTabType) ? "space" : newTabType);
Expand Down
4 changes: 4 additions & 0 deletions public/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,7 @@ dl.dl-config dd {
.mermaid {
background: #f6f8fa !important;
}

.hidden-important {
@apply hidden !important;
}
4 changes: 3 additions & 1 deletion templates/pages/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ <h1 class="text-2xl font-bold leading-tight text-slate-700 dark:text-slate-300">
<div class="rounded-md border border-1 border-gray-200 dark:border-gray-700 editor">
<div class="border-b-1 border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 my-auto flex">
<p class="mx-2 my-2 inline-flex">
<input type="text" name="name" placeholder="{{ .locale.Tr "gist.new.filename-with-extension" }}" style="line-height: 0.05em" class="form-filename bg-white dark:bg-gray-900 shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-200 dark:border-gray-700 rounded-md">
<input type="text" name="name" placeholder="{{ .locale.Tr "gist.new.filename-with-extension" }}" style="line-height: 0.05em" class="form-filename bg-white dark:bg-gray-900 shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-200 dark:border-gray-700 rounded-md gist-title">
</p>
<button type="button" class="md-preview hidden whitespace-nowrap text-slate-700 dark:text-slate-300 rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-900 my-2 px-2 text-xs font-medium shadow-sm hover:bg-gray-200 dark:hover:bg-gray-700 hover:border-gray-500 hover:text-slate-700 dark:hover:text-slate-300 focus:outline-none focus:ring-1 focus:border-primary-500 focus:ring-primary-500">{{ .locale.Tr "gist.new.preview" }}</button>
<div class="hidden mx-2 my-2 sm:inline-flex ml-auto space-x-2">
<select class="editor-indent-type whitespace-nowrap text-slate-700 dark:text-slate-300 rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-900 pr-8 text-xs font-medium shadow-sm hover:bg-gray-200 dark:hover:bg-gray-700 hover:border-gray-500 hover:text-slate-700 dark:hover:text-slate-300 focus:outline-none focus:ring-1 focus:border-primary-500 focus:ring-primary-500">
<optgroup label="{{ .locale.Tr "gist.new.indent-mode" }}">
Expand All @@ -56,6 +57,7 @@ <h1 class="text-2xl font-bold leading-tight text-slate-700 dark:text-slate-300">
</div>
</div>
<input type="hidden" value="" name="content" class="form-filecontent" autocomplete="off">
<div class="hidden preview chroma markdown markdown-body p-8"></div>
</div>
</div>

Expand Down
4 changes: 3 additions & 1 deletion templates/pages/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ <h1 class="text-2xl font-bold leading-tight text-slate-700 dark:text-slate-300">
<div class="rounded-md border border-1 border-gray-200 dark:border-gray-700 editor">
<div class="border-b-1 border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 my-auto flex">
<p class="mx-2 my-2 inline-flex">
<input type="text" value="{{ $file.Filename }}" name="name" placeholder="Filename with extension" style="line-height: 0.05em; z-index: 99999" class="form-filename bg-white dark:bg-gray-900 shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-200 dark:border-gray-700 rounded-l-md">
<input type="text" value="{{ $file.Filename }}" name="name" placeholder="Filename with extension" style="line-height: 0.05em; z-index: 99999" class="form-filename bg-white dark:bg-gray-900 shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-200 dark:border-gray-700 rounded-l-md gist-title">
<button style="line-height: 0.05em" class="delete-file -ml-px relative inline-flex items-center space-x-2 px-4 py-2 border border-gray-200 dark:border-gray-700 text-sm font-medium rounded-r-md text-slate-700 dark:text-slate-300 bg-gray-50 dark:bg-gray-800 hover:bg-white dark:hover:bg-gray-900 focus:outline-none" type="button">
<svg xmlns="http:https://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
</p>
<button type="button" class="md-preview hidden whitespace-nowrap text-slate-700 dark:text-slate-300 rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-900 my-2 px-2 text-xs font-medium shadow-sm hover:bg-gray-200 dark:hover:bg-gray-700 hover:border-gray-500 hover:text-slate-700 dark:hover:text-slate-300 focus:outline-none focus:ring-1 focus:border-primary-500 focus:ring-primary-500">{{ $.locale.Tr "gist.new.preview" }}</button>
<div class="hidden mx-2 my-2 sm:inline-flex ml-auto space-x-2">
<select class="editor-indent-type whitespace-nowrap text-slate-700 dark:text-slate-300 rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-900 pr-8 text-xs font-medium shadow-sm hover:bg-gray-200 dark:hover:bg-gray-700 hover:border-gray-500 hover:text-slate-700 dark:hover:text-slate-300 focus:outline-none focus:ring-1 focus:border-primary-500 focus:ring-primary-500">
<optgroup label="{{ $.locale.Tr "gist.new.indent-mode" }}">
Expand All @@ -91,6 +92,7 @@ <h1 class="text-2xl font-bold leading-tight text-slate-700 dark:text-slate-300">
</div>
</div>
<input type="hidden" value="{{ $file.Content }}" name="content" class="form-filecontent" autocomplete="off">
<div class="hidden preview chroma markdown markdown-body p-8"></div>
</div>
{{ end }}
</div>
Expand Down

0 comments on commit fc9a75c

Please sign in to comment.