mirror of
https://github.com/discourse/discourse.git
synced 2025-03-01 19:32:13 +08:00

This is the first in a series of PRs to introduce a ProseMirror-based WYSIWYM editor experience alongside our current textarea Markdown editor. Behind a hidden site setting, this PR adds a toggle to the composer toolbar, allowing users to switch between the two options. Our implementation builds upon the excellent ProseMirror and its non-core Markdown module, using the module's schema, parsing, and serialization definitions as the base for further Discourse-specific features. An extension API is included to enable further customizations. The necessary extensions to support all Discourse's core and core plugins features **will be implemented in subsequent PRs**. --------- Co-authored-by: David Taylor <david@taylorhq.com>
257 lines
4.5 KiB
SCSS
257 lines
4.5 KiB
SCSS
.ProseMirror-container {
|
|
margin: 0;
|
|
overscroll-behavior: contain;
|
|
overflow-anchor: none;
|
|
flex-direction: column;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
display: flex;
|
|
height: 100%;
|
|
}
|
|
|
|
.ProseMirror {
|
|
outline: 0;
|
|
padding: 0 0.625rem;
|
|
|
|
> div:first-child,
|
|
> details:first-child {
|
|
// This is hacky, but helps having the leading gapcursor at the right position
|
|
&.ProseMirror-gapcursor {
|
|
position: relative;
|
|
display: block;
|
|
}
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
margin: 30px 0 10px;
|
|
|
|
&:first-child {
|
|
margin-top: 10px;
|
|
}
|
|
}
|
|
|
|
h1 {
|
|
font-size: var(--font-up-3-rem);
|
|
}
|
|
|
|
h2 {
|
|
font-size: var(--font-up-2-rem);
|
|
}
|
|
|
|
h3 {
|
|
font-size: var(--font-up-1-rem);
|
|
}
|
|
|
|
img {
|
|
display: inline-block;
|
|
height: auto;
|
|
max-width: 100%;
|
|
|
|
&[data-placeholder="true"] {
|
|
animation: placeholder 1.5s infinite;
|
|
|
|
@keyframes placeholder {
|
|
0% {
|
|
opacity: 0.6;
|
|
}
|
|
|
|
50% {
|
|
opacity: 0.4;
|
|
}
|
|
|
|
100% {
|
|
opacity: 0.6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ul,
|
|
ol {
|
|
padding-left: 1.25em;
|
|
|
|
&[data-tight="true"] > li > p {
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
|
|
p {
|
|
line-height: 1.5;
|
|
|
|
&:first-child {
|
|
margin-top: 0.59rem;
|
|
}
|
|
}
|
|
|
|
p[data-placeholder]::before {
|
|
pointer-events: none;
|
|
position: absolute;
|
|
padding-top: 2px;
|
|
padding-right: 0.5rem;
|
|
content: attr(data-placeholder);
|
|
color: var(--primary-400);
|
|
line-height: 1.1;
|
|
}
|
|
|
|
del {
|
|
background-color: var(--danger-low);
|
|
}
|
|
|
|
ins {
|
|
background-color: var(--success-low);
|
|
}
|
|
|
|
mark {
|
|
background-color: var(--highlight);
|
|
}
|
|
|
|
td {
|
|
padding: 3px 3px 3px 0.5em;
|
|
}
|
|
|
|
th {
|
|
padding-bottom: 2px;
|
|
font-weight: bold;
|
|
color: var(--primary);
|
|
}
|
|
|
|
kbd {
|
|
// I believe this shouldn't be `inline-flex` in posts either (test with emojis before/after text to see why),
|
|
// but overriding just for the editor for now
|
|
display: inline;
|
|
padding-top: 0.2rem;
|
|
}
|
|
|
|
.onebox-wrapper {
|
|
white-space: normal;
|
|
}
|
|
|
|
.code-block {
|
|
position: relative;
|
|
}
|
|
|
|
.code-language-select {
|
|
position: absolute;
|
|
right: 0.25rem;
|
|
top: -0.6rem;
|
|
border: 1px solid var(--primary-low);
|
|
border-radius: var(--d-border-radius);
|
|
background-color: var(--primary-very-low);
|
|
color: var(--primary-medium);
|
|
font-size: var(--font-down-1-rem);
|
|
}
|
|
|
|
.html-block {
|
|
position: relative;
|
|
border: 1px dashed var(--primary-low-mid);
|
|
|
|
&::after {
|
|
position: absolute;
|
|
right: 0;
|
|
top: 0;
|
|
content: "HTML";
|
|
font-size: var(--font-down-2-rem);
|
|
color: var(--primary-low-mid);
|
|
z-index: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************
|
|
Section below from prosemirror-view/style/prosemirror.css
|
|
********************************************************/
|
|
|
|
.ProseMirror {
|
|
position: relative;
|
|
}
|
|
|
|
.ProseMirror {
|
|
word-wrap: break-word;
|
|
white-space: break-spaces;
|
|
}
|
|
|
|
.ProseMirror pre {
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.ProseMirror li {
|
|
position: relative;
|
|
}
|
|
|
|
.ProseMirror-hideselection *::selection {
|
|
background: transparent;
|
|
}
|
|
|
|
.ProseMirror-hideselection {
|
|
caret-color: transparent;
|
|
}
|
|
|
|
/* See https://github.com/ProseMirror/prosemirror/issues/1421#issuecomment-1759320191 */
|
|
.ProseMirror [draggable][contenteditable="false"] {
|
|
user-select: text;
|
|
}
|
|
|
|
.ProseMirror-selectednode {
|
|
outline: 2px solid #8cf;
|
|
}
|
|
|
|
/* Make sure li selections wrap around markers */
|
|
li.ProseMirror-selectednode {
|
|
outline: none;
|
|
}
|
|
|
|
li.ProseMirror-selectednode::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: -32px;
|
|
right: -2px;
|
|
top: -2px;
|
|
bottom: -2px;
|
|
border: 2px solid #8cf;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Protect against generic img rules */
|
|
.ProseMirror-separator {
|
|
display: inline !important;
|
|
border: none !important;
|
|
margin: 0 !important;
|
|
}
|
|
|
|
/************************************************************
|
|
Section below from prosemirror-gapcursor/style/gapcursor.css
|
|
***********************************************************/
|
|
|
|
.ProseMirror-gapcursor {
|
|
display: none;
|
|
pointer-events: none;
|
|
position: absolute;
|
|
}
|
|
|
|
.ProseMirror-gapcursor::after {
|
|
content: "";
|
|
display: block;
|
|
position: absolute;
|
|
top: -2px;
|
|
width: 20px;
|
|
border-top: 1px solid var(--primary);
|
|
animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
|
|
}
|
|
|
|
@keyframes ProseMirror-cursor-blink {
|
|
to {
|
|
visibility: hidden;
|
|
}
|
|
}
|
|
|
|
.ProseMirror-focused .ProseMirror-gapcursor {
|
|
display: block;
|
|
}
|