Merge pull request #443 from writefreely/minor-fixes

Minor WYSIWYG and miscellaneous fixes
This commit is contained in:
Matt Baer 2021-04-30 11:31:06 -04:00 committed by GitHub
commit 895e04c8c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 95 additions and 51 deletions

View File

@ -822,7 +822,7 @@ func viewEditCollection(app *App, u *User, w http.ResponseWriter, r *http.Reques
} }
// Add collection properties // Add collection properties
c.MonetizationPointer = app.db.GetCollectionAttribute(c.ID, "monetization_pointer") c.Monetization = app.db.GetCollectionAttribute(c.ID, "monetization_pointer")
silenced, err := app.db.IsUserSilenced(u.ID) silenced, err := app.db.IsUserSilenced(u.ID)
if err != nil { if err != nil {

View File

@ -57,7 +57,7 @@ type (
PublicOwner bool `datastore:"public_owner" json:"-"` PublicOwner bool `datastore:"public_owner" json:"-"`
URL string `json:"url,omitempty"` URL string `json:"url,omitempty"`
MonetizationPointer string `json:"monetization_pointer,omitempty"` Monetization string `json:"monetization_pointer,omitempty"`
db *datastore db *datastore
hostName string hostName string

View File

@ -1,3 +1,5 @@
@classicHorizMargin: 2rem;
body#pad.classic { body#pad.classic {
header { header {
display: flex; display: flex;
@ -6,6 +8,7 @@ body#pad.classic {
} }
#editor { #editor {
top: 4em; top: 4em;
bottom: 1em;
} }
#title { #title {
top: 4.25rem; top: 4.25rem;
@ -13,8 +16,7 @@ body#pad.classic {
height: auto; height: auto;
font-weight: bold; font-weight: bold;
font-size: 2em; font-size: 2em;
padding-top: 0; padding: 0;
padding-bottom: 0;
border: 0; border: 0;
} }
#tools { #tools {
@ -31,6 +33,11 @@ body#pad.classic {
} }
} }
#title {
margin-left: @classicHorizMargin;
margin-right: @classicHorizMargin;
}
.ProseMirror { .ProseMirror {
position: relative; position: relative;
height: calc(~"100% - 1.6em"); height: calc(~"100% - 1.6em");
@ -42,7 +49,7 @@ body#pad.classic {
white-space: pre-wrap; white-space: pre-wrap;
-webkit-font-variant-ligatures: none; -webkit-font-variant-ligatures: none;
font-variant-ligatures: none; font-variant-ligatures: none;
padding: 0.5em 0; padding: 0.5em @classicHorizMargin;
line-height: 1.5; line-height: 1.5;
outline: none; outline: none;
} }
@ -209,6 +216,7 @@ li.ProseMirror-selectednode:after {
} }
.ProseMirror-menubar { .ProseMirror-menubar {
font-family: @sansFont;
position: relative; position: relative;
min-height: 1em; min-height: 1em;
color: #666; color: #666;
@ -221,6 +229,8 @@ li.ProseMirror-selectednode:after {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
overflow: visible; overflow: visible;
margin-left: @classicHorizMargin;
margin-right: @classicHorizMargin;
} }
.ProseMirror-icon { .ProseMirror-icon {
@ -273,16 +283,17 @@ li.ProseMirror-selectednode:after {
/* Add space around the hr to make clicking it easier */ /* Add space around the hr to make clicking it easier */
.ProseMirror-example-setup-style hr { .ProseMirror-example-setup-style hr {
padding: 2px 10px; padding: 4px 10px;
border: none; border: none;
margin: 1em 0; margin: 1em 0;
background: initial;
} }
.ProseMirror-example-setup-style hr:after { .ProseMirror-example-setup-style hr:after {
content: ""; content: "";
display: block; display: block;
height: 1px; height: 1px;
background-color: silver; background-color: #ccc;
line-height: 2px; line-height: 2px;
} }
@ -292,13 +303,15 @@ li.ProseMirror-selectednode:after {
.ProseMirror blockquote { .ProseMirror blockquote {
padding-left: 1em; padding-left: 1em;
border-left: 3px solid #eee; border-left: 4px solid #ddd;
color: #767676;
margin-left: 0; margin-left: 0;
margin-right: 0; margin-right: 0;
} }
.ProseMirror-example-setup-style img { .ProseMirror-example-setup-style img {
cursor: default; cursor: default;
max-width: 100%;
} }
.ProseMirror-prompt { .ProseMirror-prompt {
@ -370,6 +383,10 @@ li.ProseMirror-selectednode:after {
margin: 4em auto 23px auto; margin: 4em auto 23px auto;
} }
.dark #editor {
color: white;
}
.ProseMirror p:first-child, .ProseMirror p:first-child,
.ProseMirror h1:first-child, .ProseMirror h1:first-child,
.ProseMirror h2:first-child, .ProseMirror h2:first-child,
@ -415,36 +432,59 @@ textarea {
} }
@media all and (min-width: 50em) { @media all and (min-width: 50em) {
#editor { #photo-upload label {
display: inline;
}
.ProseMirror-menubar, #title, #photo-upload {
margin-left: 10%; margin-left: 10%;
margin-right: 10%; margin-right: 10%;
} }
.ProseMirror {
padding-left: 10%;
padding-right: 10%;
}
} }
@media all and (min-width: 60em) { @media all and (min-width: 60em) {
#editor { .ProseMirror-menubar, #title, #photo-upload {
margin-left: 15%; margin-left: 15%;
margin-right: 15%; margin-right: 15%;
} }
.ProseMirror {
padding-left: 15%;
padding-right: 15%;
}
} }
@media all and (min-width: 70em) { @media all and (min-width: 70em) {
#editor { .ProseMirror-menubar, #title, #photo-upload {
margin-left: 20%; margin-left: 20%;
margin-right: 20%; margin-right: 20%;
} }
.ProseMirror {
padding-left: 20%;
padding-right: 20%;
}
} }
@media all and (min-width: 85em) { @media all and (min-width: 85em) {
#editor { .ProseMirror-menubar, #title, #photo-upload {
margin-left: 25%; margin-left: 25%;
margin-right: 25%; margin-right: 25%;
} }
.ProseMirror {
padding-left: 25%;
padding-right: 25%;
}
} }
@media all and (min-width: 105em) { @media all and (min-width: 105em) {
#editor { .ProseMirror-menubar, #title, #photo-upload {
margin-left: 30%; margin-left: 30%;
margin-right: 30%; margin-right: 30%;
} }
.ProseMirror {
padding-left: 30%;
padding-right: 30%;
}
} }

View File

@ -3,11 +3,11 @@ import markdownit from "markdown-it";
import { writeFreelySchema } from "./schema"; import { writeFreelySchema } from "./schema";
export const writeAsMarkdownParser = new MarkdownParser( export const writeFreelyMarkdownParser = new MarkdownParser(
writeFreelySchema, writeFreelySchema,
markdownit("commonmark", { html: true }), markdownit("commonmark", { html: true }),
{ {
// blockquote: { block: "blockquote" }, blockquote: { block: "blockquote" },
paragraph: { block: "paragraph" }, paragraph: { block: "paragraph" },
list_item: { block: "list_item" }, list_item: { block: "list_item" },
bullet_list: { block: "bullet_list" }, bullet_list: { block: "bullet_list" },
@ -25,13 +25,13 @@ export const writeAsMarkdownParser = new MarkdownParser(
getAttrs: (tok) => ({ params: tok.info || "" }), getAttrs: (tok) => ({ params: tok.info || "" }),
noCloseToken: true, noCloseToken: true,
}, },
// hr: { node: "horizontal_rule" }, hr: { node: "horizontal_rule" },
image: { image: {
node: "image", node: "image",
getAttrs: (tok) => ({ getAttrs: (tok) => ({
src: tok.attrGet("src"), src: tok.attrGet("src"),
title: tok.attrGet("title") || null, title: tok.attrGet("title") || null,
alt: tok.children?.[0].content || null, alt: (tok.children !== null && typeof tok.children[0] !== 'undefined' ? tok.children[0].content : null),
}), }),
}, },
hardbreak: { node: "hard_break" }, hardbreak: { node: "hard_break" },

View File

@ -26,15 +26,15 @@ function isPlainURL(link, parent, index, side) {
return !link.isInSet(next.marks); return !link.isInSet(next.marks);
} }
export const writeAsMarkdownSerializer = new MarkdownSerializer( export const writeFreelyMarkdownSerializer = new MarkdownSerializer(
{ {
readmore(state, node) { readmore(state, node) {
state.write("<!--more-->\n"); state.write("<!--more-->\n");
state.closeBlock(node); state.closeBlock(node);
}, },
// blockquote(state, node) { blockquote(state, node) {
// state.wrapBlock("> ", undefined, node, () => state.renderContent(node)); state.wrapBlock("> ", null, node, () => state.renderContent(node));
// }, },
code_block(state, node) { code_block(state, node) {
state.write(`\`\`\`${node.attrs.params || ""}\n`); state.write(`\`\`\`${node.attrs.params || ""}\n`);
state.text(node.textContent, false); state.text(node.textContent, false);
@ -47,7 +47,12 @@ export const writeAsMarkdownSerializer = new MarkdownSerializer(
state.renderInline(node); state.renderInline(node);
state.closeBlock(node); state.closeBlock(node);
}, },
horizontal_rule: function horizontal_rule(state, node) {
state.write(node.attrs.markup || "---");
state.closeBlock(node);
},
bullet_list(state, node) { bullet_list(state, node) {
node.attrs.tight = true;
state.renderList(node, " ", () => `${node.attrs.bullet || "*"} `); state.renderList(node, " ", () => `${node.attrs.bullet || "*"} `);
}, },
ordered_list(state, node) { ordered_list(state, node) {

View File

@ -7,9 +7,9 @@
"babel-core": "^6.26.3", "babel-core": "^6.26.3",
"babel-preset-es2015": "^6.24.1", "babel-preset-es2015": "^6.24.1",
"markdown-it": "^12.0.4", "markdown-it": "^12.0.4",
"prosemirror-example-setup": "^1.1.2", "prosemirror-example-setup": "github:writefreely/prosemirror-example-setup",
"prosemirror-keymap": "^1.1.4", "prosemirror-keymap": "^1.1.4",
"prosemirror-markdown": "github:VV-EE/prosemirror-markdown", "prosemirror-markdown": "github:writefreely/prosemirror-markdown",
"prosemirror-model": "^1.9.1", "prosemirror-model": "^1.9.1",
"prosemirror-state": "^1.3.2", "prosemirror-state": "^1.3.2",
"prosemirror-view": "^1.14.2", "prosemirror-view": "^1.14.2",

View File

@ -14,8 +14,8 @@ import { EditorState, TextSelection } from "prosemirror-state";
import { exampleSetup } from "prosemirror-example-setup"; import { exampleSetup } from "prosemirror-example-setup";
import { keymap } from "prosemirror-keymap"; import { keymap } from "prosemirror-keymap";
import { writeAsMarkdownParser } from "./markdownParser"; import { writeFreelyMarkdownParser } from "./markdownParser";
import { writeAsMarkdownSerializer } from "./markdownSerializer"; import { writeFreelyMarkdownSerializer } from "./markdownSerializer";
import { writeFreelySchema } from "./schema"; import { writeFreelySchema } from "./schema";
import { getMenu } from "./menu"; import { getMenu } from "./menu";
@ -40,7 +40,7 @@ class ProseMirrorView {
$title.value = title; $title.value = title;
} }
const doc = writeAsMarkdownParser.parse( const doc = writeFreelyMarkdownParser.parse(
// Replace all "solo" \n's with \\\n for correct markdown parsing // Replace all "solo" \n's with \\\n for correct markdown parsing
// Can't use lookahead or lookbehind because it's not supported on Safari // Can't use lookahead or lookbehind because it's not supported on Safari
content.replace(/([^]{0,1})(\n)([^]{0,1})/g, (match, p1, p2, p3) => { content.replace(/([^]{0,1})(\n)([^]{0,1})/g, (match, p1, p2, p3) => {
@ -73,7 +73,7 @@ class ProseMirrorView {
}), }),
dispatchTransaction(transaction) { dispatchTransaction(transaction) {
let newState = this.state.apply(transaction); let newState = this.state.apply(transaction);
const newContent = writeAsMarkdownSerializer const newContent = writeFreelyMarkdownSerializer
.serialize(newState.doc) .serialize(newState.doc)
// Replace all \\\ns ( not followed by a \n ) with \n // Replace all \\\ns ( not followed by a \n ) with \n
.replace(/(\\\n)(\n{0,1})/g, (match, p1, p2) => .replace(/(\\\n)(\n{0,1})/g, (match, p1, p2) =>
@ -104,7 +104,7 @@ class ProseMirrorView {
} }
get content() { get content() {
return defaultMarkdownSerializer.serialize(this.view.state.doc); return writeFreelyMarkdownSerializer.serialize(this.view.state.doc);
} }
focus() { focus() {
this.view.focus(); this.view.focus();

View File

@ -3,8 +3,6 @@ import { Schema } from "prosemirror-model";
export const writeFreelySchema = new Schema({ export const writeFreelySchema = new Schema({
nodes: schema.spec.nodes nodes: schema.spec.nodes
.remove("blockquote")
.remove("horizontal_rule")
.addToEnd("readmore", { .addToEnd("readmore", {
inline: false, inline: false,
content: "", content: "",

View File

@ -41,6 +41,9 @@ func (app *App) InitSession() {
HttpOnly: true, HttpOnly: true,
Secure: strings.HasPrefix(app.cfg.App.Host, "https://"), Secure: strings.HasPrefix(app.cfg.App.Host, "https://"),
} }
if store.Options.Secure {
store.Options.SameSite = http.SameSiteNoneMode
}
app.sessionStore = store app.sessionStore = store
} }

1
static/js/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
prose.bundle.js

File diff suppressed because one or more lines are too long

View File

@ -105,15 +105,12 @@
$btnPublish.el.disabled = true; $btnPublish.el.disabled = true;
var http = new XMLHttpRequest(); var http = new XMLHttpRequest();
var lang = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
lang = lang.substring(0, 2);
var post = H.getTitleStrict(content); var post = H.getTitleStrict(content);
var params = { var params = {
body: post.content, body: post.content,
title: post.title, title: post.title,
font: font, font: font
lang: lang
}; };
{{ if .Post.Slug }} {{ if .Post.Slug }}
var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}"; var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}";
@ -124,6 +121,10 @@
} }
params.token = token; params.token = token;
{{ else }} {{ else }}
var lang = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
lang = lang.substring(0, 2);
params.lang = lang;
var url = "/api/posts"; var url = "/api/posts";
var postTarget = '{{if .Blogs}}{{$c := index .Blogs 0}}{{$c.Alias}}{{else}}anonymous{{end}}'; var postTarget = '{{if .Blogs}}{{$c := index .Blogs 0}}{{$c.Alias}}{{else}}anonymous{{end}}';
if (postTarget != 'anonymous') { if (postTarget != 'anonymous') {

View File

@ -82,7 +82,7 @@
btns[i].src = btns[i].src.replace('_dark@2x.png', '@2x.png'); btns[i].src = btns[i].src.replace('_dark@2x.png', '@2x.png');
} }
} else { } else {
TextnewTheme = 'light'; newTheme = 'light';
document.body.className = document.body.className.replace(/(?:^|\s)dark(?!\S)/g, newTheme); document.body.className = document.body.className.replace(/(?:^|\s)dark(?!\S)/g, newTheme);
for (var i=0; i<btns.length; i++) { for (var i=0; i<btns.length; i++) {
btns[i].src = btns[i].src.replace('@2x.png', '_dark@2x.png'); btns[i].src = btns[i].src.replace('@2x.png', '_dark@2x.png');
@ -168,15 +168,12 @@
var xpostTarg = H.get('crosspostTarget', '[]'); var xpostTarg = H.get('crosspostTarget', '[]');
var http = new XMLHttpRequest(); var http = new XMLHttpRequest();
var lang = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
lang = lang.substring(0, 2);
var post = H.getTitleStrict(content); var post = H.getTitleStrict(content);
var params = { var params = {
body: post.content, body: post.content,
title: title, title: title,
font: font, font: font
lang: lang
}; };
{{ if .Post.Slug }} {{ if .Post.Slug }}
var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}"; var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}";
@ -187,6 +184,10 @@
} }
params.token = token; params.token = token;
{{ else }} {{ else }}
var lang = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
lang = lang.substring(0, 2);
params.lang = lang;
var url = "/api/posts"; var url = "/api/posts";
var postTarget = H.get('postTarget', 'anonymous'); var postTarget = H.get('postTarget', 'anonymous');
if (postTarget != 'anonymous') { if (postTarget != 'anonymous') {

View File

@ -186,21 +186,14 @@
var xpostTarg = H.get('crosspostTarget', '[]'); var xpostTarg = H.get('crosspostTarget', '[]');
var http = new XMLHttpRequest(); var http = new XMLHttpRequest();
var lang = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
lang = lang.substring(0, 2);
var post = H.getTitleStrict(content); var post = H.getTitleStrict(content);
var params = { var params = {
body: post.content, body: post.content,
title: post.title, title: post.title,
font: font, font: font
{{ if or .Post.Slug .Post.Id }} };
};
{{ else }}
lang: lang
};
{{ end }}
{{ if .Post.Slug }} {{ if .Post.Slug }}
var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}"; var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}";
{{ else if .Post.Id }} {{ else if .Post.Id }}
@ -210,6 +203,10 @@
} }
params.token = token; params.token = token;
{{ else }} {{ else }}
var lang = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
lang = lang.substring(0, 2);
params.lang = lang;
var url = "/api/posts"; var url = "/api/posts";
var postTarget = H.get('postTarget', 'anonymous'); var postTarget = H.get('postTarget', 'anonymous');
if (postTarget != 'anonymous') { if (postTarget != 'anonymous') {