mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-06-11 03:33:12 +08:00
docs: demos styling
This commit is contained in:
parent
171924ee49
commit
aba6657d70
@ -1,4 +1,23 @@
|
|||||||
$colorBlack: #000;
|
/* Base HTML and global element styles*/
|
||||||
|
:root {
|
||||||
|
--white: #FFF;
|
||||||
|
--black: #2E2B29;
|
||||||
|
--black-contrast: #110F0E;
|
||||||
|
--gray-1: rgba(61, 37, 20, 0.05);
|
||||||
|
--gray-2: rgba(61, 37, 20, 0.08);
|
||||||
|
--gray-3: rgba(61, 37, 20, 0.12);
|
||||||
|
--gray-4: rgba(53, 38, 28, 0.30);
|
||||||
|
--gray-5: rgba(28, 25, 23, 0.60);
|
||||||
|
--purple: #6A00F5;
|
||||||
|
--purple-contrast: #5800CC;
|
||||||
|
--purple-light: rgba(88, 5, 255, 0.05);
|
||||||
|
--yellow-contrast: #FACC15;
|
||||||
|
--yellow: rgba(250, 204, 21, 0.4);
|
||||||
|
--yellow-light: #FFFAE5;
|
||||||
|
--red: #FF5C33;
|
||||||
|
--red-light: #FFEBE5;
|
||||||
|
--shadow: 0px 12px 33px 0px rgba(0, 0, 0, 0.06), 0px 3.618px 9.949px 0px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
@ -9,32 +28,46 @@ $colorBlack: #000;
|
|||||||
html {
|
html {
|
||||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 1rem;
|
|
||||||
min-height: 10rem;
|
min-height: 10rem;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tiptap {
|
||||||
|
caret-color: var(--purple);
|
||||||
|
margin: 1.5rem;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbar styles */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
border: 4px solid transparent;
|
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
border-radius: 8px;
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
border: 4px solid rgba(0, 0, 0, 0);
|
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
border-radius: 8px;
|
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
border: 4px solid rgba(0, 0, 0, 0);
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:hover::-webkit-scrollbar-thumb {
|
:hover::-webkit-scrollbar-thumb {
|
||||||
@ -47,37 +80,276 @@ body {
|
|||||||
|
|
||||||
::-webkit-scrollbar-button {
|
::-webkit-scrollbar-button {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-corner {
|
::-webkit-scrollbar-corner {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specific element and component styles */
|
||||||
button,
|
button,
|
||||||
input,
|
input,
|
||||||
select {
|
select,
|
||||||
font-size: inherit;
|
textarea {
|
||||||
|
background: var(--gray-2);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border: none;
|
||||||
|
color: var(--black);
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
color: black;
|
font-size: 0.875rem;
|
||||||
margin: 0.1rem;
|
font-weight: 500;
|
||||||
border: 1px solid black;
|
line-height: 1.15;
|
||||||
border-radius: 0.3rem;
|
margin: none;
|
||||||
padding: 0.1rem 0.4rem;
|
padding: 0.375rem 0.625rem;
|
||||||
background: white;
|
transition: all 0.2s cubic-bezier(0.65,0.05,0.36,1);
|
||||||
accent-color: black;
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
color: var(--black-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
&[disabled] {
|
&[disabled] {
|
||||||
opacity: 0.3;
|
background: var(--gray-1);
|
||||||
|
color: var(--gray-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
accent-color: var(--purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background: var(--black);
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--black-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
background: var(--gray-1);
|
||||||
|
color: var(--gray-4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background: var(--purple);
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--purple-contrast);
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tiptap:focus {
|
button:not([disabled]),
|
||||||
outline: none;
|
select:not([disabled]) {
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-active {
|
input[type="text"],
|
||||||
background: black;
|
textarea {
|
||||||
color: white;
|
background-color: unset;
|
||||||
|
border: 1px solid var(--gray-3);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--black);
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--gray-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: unset;
|
||||||
|
border-color: var(--gray-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible, &:focus {
|
||||||
|
border-color: var(--purple);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
/* reset */
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="Gray" d="M7 10l5 5 5-5z"/></svg>');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right 0.1rem center;
|
||||||
|
background-size: 1.25rem 1.25rem;
|
||||||
|
padding-right: 1.25rem;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--yellow-light);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border: 1px solid var(--gray-2);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: 0.5rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
min-height: 1.75rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
|
||||||
|
&.purple-spinner,
|
||||||
|
&.error {
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.purple-spinner {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
background-image: url("data:image/svg+xml;utf8,<svg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='28px' height='30px' viewBox='0 0 24 30' style='enable-background:new 0 0 50 50;' xml:space='preserve'><rect x='0' y='10' width='6' height='10' fill='%236A00F5' rx='3' ry='3'><animateTransform attributeType='xml' attributeName='transform' type='translate' values='0 0; 0 5; 0 -5; 0 0' begin='0' dur='0.6s' repeatCount='indefinite'/></rect><rect x='10' y='10' width='6' height='10' fill='%236A00F5' rx='3' ry='3'><animateTransform attributeType='xml' attributeName='transform' type='translate' values='0 0; 0 5; 0 -5; 0 0' begin='0.2s' dur='0.6s' repeatCount='indefinite'/></rect><rect x='20' y='10' width='6' height='10' fill='%236A00F5' rx='3' ry='3'><animateTransform attributeType='xml' attributeName='transform' type='translate' values='0 0; 0 5; 0 -5; 0 0' begin='0.4s' dur='0.6s' repeatCount='indefinite'/></rect></svg>");
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
background-color: var(--red-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label,
|
||||||
|
.label-small,
|
||||||
|
.label-large {
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-small {
|
||||||
|
color: var(--gray-5);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-large {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-3);
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout and structure */
|
||||||
|
#app,
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
margin: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-node-view-wrapper] > .control-group {
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-group {
|
||||||
|
align-items: center;
|
||||||
|
background: var(--gray-2);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 0.125rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
color: var(--gray-5);
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
gap: 0.25rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
min-height: 1.5rem;
|
||||||
|
padding: 0 0.375rem;
|
||||||
|
transition: all 0.2s cubic-bezier(0.65,0.05,0.36,1);
|
||||||
|
|
||||||
|
&:has(input:checked) {
|
||||||
|
background-color: var(--white);
|
||||||
|
color: var(--black-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
display: none;
|
||||||
|
margin: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-group {
|
||||||
|
background-color: var(--gray-1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
}
|
}
|
@ -21,10 +21,12 @@ const MenuBar = ({ editor }) => {
|
|||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button onClick={onCutToStart}>Cut content to start of document</button>
|
<button onClick={onCutToStart}>Cut content to start of document</button>
|
||||||
<button onClick={onCutToEnd}>Cut content to end of document</button>
|
<button onClick={onCutToEnd}>Cut content to end of document</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +51,7 @@ export default () => {
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -77,9 +79,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -21,41 +21,41 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -64,40 +64,40 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -109,35 +109,35 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,17 +29,19 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button data-test-id="html-content" onClick={() => editor.chain().insertContent(htmlContent).focus().run()}>
|
<button data-test-id="html-content" onClick={() => editor.chain().insertContent(htmlContent).focus().run()}>
|
||||||
Insert html content
|
Insert HTML content
|
||||||
</button>
|
</button>
|
||||||
<button data-test-id="html-content-spans" onClick={() => editor.chain().insertContent('<p><b>Hello</b> <i>World</i></p>').focus().run()}>
|
<button data-test-id="html-content-spans" onClick={() => editor.chain().insertContent('<p><b>Hello</b> <i>World</i></p>').focus().run()}>
|
||||||
Insert html with span tags content
|
Insert HTML with span tags content
|
||||||
</button>
|
</button>
|
||||||
<button data-test-id="text-content" onClick={() => editor.chain().insertContent(textContent).focus().run()}>
|
<button data-test-id="text-content" onClick={() => editor.chain().insertContent(textContent).focus().run()}>
|
||||||
Insert text content
|
Insert text content
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,30 +14,27 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<label>
|
||||||
onClick={() => setUseInputRules(prev => !prev)}
|
<input
|
||||||
style={{
|
type="checkbox"
|
||||||
color: useInputRules ? 'white' : 'inherit',
|
checked={useInputRules}
|
||||||
backgroundColor: useInputRules ? 'black' : 'transparent',
|
onChange={() => setUseInputRules(prev => !prev)}
|
||||||
}}
|
/>
|
||||||
>
|
Apply input rules
|
||||||
Apply Input Rules
|
</label>
|
||||||
</button>
|
<label>
|
||||||
<button
|
<input
|
||||||
onClick={() => setUsePasteRules(prev => !prev)}
|
type="checkbox"
|
||||||
style={{
|
checked={usePasteRules}
|
||||||
color: usePasteRules ? 'white' : 'inherit',
|
onChange={() => setUsePasteRules(prev => !prev)}
|
||||||
backgroundColor: usePasteRules ? 'black' : 'transparent',
|
/>
|
||||||
}}
|
Apply paste rules
|
||||||
>
|
</label>
|
||||||
Apply Paste Rules
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<div className="button-group">
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
editor
|
editor
|
||||||
@ -161,7 +158,8 @@ const MenuBar = () => {
|
|||||||
>
|
>
|
||||||
Insert "*this is a test*"
|
Insert "*this is a test*"
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,22 +50,26 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button
|
<button
|
||||||
onClick={setLink}
|
onClick={setLink}
|
||||||
className={editor.isActive('link') ? 'is-active' : ''}
|
className={editor.isActive('link') ? 'is-active' : ''}
|
||||||
data-testid="setLink"
|
data-testid="setLink"
|
||||||
>
|
>
|
||||||
setLink
|
Set link
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().unsetLink().run()}
|
onClick={() => editor.chain().focus().unsetLink().run()}
|
||||||
disabled={!editor.isActive('link')}
|
disabled={!editor.isActive('link')}
|
||||||
data-testid="unsetLink"
|
data-testid="unsetLink"
|
||||||
>
|
>
|
||||||
unsetLink
|
Unset link
|
||||||
</button>
|
</button>
|
||||||
<EditorContent editor={editor} />
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<EditorContent editor={editor} />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,39 +24,78 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Link styles */
|
||||||
|
a {
|
||||||
|
color: var(--purple);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--purple-contrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,116 +12,118 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
className={editor.isActive('bold') ? 'is-active' : ''}
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
className={editor.isActive('italic') ? 'is-active' : ''}
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
className={editor.isActive('strike') ? 'is-active' : ''}
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
className={editor.isActive('code') ? 'is-active' : ''}
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||||
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().undo().run()}>
|
<button onClick={() => editor.chain().focus().undo().run()}>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().redo().run()}>
|
<button onClick={() => editor.chain().focus().redo().run()}>
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,9 +141,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,39 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,70 +1,74 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().clearNodes().run()">
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHardBreak().run()">
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().undo().run()">
|
<button @click="editor.chain().focus().undo().run()">
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().redo().run()">
|
<button @click="editor.chain().focus().redo().run()">
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -107,15 +111,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -123,40 +135,69 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -17,109 +17,109 @@ const MenuBar = ({ editor }) => {
|
|||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
className={editor.isActive('bold') ? 'is-active' : ''}
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
className={editor.isActive('italic') ? 'is-active' : ''}
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
className={editor.isActive('strike') ? 'is-active' : ''}
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
className={editor.isActive('code') ? 'is-active' : ''}
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||||
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().undo().run()}>
|
<button onClick={() => editor.chain().focus().undo().run()}>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().redo().run()}>
|
<button onClick={() => editor.chain().focus().redo().run()}>
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -135,7 +135,7 @@ export default () => {
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -163,9 +163,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,67 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor" class="toolbar" :class="styles.toolbar">
|
<div v-if="editor" class="toolbar" :class="styles.toolbar">
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().clearNodes().run()">
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHardBreak().run()">
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().undo().run()">
|
<button @click="editor.chain().focus().undo().run()">
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().redo().run()">
|
<button @click="editor.chain().focus().redo().run()">
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
@ -95,7 +95,7 @@ export default {
|
|||||||
This is a red headline
|
This is a red headline
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -132,15 +132,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -148,41 +156,68 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
.code-block {
|
.tiptap {
|
||||||
|
.code-block {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
select {
|
select {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
background-color: var(--white);
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="Black" d="M7 10l5 5 5-5z"/></svg>');
|
||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
top: 0.5rem;
|
top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -30,9 +30,13 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button onClick={() => editor.chain().focus().toggleCodeBlock().run()} className={editor.isActive('codeBlock') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleCodeBlock().run()} className={editor.isActive('codeBlock') ? 'is-active' : ''}>
|
||||||
code block
|
Toggle code block
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,9 +76,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0d0d0d;
|
background: var(--black);
|
||||||
color: #fff;
|
|
||||||
font-family: "JetBrainsMono", monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code styling */
|
||||||
.hljs-comment,
|
.hljs-comment,
|
||||||
.hljs-quote {
|
.hljs-quote {
|
||||||
color: #616161;
|
color: #616161;
|
||||||
|
@ -46,13 +46,17 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.code-block {
|
.tiptap {
|
||||||
|
.code-block {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
select {
|
select {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.5rem;
|
background-color: var(--white);
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="Black" d="M7 10l5 5 5-5z"/></svg>');
|
||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
|
top: 0.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-">
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Toggle code block
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -88,24 +92,26 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code styling */
|
||||||
.hljs-comment,
|
.hljs-comment,
|
||||||
.hljs-quote {
|
.hljs-quote {
|
||||||
color: #616161;
|
color: #616161;
|
||||||
@ -121,7 +127,7 @@ export default {
|
|||||||
.hljs-name,
|
.hljs-name,
|
||||||
.hljs-selector-id,
|
.hljs-selector-id,
|
||||||
.hljs-selector-class {
|
.hljs-selector-class {
|
||||||
color: #F98181;
|
color: #f98181;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-number,
|
.hljs-number,
|
||||||
@ -131,23 +137,23 @@ export default {
|
|||||||
.hljs-literal,
|
.hljs-literal,
|
||||||
.hljs-type,
|
.hljs-type,
|
||||||
.hljs-params {
|
.hljs-params {
|
||||||
color: #FBBC88;
|
color: #fbbc88;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-string,
|
.hljs-string,
|
||||||
.hljs-symbol,
|
.hljs-symbol,
|
||||||
.hljs-bullet {
|
.hljs-bullet {
|
||||||
color: #B9F18D;
|
color: #b9f18d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-title,
|
.hljs-title,
|
||||||
.hljs-section {
|
.hljs-section {
|
||||||
color: #FAF594;
|
color: #faf594;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-keyword,
|
.hljs-keyword,
|
||||||
.hljs-selector-tag {
|
.hljs-selector-tag {
|
||||||
color: #70CFF8;
|
color: #70cff8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-emphasis {
|
.hljs-emphasis {
|
||||||
|
@ -59,25 +59,25 @@ export default ({ editor }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-unordered',
|
icon: 'list-unordered',
|
||||||
title: 'Bullet List',
|
title: 'Bullet list',
|
||||||
action: () => editor.chain().focus().toggleBulletList().run(),
|
action: () => editor.chain().focus().toggleBulletList().run(),
|
||||||
isActive: () => editor.isActive('bulletList'),
|
isActive: () => editor.isActive('bulletList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-ordered',
|
icon: 'list-ordered',
|
||||||
title: 'Ordered List',
|
title: 'Ordered list',
|
||||||
action: () => editor.chain().focus().toggleOrderedList().run(),
|
action: () => editor.chain().focus().toggleOrderedList().run(),
|
||||||
isActive: () => editor.isActive('orderedList'),
|
isActive: () => editor.isActive('orderedList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-check-2',
|
icon: 'list-check-2',
|
||||||
title: 'Task List',
|
title: 'Task list',
|
||||||
action: () => editor.chain().focus().toggleTaskList().run(),
|
action: () => editor.chain().focus().toggleTaskList().run(),
|
||||||
isActive: () => editor.isActive('taskList'),
|
isActive: () => editor.isActive('taskList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'code-box-line',
|
icon: 'code-box-line',
|
||||||
title: 'Code Block',
|
title: 'Code block',
|
||||||
action: () => editor.chain().focus().toggleCodeBlock().run(),
|
action: () => editor.chain().focus().toggleCodeBlock().run(),
|
||||||
isActive: () => editor.isActive('codeBlock'),
|
isActive: () => editor.isActive('codeBlock'),
|
||||||
},
|
},
|
||||||
@ -92,7 +92,7 @@ export default ({ editor }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'separator',
|
icon: 'separator',
|
||||||
title: 'Horizontal Rule',
|
title: 'Horizontal rule',
|
||||||
action: () => editor.chain().focus().setHorizontalRule().run(),
|
action: () => editor.chain().focus().setHorizontalRule().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -100,12 +100,12 @@ export default ({ editor }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'text-wrap',
|
icon: 'text-wrap',
|
||||||
title: 'Hard Break',
|
title: 'Hard break',
|
||||||
action: () => editor.chain().focus().setHardBreak().run(),
|
action: () => editor.chain().focus().setHardBreak().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'format-clear',
|
icon: 'format-clear',
|
||||||
title: 'Clear Format',
|
title: 'Clear format',
|
||||||
action: () => editor.chain().focus().clearNodes().unsetAllMarks()
|
action: () => editor.chain().focus().clearNodes().unsetAllMarks()
|
||||||
.run(),
|
.run(),
|
||||||
},
|
},
|
||||||
|
@ -78,25 +78,25 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-unordered',
|
icon: 'list-unordered',
|
||||||
title: 'Bullet List',
|
title: 'Bullet list',
|
||||||
action: () => this.editor.chain().focus().toggleBulletList().run(),
|
action: () => this.editor.chain().focus().toggleBulletList().run(),
|
||||||
isActive: () => this.editor.isActive('bulletList'),
|
isActive: () => this.editor.isActive('bulletList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-ordered',
|
icon: 'list-ordered',
|
||||||
title: 'Ordered List',
|
title: 'Ordered list',
|
||||||
action: () => this.editor.chain().focus().toggleOrderedList().run(),
|
action: () => this.editor.chain().focus().toggleOrderedList().run(),
|
||||||
isActive: () => this.editor.isActive('orderedList'),
|
isActive: () => this.editor.isActive('orderedList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-check-2',
|
icon: 'list-check-2',
|
||||||
title: 'Task List',
|
title: 'Task list',
|
||||||
action: () => this.editor.chain().focus().toggleTaskList().run(),
|
action: () => this.editor.chain().focus().toggleTaskList().run(),
|
||||||
isActive: () => this.editor.isActive('taskList'),
|
isActive: () => this.editor.isActive('taskList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'code-box-line',
|
icon: 'code-box-line',
|
||||||
title: 'Code Block',
|
title: 'Code block',
|
||||||
action: () => this.editor.chain().focus().toggleCodeBlock().run(),
|
action: () => this.editor.chain().focus().toggleCodeBlock().run(),
|
||||||
isActive: () => this.editor.isActive('codeBlock'),
|
isActive: () => this.editor.isActive('codeBlock'),
|
||||||
},
|
},
|
||||||
@ -111,7 +111,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'separator',
|
icon: 'separator',
|
||||||
title: 'Horizontal Rule',
|
title: 'Horizontal rule',
|
||||||
action: () => this.editor.chain().focus().setHorizontalRule().run(),
|
action: () => this.editor.chain().focus().setHorizontalRule().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -119,12 +119,12 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'text-wrap',
|
icon: 'text-wrap',
|
||||||
title: 'Hard Break',
|
title: 'Hard break',
|
||||||
action: () => this.editor.chain().focus().setHardBreak().run(),
|
action: () => this.editor.chain().focus().setHardBreak().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'format-clear',
|
icon: 'format-clear',
|
||||||
title: 'Clear Format',
|
title: 'Clear format',
|
||||||
action: () => this.editor.chain()
|
action: () => this.editor.chain()
|
||||||
.focus()
|
.focus()
|
||||||
.clearNodes()
|
.clearNodes()
|
||||||
|
@ -54,11 +54,11 @@ export const MentionList = forwardRef((props, ref) => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="items">
|
<div className="dropdown-menu">
|
||||||
{props.items.length
|
{props.items.length
|
||||||
? props.items.map((item, index) => (
|
? props.items.map((item, index) => (
|
||||||
<button
|
<button
|
||||||
className={`item ${index === selectedIndex ? 'is-selected' : ''}`}
|
className={index === selectedIndex ? 'is-selected' : ''}
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => selectItem(index)}
|
onClick={() => selectItem(index)}
|
||||||
>
|
>
|
||||||
|
@ -1,28 +1,31 @@
|
|||||||
.items {
|
/* Dropdown menu */
|
||||||
padding: 0.2rem;
|
.dropdown-menu {
|
||||||
|
background: var(--white);
|
||||||
|
border: 1px solid var(--gray-1);
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.4rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 0.5rem;
|
|
||||||
background: #FFF;
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(0, 0, 0, 0.05),
|
|
||||||
0px 10px 20px rgba(0, 0, 0, 0.1),
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
button {
|
||||||
display: block;
|
align-items: center;
|
||||||
margin: 0;
|
background-color: transparent;
|
||||||
width: 100%;
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background: transparent;
|
width: 100%;
|
||||||
border-radius: 0.4rem;
|
|
||||||
border: 1px solid transparent;
|
&:hover,
|
||||||
padding: 0.2rem 0.4rem;
|
&:hover.is-selected {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
&.is-selected {
|
&.is-selected {
|
||||||
border-color: #000;
|
background-color: var(--gray-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ export default () => {
|
|||||||
: 0
|
: 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
{editor
|
{editor
|
||||||
&& <div className={`character-count ${editor.storage.characterCount.characters() === limit ? 'character-count--warning' : ''}`}>
|
&& <div className={`character-count ${editor.storage.characterCount.characters() === limit ? 'character-count--warning' : ''}`}>
|
||||||
@ -48,7 +48,6 @@ export default () => {
|
|||||||
height="20"
|
height="20"
|
||||||
width="20"
|
width="20"
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
className="character-count__graph"
|
|
||||||
>
|
>
|
||||||
<circle
|
<circle
|
||||||
r="10"
|
r="10"
|
||||||
@ -74,11 +73,9 @@ export default () => {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div className="character-count__text">
|
{editor.storage.characterCount.characters()} / {limit} characters
|
||||||
{editor.storage.characterCount.characters()}/{limit} characters
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,33 +4,33 @@ context('/src/Examples/Community/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should count the characters correctly', () => {
|
it('should count the characters correctly', () => {
|
||||||
// check if count text is "44/280 characters"
|
// check if count text is "44 / 280 characters"
|
||||||
cy.get('.character-count__text').should('have.text', '44/280 characters')
|
cy.get('.character-count').should('contain', '44 / 280 characters')
|
||||||
|
|
||||||
// type in .tiptap
|
// type in .tiptap
|
||||||
cy.get('.tiptap').type(' Hello World')
|
cy.get('.tiptap').type(' Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '56/280 characters')
|
cy.get('.character-count').should('contain', '56 / 280 characters')
|
||||||
|
|
||||||
// remove content from .tiptap and enter text
|
// remove content from .tiptap and enter text
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '11/280 characters')
|
cy.get('.character-count').should('contain', '11 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should mention a user', () => {
|
it('should mention a user', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||||
|
|
||||||
// check if the mention autocomplete is visible
|
// check if the mention autocomplete is visible
|
||||||
cy.get('.tippy-content .items').should('be.visible')
|
cy.get('.tippy-content .dropdown-menu').should('be.visible')
|
||||||
|
|
||||||
// select the first user
|
// select the first user
|
||||||
cy.get('.tippy-content .items .item').first().then($el => {
|
cy.get('.tippy-content .dropdown-menu button').first().then($el => {
|
||||||
const name = $el.text()
|
const name = $el.text()
|
||||||
|
|
||||||
$el.click()
|
$el.click()
|
||||||
|
|
||||||
// check if the user is mentioned
|
// check if the user is mentioned
|
||||||
cy.get('.tiptap').should('have.text', `@${name} `)
|
cy.get('.tiptap').should('have.text', `@${name} `)
|
||||||
cy.get('.character-count__text').should('have.text', '2/280 characters')
|
cy.get('.character-count').should('contain', '2 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -1,41 +1,33 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1,
|
.mention {
|
||||||
h2,
|
background-color: var(--purple-light);
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mention {
|
|
||||||
border: 1px solid #000;
|
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
padding: 0.1rem 0.3rem;
|
|
||||||
box-decoration-break: clone;
|
box-decoration-break: clone;
|
||||||
|
color: var(--purple);
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Character count */
|
||||||
.character-count {
|
.character-count {
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #68CEF8;
|
color: var(--gray-5);
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: .5rem;
|
||||||
|
margin: 1.5rem;
|
||||||
|
|
||||||
&--warning {
|
svg {
|
||||||
color: #FB5151;
|
color: var(--purple);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__graph {
|
&--warning,
|
||||||
margin-right: 0.5rem;
|
&--warning svg {
|
||||||
}
|
color: var(--red);
|
||||||
|
|
||||||
&__text {
|
|
||||||
color: #868e96;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="items">
|
<div class="dropdown-menu">
|
||||||
<template v-if="items.length">
|
<template v-if="items.length">
|
||||||
<button
|
<button
|
||||||
class="item"
|
|
||||||
:class="{ 'is-selected': index === selectedIndex }"
|
:class="{ 'is-selected': index === selectedIndex }"
|
||||||
v-for="(item, index) in items"
|
v-for="(item, index) in items"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -87,32 +86,35 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.items {
|
/* Dropdown menu */
|
||||||
padding: 0.2rem;
|
.dropdown-menu {
|
||||||
|
background: var(--white);
|
||||||
|
border: 1px solid var(--gray-1);
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.4rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 0.5rem;
|
|
||||||
background: #FFF;
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(0, 0, 0, 0.05),
|
|
||||||
0px 10px 20px rgba(0, 0, 0, 0.1),
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
button {
|
||||||
display: block;
|
align-items: center;
|
||||||
margin: 0;
|
background-color: transparent;
|
||||||
width: 100%;
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background: transparent;
|
width: 100%;
|
||||||
border-radius: 0.4rem;
|
|
||||||
border: 1px solid transparent;
|
&:hover,
|
||||||
padding: 0.2rem 0.4rem;
|
&:hover.is-selected {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
&.is-selected {
|
&.is-selected {
|
||||||
border-color: #000;
|
background-color: var(--gray-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -4,33 +4,33 @@ context('/src/Examples/Community/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should count the characters correctly', () => {
|
it('should count the characters correctly', () => {
|
||||||
// check if count text is "44/280 characters"
|
// check if count text is "44 / 280 characters"
|
||||||
cy.get('.character-count__text').should('have.text', '44/280 characters')
|
cy.get('.character-count').should('contain', '44 / 280 characters')
|
||||||
|
|
||||||
// type in .tiptap
|
// type in .tiptap
|
||||||
cy.get('.tiptap').type(' Hello World')
|
cy.get('.tiptap').type(' Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '56/280 characters')
|
cy.get('.character-count').should('contain', '56 / 280 characters')
|
||||||
|
|
||||||
// remove content from .tiptap and enter text
|
// remove content from .tiptap and enter text
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '11/280 characters')
|
cy.get('.character-count').should('contain', '11 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should mention a user', () => {
|
it('should mention a user', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||||
|
|
||||||
// check if the mention autocomplete is visible
|
// check if the mention autocomplete is visible
|
||||||
cy.get('.tippy-content .items').should('be.visible')
|
cy.get('.tippy-content .dropdown-menu').should('be.visible')
|
||||||
|
|
||||||
// select the first user
|
// select the first user
|
||||||
cy.get('.tippy-content .items .item').first().then($el => {
|
cy.get('.tippy-content .dropdown-menu button').first().then($el => {
|
||||||
const name = $el.text()
|
const name = $el.text()
|
||||||
|
|
||||||
$el.click()
|
$el.click()
|
||||||
|
|
||||||
// check if the user is mentioned
|
// check if the user is mentioned
|
||||||
cy.get('.tiptap').should('have.text', `@${name} `)
|
cy.get('.tiptap').should('have.text', `@${name} `)
|
||||||
cy.get('.character-count__text').should('have.text', '2/280 characters')
|
cy.get('.character-count').should('contain', '2 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
height="20"
|
height="20"
|
||||||
width="20"
|
width="20"
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
class="character-count__graph"
|
|
||||||
>
|
>
|
||||||
<circle
|
<circle
|
||||||
r="10"
|
r="10"
|
||||||
@ -32,7 +31,7 @@
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div class="character-count__text">{{ editor.storage.characterCount.characters() }}/{{ limit }} characters</div>
|
{{ editor.storage.characterCount.characters() }} / {{ limit }} characters
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -97,43 +96,35 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1,
|
.mention {
|
||||||
h2,
|
background-color: var(--purple-light);
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mention {
|
|
||||||
border: 1px solid #000;
|
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
padding: 0.1rem 0.3rem;
|
|
||||||
box-decoration-break: clone;
|
box-decoration-break: clone;
|
||||||
|
color: var(--purple);
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Character count */
|
||||||
.character-count {
|
.character-count {
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #68CEF8;
|
color: var(--gray-5);
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: .5rem;
|
||||||
|
margin: 1.5rem;
|
||||||
|
|
||||||
&--warning {
|
svg {
|
||||||
color: #FB5151;
|
color: var(--purple);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__graph {
|
&--warning,
|
||||||
margin-right: 0.5rem;
|
&--warning svg {
|
||||||
}
|
color: var(--red);
|
||||||
|
|
||||||
&__text {
|
|
||||||
color: #868e96;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,109 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Placeholder (at the top) */
|
||||||
|
/* p.is-editor-empty:first-child::before {
|
||||||
|
color: var(--gray-4);
|
||||||
|
content: attr(data-placeholder);
|
||||||
|
float: left;
|
||||||
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* Placeholder (on every new line) */
|
||||||
|
.is-empty::before {
|
||||||
|
color: var(--gray-4);
|
||||||
|
content: attr(data-placeholder);
|
||||||
|
float: left;
|
||||||
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Placeholder (at the top) */
|
|
||||||
/*.tiptap p.is-editor-empty:first-child::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* Placeholder (on every new line) */
|
|
||||||
.tiptap .is-empty::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
@ -60,26 +60,111 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Placeholder (at the top) */
|
||||||
|
/* p.is-editor-empty:first-child::before {
|
||||||
|
color: var(--gray-4);
|
||||||
|
content: attr(data-placeholder);
|
||||||
|
float: left;
|
||||||
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* Placeholder (on every new line) */
|
||||||
|
.is-empty::before {
|
||||||
|
color: var(--gray-4);
|
||||||
|
content: attr(data-placeholder);
|
||||||
|
float: left;
|
||||||
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Placeholder (at the top) */
|
|
||||||
/*.tiptap p.is-editor-empty:first-child::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* Placeholder (on every new line) */
|
|
||||||
.tiptap .is-empty::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,91 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Placeholder (at the top) */
|
|
||||||
/*.tiptap p.is-editor-empty:first-child::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* Placeholder (on every new line) */
|
|
||||||
.tiptap .is-empty::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
@ -15,7 +15,8 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
disabled={
|
disabled={
|
||||||
@ -27,7 +28,7 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('bold') ? 'is-active' : ''}
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
@ -40,7 +41,7 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('italic') ? 'is-active' : ''}
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
@ -53,7 +54,7 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('strike') ? 'is-active' : ''}
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
@ -66,85 +67,85 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('code') ? 'is-active' : ''}
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||||
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().undo().run()}
|
onClick={() => editor.chain().focus().undo().run()}
|
||||||
@ -156,7 +157,7 @@ const MenuBar = () => {
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().redo().run()}
|
onClick={() => editor.chain().focus().redo().run()}
|
||||||
@ -168,15 +169,16 @@ const MenuBar = () => {
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setColor('#958DF1').run()}
|
onClick={() => editor.chain().focus().setColor('#958DF1').run()}
|
||||||
className={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
className={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
purple
|
Purple
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +202,7 @@ const content = `
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -214,7 +216,7 @@ const content = `
|
|||||||
Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block:
|
Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block:
|
||||||
</p>
|
</p>
|
||||||
<pre><code class="language-css">body {
|
<pre><code class="language-css">body {
|
||||||
display: none;
|
display: none;
|
||||||
}</code></pre>
|
}</code></pre>
|
||||||
<p>
|
<p>
|
||||||
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
|
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
|
||||||
|
@ -21,41 +21,41 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -64,40 +64,40 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -109,35 +109,35 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,15 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -38,40 +38,40 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -83,35 +83,35 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import "./styles.scss";
|
import "./styles.scss";
|
||||||
|
|
||||||
|
import { Color } from '@tiptap/extension-color'
|
||||||
|
import ListItem from '@tiptap/extension-list-item'
|
||||||
|
import TextStyle from '@tiptap/extension-text-style'
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
import { Editor } from "@tiptap/core";
|
import { Editor } from "@tiptap/core";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
@ -11,13 +14,17 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
editor = new Editor({
|
editor = new Editor({
|
||||||
element: element,
|
element: element,
|
||||||
extensions: [StarterKit],
|
extensions: [
|
||||||
|
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
||||||
|
TextStyle.configure({ types: [ListItem.name] }),
|
||||||
|
StarterKit,
|
||||||
|
],
|
||||||
content: `
|
content: `
|
||||||
<h2>
|
<h2>
|
||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -32,7 +39,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<pre><code class="language-css">body {
|
<pre><code class="language-css">body {
|
||||||
display: none;
|
display: none;
|
||||||
}</code></pre>
|
}</code></pre>
|
||||||
<p>
|
<p>
|
||||||
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
|
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
|
||||||
</p>
|
</p>
|
||||||
@ -51,119 +58,125 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if editor}
|
{#if editor}
|
||||||
<div>
|
<div class="control-group">
|
||||||
<div>
|
<div class="button-group">
|
||||||
<button
|
<button
|
||||||
on:click={() => console.log && editor.chain().focus().toggleBold().run()}
|
on:click={() => console.log && editor.chain().focus().toggleBold().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleBold().run()}
|
disabled={!editor.can().chain().focus().toggleBold().run()}
|
||||||
class={editor.isActive("bold") ? "is-active" : ""}
|
class={editor.isActive("bold") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleItalic().run()}
|
on:click={() => editor.chain().focus().toggleItalic().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
||||||
class={editor.isActive("italic") ? "is-active" : ""}
|
class={editor.isActive("italic") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleStrike().run()}
|
on:click={() => editor.chain().focus().toggleStrike().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
||||||
class={editor.isActive("strike") ? "is-active" : ""}
|
class={editor.isActive("strike") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleCode().run()}
|
on:click={() => editor.chain().focus().toggleCode().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleCode().run()}
|
disabled={!editor.can().chain().focus().toggleCode().run()}
|
||||||
class={editor.isActive("code") ? "is-active" : ""}
|
class={editor.isActive("code") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button on:click={() => editor.chain().focus().unsetAllMarks().run()}> clear marks </button>
|
<button on:click={() => editor.chain().focus().unsetAllMarks().run()}>Clear marks</button>
|
||||||
<button on:click={() => editor.chain().focus().clearNodes().run()}> clear nodes </button>
|
<button on:click={() => editor.chain().focus().clearNodes().run()}>Clear nodes</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().setParagraph().run()}
|
on:click={() => editor.chain().focus().setParagraph().run()}
|
||||||
class={editor.isActive("paragraph") ? "is-active" : ""}
|
class={editor.isActive("paragraph") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
class={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
class={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
class={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
class={editor.isActive("heading", { level: 4 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 4 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
class={editor.isActive("heading", { level: 5 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 5 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
class={editor.isActive("heading", { level: 6 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 6 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleBulletList().run()}
|
on:click={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
class={editor.isActive("bulletList") ? "is-active" : ""}
|
class={editor.isActive("bulletList") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleOrderedList().run()}
|
on:click={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
class={editor.isActive("orderedList") ? "is-active" : ""}
|
class={editor.isActive("orderedList") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleCodeBlock().run()}
|
on:click={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
class={editor.isActive("codeBlock") ? "is-active" : ""}
|
class={editor.isActive("codeBlock") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleBlockquote().run()}
|
on:click={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
class={editor.isActive("blockquote") ? "is-active" : ""}
|
class={editor.isActive("blockquote") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button on:click={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button on:click={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button on:click={() => editor.chain().focus().setHardBreak().run()}> hard break </button>
|
<button on:click={() => editor.chain().focus().setHardBreak().run()}>Hard break</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().undo().run()}
|
on:click={() => editor.chain().focus().undo().run()}
|
||||||
disabled={!editor.can().chain().focus().undo().run()}
|
disabled={!editor.can().chain().focus().undo().run()}
|
||||||
>
|
>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().redo().run()}
|
on:click={() => editor.chain().focus().redo().run()}
|
||||||
disabled={!editor.can().chain().focus().redo().run()}
|
disabled={!editor.can().chain().focus().redo().run()}
|
||||||
>
|
>
|
||||||
redo
|
Redo
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => editor.chain().focus().setColor('#958DF1').run()}
|
||||||
|
class={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
||||||
|
>
|
||||||
|
Purple
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,15 @@ context('/src/Examples/Default/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -38,40 +38,40 @@ context('/src/Examples/Default/Vue/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -83,35 +83,35 @@ context('/src/Examples/Default/Vue/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,73 +1,83 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :disabled="!editor.can().chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :disabled="!editor.can().chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :disabled="!editor.can().chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :disabled="!editor.can().chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :disabled="!editor.can().chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :disabled="!editor.can().chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCode().run()" :disabled="!editor.can().chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
<button @click="editor.chain().focus().toggleCode().run()" :disabled="!editor.can().chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().clearNodes().run()">
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHardBreak().run()">
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().undo().run()" :disabled="!editor.can().chain().focus().undo().run()">
|
<button @click="editor.chain().focus().undo().run()" :disabled="!editor.can().chain().focus().undo().run()">
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().redo().run()" :disabled="!editor.can().chain().focus().redo().run()">
|
<button @click="editor.chain().focus().redo().run()" :disabled="!editor.can().chain().focus().redo().run()">
|
||||||
redo
|
Redo
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().setColor('#958DF1').run()" :class="{ 'is-active': editor.isActive('textStyle', { color: '#958DF1' }) }">
|
||||||
|
Purple
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { Color } from '@tiptap/extension-color'
|
||||||
|
import ListItem from '@tiptap/extension-list-item'
|
||||||
|
import TextStyle from '@tiptap/extension-text-style'
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
import { Editor, EditorContent } from '@tiptap/vue-3'
|
import { Editor, EditorContent } from '@tiptap/vue-3'
|
||||||
|
|
||||||
@ -85,6 +95,8 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.editor = new Editor({
|
this.editor = new Editor({
|
||||||
extensions: [
|
extensions: [
|
||||||
|
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
||||||
|
TextStyle.configure({ types: [ListItem.name] }),
|
||||||
StarterKit,
|
StarterKit,
|
||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
@ -92,7 +104,7 @@ export default {
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -129,15 +141,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -145,41 +165,68 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<node-view-wrapper class="draw">
|
<node-view-wrapper class="draw">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<input type="color" v-model="color">
|
<input type="color" v-model="color">
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -8,8 +10,9 @@
|
|||||||
v-model="size"
|
v-model="size"
|
||||||
>
|
>
|
||||||
<button @click="clear">
|
<button @click="clear">
|
||||||
clear
|
Clear
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
<svg viewBox="0 0 500 250" ref="canvas">
|
<svg viewBox="0 0 500 250" ref="canvas">
|
||||||
<template v-for="item in node.attrs.lines">
|
<template v-for="item in node.attrs.lines">
|
||||||
<path
|
<path
|
||||||
@ -22,6 +25,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</svg>
|
</svg>
|
||||||
|
</div>
|
||||||
</node-view-wrapper>
|
</node-view-wrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -12,44 +12,46 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setParagraph().run()} className={editor.isActive('paragraph') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setParagraph().run()} className={editor.isActive('paragraph') ? 'is-active' : ''}>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleBold().run()} className={editor.isActive('bold') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleBold().run()} className={editor.isActive('bold') ? 'is-active' : ''}>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleItalic().run()} className={editor.isActive('italic') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleItalic().run()} className={editor.isActive('italic') ? 'is-active' : ''}>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleStrike().run()} className={editor.isActive('strike') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleStrike().run()} className={editor.isActive('strike') ? 'is-active' : ''}>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHighlight().run()} className={editor.isActive('highlight') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHighlight().run()} className={editor.isActive('highlight') ? 'is-active' : ''}>
|
||||||
highlight
|
Highlight
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('left').run()} className={editor.isActive({ textAlign: 'left' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('left').run()} className={editor.isActive({ textAlign: 'left' }) ? 'is-active' : ''}>
|
||||||
left
|
Left
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('center').run()} className={editor.isActive({ textAlign: 'center' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('center').run()} className={editor.isActive({ textAlign: 'center' }) ? 'is-active' : ''}>
|
||||||
center
|
Center
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('right').run()} className={editor.isActive({ textAlign: 'right' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('right').run()} className={editor.isActive({ textAlign: 'right' }) ? 'is-active' : ''}>
|
||||||
right
|
Right
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('justify').run()} className={editor.isActive({ textAlign: 'justify' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('justify').run()} className={editor.isActive({ textAlign: 'justify' }) ? 'is-active' : ''}>
|
||||||
justify
|
Justify
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,9 +93,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ context('/src/Examples/Formatting/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const marks = [
|
const marks = [
|
||||||
{ label: 'highlight', mark: 'mark' },
|
{ label: 'Highlight', mark: 'mark' },
|
||||||
]
|
]
|
||||||
|
|
||||||
marks.forEach(m => {
|
marks.forEach(m => {
|
||||||
@ -20,10 +20,10 @@ context('/src/Examples/Formatting/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const alignments = [
|
const alignments = [
|
||||||
{ label: 'left', alignment: 'left' },
|
{ label: 'Left', alignment: 'left' },
|
||||||
{ label: 'center', alignment: 'center' },
|
{ label: 'Center', alignment: 'center' },
|
||||||
{ label: 'right', alignment: 'right' },
|
{ label: 'Right', alignment: 'right' },
|
||||||
{ label: 'justify', alignment: 'justify' },
|
{ label: 'Justify', alignment: 'justify' },
|
||||||
]
|
]
|
||||||
|
|
||||||
alignments.forEach(a => {
|
alignments.forEach(a => {
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
margin-top: 1rem;
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
> * + * {
|
|
||||||
margin-top: 0.75em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -18,45 +24,75 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark {
|
mark {
|
||||||
background-color: #FAF594;
|
background-color: #FAF594;
|
||||||
}
|
border-radius: 0.4rem;
|
||||||
|
box-decoration-break: clone;
|
||||||
img {
|
padding: 0.1rem 0.3rem;
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ context('/src/Examples/Formatting/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const marks = [
|
const marks = [
|
||||||
{ label: 'highlight', mark: 'mark' },
|
{ label: 'Highlight', mark: 'mark' },
|
||||||
]
|
]
|
||||||
|
|
||||||
marks.forEach(m => {
|
marks.forEach(m => {
|
||||||
@ -20,10 +20,10 @@ context('/src/Examples/Formatting/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const alignments = [
|
const alignments = [
|
||||||
{ label: 'left', alignment: 'left' },
|
{ label: 'Left', alignment: 'left' },
|
||||||
{ label: 'center', alignment: 'center' },
|
{ label: 'Center', alignment: 'center' },
|
||||||
{ label: 'right', alignment: 'right' },
|
{ label: 'Right', alignment: 'right' },
|
||||||
{ label: 'justify', alignment: 'justify' },
|
{ label: 'Justify', alignment: 'justify' },
|
||||||
]
|
]
|
||||||
|
|
||||||
alignments.forEach(a => {
|
alignments.forEach(a => {
|
||||||
|
@ -1,43 +1,47 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHighlight().run()" :class="{ 'is-active': editor.isActive('highlight') }">
|
<button @click="editor.chain().focus().toggleHighlight().run()" :class="{ 'is-active': editor.isActive('highlight') }">
|
||||||
highlight
|
Highlight
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('left').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'left' }) }">
|
<button @click="editor.chain().focus().setTextAlign('left').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'left' }) }">
|
||||||
left
|
Left
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('center').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }">
|
<button @click="editor.chain().focus().setTextAlign('center').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }">
|
||||||
center
|
Center
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('right').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }">
|
<button @click="editor.chain().focus().setTextAlign('right').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }">
|
||||||
right
|
Right
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('justify').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'justify' }) }">
|
<button @click="editor.chain().focus().setTextAlign('justify').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'justify' }) }">
|
||||||
justify
|
Justify
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -104,17 +108,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
margin-top: 1rem;
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
> * + * {
|
|
||||||
margin-top: 0.75em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -122,45 +132,75 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark {
|
mark {
|
||||||
background-color: #FAF594;
|
background-color: #FAF594;
|
||||||
}
|
border-radius: 0.4rem;
|
||||||
|
box-decoration-break: clone;
|
||||||
img {
|
padding: 0.1rem 0.3rem;
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,13 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<button onClick={addImage}>add image from URL</button>
|
<div className="control-group">
|
||||||
<EditorContent editor={editor} />
|
<div className="button-group">
|
||||||
|
<button onClick={addImage}>Add image from URL</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<EditorContent editor={editor} />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ context('/src/Examples/Images/React/', () => {
|
|||||||
cy.stub(win, 'prompt').returns('https://placehold.co/400x400')
|
cy.stub(win, 'prompt').returns('https://placehold.co/400x400')
|
||||||
|
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('button').contains('add image from URL').click({ force: false })
|
cy.get('button').contains('Add image from URL').click({ force: false })
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('.tiptap img').should('have.length', 3)
|
cy.get('.tiptap img').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
display: block;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
&.ProseMirror-selectednode {
|
&.ProseMirror-selectednode {
|
||||||
outline: 3px solid #68CEF8;
|
outline: 3px solid var(--purple);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ context('/src/Examples/Images/Vue/', () => {
|
|||||||
cy.stub(win, 'prompt').returns('https://placehold.co/400x400')
|
cy.stub(win, 'prompt').returns('https://placehold.co/400x400')
|
||||||
|
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('button').contains('add image from URL').click({ force: false })
|
cy.get('button').contains('Add image from URL').click({ force: false })
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('.tiptap img').should('have.length', 3)
|
cy.get('.tiptap img').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
<button @click="addImage">add image from URL</button>
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
|
<button @click="addImage">Add image from URL</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -60,16 +64,18 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
display: block;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
&.ProseMirror-selectednode {
|
&.ProseMirror-selectednode {
|
||||||
outline: 3px solid #68CEF8;
|
outline: 3px solid var(--purple);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ export default props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="react-component">
|
<NodeViewWrapper className="react-component">
|
||||||
<span className="label">React Component</span>
|
<label>React Component</label>
|
||||||
|
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<button onClick={increase}>
|
<button onClick={increase}>
|
||||||
|
@ -1,33 +1,116 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.react-component {
|
/* List styles */
|
||||||
background: #FAF594;
|
ul,
|
||||||
border: 3px solid #0D0D0D;
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
margin: 1rem 0;
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* React component */
|
||||||
|
.react-component {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border: 2px solid var(--purple);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
margin: 2rem 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.label {
|
label {
|
||||||
margin-left: 1rem;
|
background-color: var(--purple);
|
||||||
background-color: #0D0D0D;
|
border-radius: 0 0 0.5rem 0;
|
||||||
font-size: 0.6rem;
|
color: var(--white);
|
||||||
letter-spacing: 1px;
|
font-size: 0.75rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-transform: uppercase;
|
padding: 0.25rem 0.5rem;
|
||||||
color: #fff;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 0.25rem 0.75rem;
|
|
||||||
border-radius: 0 0 0.5rem 0.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<node-view-wrapper class="vue-component">
|
<node-view-wrapper class="vue-component">
|
||||||
<span class="label">Vue Component</span>
|
<label>Vue Component</label>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<button @click="increase">This button has been clicked {{ node.attrs.count }} times.</button>
|
<button @click="increase">This button has been clicked {{ node.attrs.count }} times.</button>
|
||||||
@ -29,30 +29,30 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.vue-component {
|
.tiptap {
|
||||||
background: #FAF594;
|
/* Vue component */
|
||||||
border: 3px solid #0D0D0D;
|
.vue-component {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border: 2px solid var(--purple);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
margin: 1rem 0;
|
margin: 2rem 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
label {
|
||||||
margin-left: 1rem;
|
background-color: var(--purple);
|
||||||
background-color: #0D0D0D;
|
border-radius: 0 0 0.5rem 0;
|
||||||
font-size: 0.6rem;
|
color: var(--white);
|
||||||
letter-spacing: 1px;
|
font-size: 0.75rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-transform: uppercase;
|
padding: 0.25rem 0.5rem;
|
||||||
color: #fff;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 0.25rem 0.75rem;
|
}
|
||||||
border-radius: 0 0 0.5rem 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -46,8 +46,93 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -3,10 +3,10 @@ import React from 'react'
|
|||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper className="react-component-with-content">
|
<NodeViewWrapper className="react-component">
|
||||||
<span className="label" contentEditable={false}>React Component</span>
|
<label contentEditable={false}>React Component</label>
|
||||||
|
|
||||||
<NodeViewContent className="content" />
|
<NodeViewContent className="content is-editable" />
|
||||||
</NodeViewWrapper>
|
</NodeViewWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,12 @@ context('/src/Examples/InteractivityComponentContent/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should render a custom node', () => {
|
it('should render a custom node', () => {
|
||||||
cy.get('.ProseMirror .react-component-with-content')
|
cy.get('.ProseMirror .react-component')
|
||||||
.should('have.length', 1)
|
.should('have.length', 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should allow text editing inside component', () => {
|
it('should allow text editing inside component', () => {
|
||||||
cy.get('.ProseMirror .react-component-with-content .content div')
|
cy.get('.ProseMirror .react-component .content div')
|
||||||
.invoke('attr', 'contentEditable', true)
|
.invoke('attr', 'contentEditable', true)
|
||||||
.invoke('text', '')
|
.invoke('text', '')
|
||||||
.type('Hello World!')
|
.type('Hello World!')
|
||||||
@ -24,24 +24,24 @@ context('/src/Examples/InteractivityComponentContent/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should allow text editing inside component with markdown text', () => {
|
it('should allow text editing inside component with markdown text', () => {
|
||||||
cy.get('.ProseMirror .react-component-with-content .content div')
|
cy.get('.ProseMirror .react-component .content div')
|
||||||
.invoke('attr', 'contentEditable', true)
|
.invoke('attr', 'contentEditable', true)
|
||||||
.invoke('text', '')
|
.invoke('text', '')
|
||||||
.type('Hello World! This is **bold**.')
|
.type('Hello World! This is **bold**.')
|
||||||
.should('have.text', 'Hello World! This is bold.')
|
.should('have.text', 'Hello World! This is bold.')
|
||||||
|
|
||||||
cy.get('.ProseMirror .react-component-with-content .content strong')
|
cy.get('.ProseMirror .react-component .content strong')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should remove node via selectall', () => {
|
it('should remove node via selectall', () => {
|
||||||
cy.get('.ProseMirror .react-component-with-content')
|
cy.get('.ProseMirror .react-component')
|
||||||
.should('have.length', 1)
|
.should('have.length', 1)
|
||||||
|
|
||||||
cy.get('.ProseMirror')
|
cy.get('.ProseMirror')
|
||||||
.type('{selectall}{backspace}')
|
.type('{selectall}{backspace}')
|
||||||
|
|
||||||
cy.get('.ProseMirror .react-component-with-content')
|
cy.get('.ProseMirror .react-component')
|
||||||
.should('have.length', 0)
|
.should('have.length', 0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,36 +1,123 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.react-component-with-content {
|
/* List styles */
|
||||||
background: #FAF594;
|
ul,
|
||||||
border: 3px solid #0D0D0D;
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
margin: 1rem 0;
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* React component */
|
||||||
|
.react-component {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border: 2px solid var(--purple);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
margin: 2rem 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.label {
|
label {
|
||||||
margin-left: 1rem;
|
background-color: var(--purple);
|
||||||
background-color: #0D0D0D;
|
border-radius: 0 0 0.5rem 0;
|
||||||
font-size: 0.6rem;
|
color: var(--white);
|
||||||
letter-spacing: 1px;
|
font-size: 0.75rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-transform: uppercase;
|
padding: 0.25rem 0.5rem;
|
||||||
color: #fff;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 0.25rem 0.75rem;
|
|
||||||
border-radius: 0 0 0.5rem 0.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
&.is-editable {
|
||||||
|
border: 2px dashed var(--gray-3);
|
||||||
|
border-radius: 0.5rem;
|
||||||
margin: 2.5rem 1rem 1rem;
|
margin: 2.5rem 1rem 1rem;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border: 2px dashed #0D0D0D20;
|
}
|
||||||
border-radius: 0.5rem;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<node-view-wrapper class="vue-component">
|
<node-view-wrapper class="vue-component">
|
||||||
<span class="label" contenteditable="false">Vue Component</span>
|
<label contenteditable="false">Vue Component</label>
|
||||||
<node-view-content class="content" />
|
<node-view-content class="content is-editable" />
|
||||||
</node-view-wrapper>
|
</node-view-wrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -19,32 +19,37 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.vue-component {
|
.tiptap {
|
||||||
background: #FAF594;
|
/* Vue component */
|
||||||
border: 3px solid #0D0D0D;
|
.vue-component {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border: 2px solid var(--purple);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
margin: 1rem 0;
|
margin: 2rem 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
label {
|
||||||
margin-left: 1rem;
|
background-color: var(--purple);
|
||||||
background-color: #0D0D0D;
|
border-radius: 0 0 0.5rem 0;
|
||||||
font-size: 0.6rem;
|
color: var(--white);
|
||||||
letter-spacing: 1px;
|
font-size: 0.75rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-transform: uppercase;
|
padding: 0.25rem 0.5rem;
|
||||||
color: #fff;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 0.25rem 0.75rem;
|
}
|
||||||
border-radius: 0 0 0.5rem 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
&.is-editable {
|
||||||
|
border: 2px dashed var(--gray-3);
|
||||||
|
border-radius: 0.5rem;
|
||||||
margin: 2.5rem 1rem 1rem;
|
margin: 2.5rem 1rem 1rem;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border: 2px dashed #0D0D0D20;
|
}
|
||||||
border-radius: 0.5rem;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -48,8 +48,93 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -21,7 +21,7 @@ export default () => {
|
|||||||
To test that, start a new line and type <code>#</code> followed by a space to get a heading. Try <code>#</code>, <code>##</code>, <code>###</code>, <code>####</code>, <code>#####</code>, <code>######</code> for different levels.
|
To test that, start a new line and type <code>#</code> followed by a space to get a heading. Try <code>#</code>, <code>##</code>, <code>###</code>, <code>####</code>, <code>#####</code>, <code>######</code> for different levels.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Those conventions are called input rules in tiptap. Some of them are enabled by default. Try <code>></code> for blockquotes, <code>*</code>, <code>-</code> or <code>+</code> for bullet lists, or <code>\`foobar\`</code> to highlight code, <code>~~tildes~~</code> to strike text, or <code>==equal signs==</code> to highlight text.
|
Those conventions are called input rules in Tiptap. Some of them are enabled by default. Try <code>></code> for blockquotes, <code>*</code>, <code>-</code> or <code>+</code> for bullet lists, or <code>\`foobar\`</code> to highlight code, <code>~~tildes~~</code> to strike text, or <code>==equal signs==</code> to highlight text.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You can overwrite existing input rules or add your own to nodes, marks and extensions.
|
You can overwrite existing input rules or add your own to nodes, marks and extensions.
|
||||||
|
@ -1,13 +1,22 @@
|
|||||||
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -15,39 +24,75 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
mark {
|
||||||
max-width: 100%;
|
background-color: #FAF594;
|
||||||
height: auto;
|
border-radius: 0.4rem;
|
||||||
}
|
box-decoration-break: clone;
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ export default {
|
|||||||
To test that, start a new line and type <code>#</code> followed by a space to get a heading. Try <code>#</code>, <code>##</code>, <code>###</code>, <code>####</code>, <code>#####</code>, <code>######</code> for different levels.
|
To test that, start a new line and type <code>#</code> followed by a space to get a heading. Try <code>#</code>, <code>##</code>, <code>###</code>, <code>####</code>, <code>#####</code>, <code>######</code> for different levels.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Those conventions are called input rules in tiptap. Some of them are enabled by default. Try <code>></code> for blockquotes, <code>*</code>, <code>-</code> or <code>+</code> for bullet lists, or <code>\`foobar\`</code> to highlight code, <code>~~tildes~~</code> to strike text, or <code>==equal signs==</code> to highlight text.
|
Those conventions are called input rules in Tiptap. Some of them are enabled by default. Try <code>></code> for blockquotes, <code>*</code>, <code>-</code> or <code>+</code> for bullet lists, or <code>\`foobar\`</code> to highlight code, <code>~~tildes~~</code> to strike text, or <code>==equal signs==</code> to highlight text.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You can overwrite existing input rules or add your own to nodes, marks and extensions.
|
You can overwrite existing input rules or add your own to nodes, marks and extensions.
|
||||||
@ -55,15 +55,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -71,40 +79,76 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
mark {
|
||||||
max-width: 100%;
|
background-color: #FAF594;
|
||||||
height: auto;
|
border-radius: 0.4rem;
|
||||||
}
|
box-decoration-break: clone;
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -64,7 +64,7 @@ export default () => {
|
|||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
Bullet List
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
</FloatingMenu>}
|
</FloatingMenu>}
|
||||||
|
|
||||||
|
@ -1,53 +1,144 @@
|
|||||||
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bubble menu */
|
||||||
.bubble-menu {
|
.bubble-menu {
|
||||||
|
background-color: var(--white);
|
||||||
|
border: 1px solid var(--gray-1);
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #0D0D0D;
|
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
border-radius: 0.5rem;
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border: none;
|
background-color: unset;
|
||||||
background: none;
|
|
||||||
color: #FFF;
|
&:hover {
|
||||||
font-size: 0.85rem;
|
background-color: var(--gray-3);
|
||||||
font-weight: 500;
|
}
|
||||||
padding: 0 0.2rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&.is-active {
|
&.is-active {
|
||||||
opacity: 1;
|
background-color: var(--purple);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--purple-contrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Floating menu */
|
||||||
.floating-menu {
|
.floating-menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #0D0D0D10;
|
background-color: var(--gray-3);
|
||||||
padding: 0.2rem;
|
padding: 0.1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border: none;
|
background-color: unset;
|
||||||
background: none;
|
padding: 0.275rem 0.425rem;
|
||||||
font-size: 0.85rem;
|
border-radius: 0.3rem;
|
||||||
font-weight: 500;
|
|
||||||
padding: 0 0.2rem;
|
&:hover {
|
||||||
opacity: 0.6;
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&.is-active {
|
&.is-active {
|
||||||
opacity: 1;
|
background-color: var(--white);
|
||||||
|
color: var(--purple);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--purple-contrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
H2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
Bullet List
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
</floating-menu>
|
</floating-menu>
|
||||||
</div>
|
</div>
|
||||||
@ -83,60 +83,145 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bubble menu */
|
||||||
.bubble-menu {
|
.bubble-menu {
|
||||||
|
background-color: var(--white);
|
||||||
|
border: 1px solid var(--gray-1);
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #0D0D0D;
|
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
border-radius: 0.5rem;
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border: none;
|
background-color: unset;
|
||||||
background: none;
|
|
||||||
color: #FFF;
|
&:hover {
|
||||||
font-size: 0.85rem;
|
background-color: var(--gray-3);
|
||||||
font-weight: 500;
|
}
|
||||||
padding: 0 0.2rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&.is-active {
|
&.is-active {
|
||||||
opacity: 1;
|
background-color: var(--purple);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--purple-contrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Floating menu */
|
||||||
.floating-menu {
|
.floating-menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #0D0D0D10;
|
background-color: var(--gray-3);
|
||||||
padding: 0.2rem;
|
padding: 0.1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border: none;
|
background-color: unset;
|
||||||
background: none;
|
padding: 0.275rem 0.425rem;
|
||||||
font-size: 0.85rem;
|
border-radius: 0.3rem;
|
||||||
font-weight: 500;
|
|
||||||
padding: 0 0.2rem;
|
&:hover {
|
||||||
opacity: 0.6;
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&.is-active {
|
&.is-active {
|
||||||
opacity: 1;
|
background-color: var(--white);
|
||||||
|
color: var(--purple);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--purple-contrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ export default () => {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
This is a radically reduced version of tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
This is a radically reduced version of Tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ export default {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
This is a radically reduced version of tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
This is a radically reduced version of Tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
||||||
@ -46,8 +46,8 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -18,7 +18,7 @@ export default () => {
|
|||||||
<p>
|
<p>
|
||||||
This is a <strong>simple</strong> paragraph.
|
This is a <strong>simple</strong> paragraph.
|
||||||
</p>
|
</p>
|
||||||
<img src="https://unsplash.it/200/200" alt="A 200x200 square thumbnail from unsplash." />
|
<img src="https://placehold.co/200x200" alt="A 200x200 square thumbnail from placehold.co." />
|
||||||
<p>
|
<p>
|
||||||
Here is another paragraph inside this document.
|
Here is another paragraph inside this document.
|
||||||
</p>
|
</p>
|
||||||
@ -72,11 +72,11 @@ export default () => {
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<p>Here we have another paragraph inside a blockquote.</p>
|
<p>Here we have another paragraph inside a blockquote.</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<img src="https://unsplash.it/260/200" alt="A 260x200 landscape thumbnail from unsplash." />
|
<img src="https://placehold.co/260x200" alt="A 260x200 landscape thumbnail from placehold.co." />
|
||||||
<img src="https://unsplash.it/100/200" alt="A 100x200 portrait thumbnail from unsplash." />
|
<img src="https://placehold.co/100x200" alt="A 100x200 portrait thumbnail from placehold.co." />
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<img src="https://unsplash.it/260/200" alt="A 260x200 landscape thumbnail from unsplash." />
|
<img src="https://placehold.co/260x200" alt="A 260x200 landscape thumbnail from placehold.co." />
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ export default () => {
|
|||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
const findSquaredImage = useCallback(() => {
|
const findSquaredImage = useCallback(() => {
|
||||||
const nodePosition = editor.$doc.querySelector('image', { src: 'https://unsplash.it/200/200' })
|
const nodePosition = editor.$doc.querySelector('image', { src: 'https://placehold.co/200x200' })
|
||||||
|
|
||||||
if (!nodePosition) {
|
if (!nodePosition) {
|
||||||
setFoundNodes(null)
|
setFoundNodes(null)
|
||||||
@ -171,7 +171,7 @@ export default () => {
|
|||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
const findLandscapeImage = useCallback(() => {
|
const findLandscapeImage = useCallback(() => {
|
||||||
const nodePosition = editor.$doc.querySelector('image', { src: 'https://unsplash.it/260/200' })
|
const nodePosition = editor.$doc.querySelector('image', { src: 'https://placehold.co/260x200' })
|
||||||
|
|
||||||
if (!nodePosition) {
|
if (!nodePosition) {
|
||||||
setFoundNodes(null)
|
setFoundNodes(null)
|
||||||
@ -182,7 +182,7 @@ export default () => {
|
|||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
const findAllLandscapeImages = useCallback(() => {
|
const findAllLandscapeImages = useCallback(() => {
|
||||||
const nodePosition = editor.$doc.querySelectorAll('image', { src: 'https://unsplash.it/260/200' })
|
const nodePosition = editor.$doc.querySelectorAll('image', { src: 'https://placehold.co/260x200' })
|
||||||
|
|
||||||
if (!nodePosition) {
|
if (!nodePosition) {
|
||||||
setFoundNodes(null)
|
setFoundNodes(null)
|
||||||
@ -193,7 +193,7 @@ export default () => {
|
|||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
const findFirstLandscapeImageWithAllQuery = useCallback(() => {
|
const findFirstLandscapeImageWithAllQuery = useCallback(() => {
|
||||||
const nodePosition = editor.$doc.querySelectorAll('image', { src: 'https://unsplash.it/260/200' }, true)
|
const nodePosition = editor.$doc.querySelectorAll('image', { src: 'https://placehold.co/260x200' }, true)
|
||||||
|
|
||||||
if (!nodePosition) {
|
if (!nodePosition) {
|
||||||
setFoundNodes(null)
|
setFoundNodes(null)
|
||||||
@ -204,7 +204,7 @@ export default () => {
|
|||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
const findPortraitImageInBlockquote = useCallback(() => {
|
const findPortraitImageInBlockquote = useCallback(() => {
|
||||||
const nodePosition = editor.$doc.querySelector('image', { src: 'https://unsplash.it/100/200' })
|
const nodePosition = editor.$doc.querySelector('image', { src: 'https://placehold.co/100x200' })
|
||||||
|
|
||||||
if (!nodePosition) {
|
if (!nodePosition) {
|
||||||
setFoundNodes(null)
|
setFoundNodes(null)
|
||||||
@ -259,8 +259,9 @@ export default () => {
|
|||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<div>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button data-testid="find-paragraphs" onClick={findParagraphs}>Find paragraphs</button>
|
<button data-testid="find-paragraphs" onClick={findParagraphs}>Find paragraphs</button>
|
||||||
<button data-testid="find-listitems" onClick={findListItems}>Find list items</button>
|
<button data-testid="find-listitems" onClick={findListItems}>Find list items</button>
|
||||||
<button data-testid="find-bulletlists" onClick={findBulletList}>Find bullet lists</button>
|
<button data-testid="find-bulletlists" onClick={findBulletList}>Find bullet lists</button>
|
||||||
@ -268,7 +269,7 @@ export default () => {
|
|||||||
<button data-testid="find-blockquotes" onClick={findBlockquote}>Find blockquotes</button>
|
<button data-testid="find-blockquotes" onClick={findBlockquote}>Find blockquotes</button>
|
||||||
<button data-testid="find-images" onClick={findImages}>Find images</button>
|
<button data-testid="find-images" onClick={findImages}>Find images</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="button-group">
|
||||||
<button data-testid="find-first-blockquote" onClick={findFirstBlockquote}>Find first blockquote</button>
|
<button data-testid="find-first-blockquote" onClick={findFirstBlockquote}>Find first blockquote</button>
|
||||||
<button data-testid="find-squared-image" onClick={findSquaredImage}>Find squared image</button>
|
<button data-testid="find-squared-image" onClick={findSquaredImage}>Find squared image</button>
|
||||||
<button data-testid="find-landscape-image" onClick={findLandscapeImage}>Find landscape image</button>
|
<button data-testid="find-landscape-image" onClick={findLandscapeImage}>Find landscape image</button>
|
||||||
@ -276,16 +277,17 @@ export default () => {
|
|||||||
<button data-testid="find-first-landscape-image-with-all-query" onClick={findFirstLandscapeImageWithAllQuery}>Find first landscape image with all query</button>
|
<button data-testid="find-first-landscape-image-with-all-query" onClick={findFirstLandscapeImageWithAllQuery}>Find first landscape image with all query</button>
|
||||||
<button data-testid="find-portrait-image-inside-blockquote" onClick={findPortraitImageInBlockquote}>Find portrait image in blockquote</button>
|
<button data-testid="find-portrait-image-inside-blockquote" onClick={findPortraitImageInBlockquote}>Find portrait image in blockquote</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="button-group">
|
||||||
<button data-testid="find-first-node" onClick={findFirstNode}>Find first node</button>
|
<button data-testid="find-first-node" onClick={findFirstNode}>Find first node</button>
|
||||||
<button data-testid="find-last-node" onClick={findLastNode}>Find last node</button>
|
<button data-testid="find-last-node" onClick={findLastNode}>Find last node</button>
|
||||||
<button data-testid="find-last-node-of-first-bullet-list" onClick={findLastNodeOfFirstBulletList}>Find last node of first bullet list</button>
|
<button data-testid="find-last-node-of-first-bullet-list" onClick={findLastNodeOfFirstBulletList}>Find last node of first bullet list</button>
|
||||||
<button data-testid="find-nonexistent-node" onClick={findNonexistentNode}>Find nonexistent node</button>
|
<button data-testid="find-nonexistent-node" onClick={findNonexistentNode}>Find nonexistent node</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
{foundNodes ? <div data-testid="found-nodes">{foundNodes.map(n => (
|
{foundNodes ? <div className="output-group" data-testid="found-nodes">{foundNodes.map(n => (
|
||||||
<div data-testid="found-node" key={n.pos}>{mapNodePosToString(n)}</div>
|
<div data-testid="found-node" key={n.pos}>{mapNodePosToString(n)}</div>
|
||||||
))}</div> : ''}
|
))}</div> : ''}
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ context('/src/Examples/NodePos/React/', () => {
|
|||||||
cy.get('button[data-testid="find-squared-image"]').click()
|
cy.get('button[data-testid="find-squared-image"]').click()
|
||||||
cy.get('div[data-testid="found-nodes"]').should('exist')
|
cy.get('div[data-testid="found-nodes"]').should('exist')
|
||||||
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
||||||
cy.get('div[data-testid="found-node"]').should('contain', 'https://unsplash.it/200/200')
|
cy.get('div[data-testid="found-node"]').should('contain', 'https://placehold.co/200x200')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ context('/src/Examples/NodePos/React/', () => {
|
|||||||
cy.get('button[data-testid="find-landscape-image"]').click()
|
cy.get('button[data-testid="find-landscape-image"]').click()
|
||||||
cy.get('div[data-testid="found-nodes"]').should('exist')
|
cy.get('div[data-testid="found-nodes"]').should('exist')
|
||||||
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
||||||
cy.get('div[data-testid="found-node"]').should('contain', 'https://unsplash.it/260/200')
|
cy.get('div[data-testid="found-node"]').should('contain', 'https://placehold.co/260x200')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -84,8 +84,8 @@ context('/src/Examples/NodePos/React/', () => {
|
|||||||
cy.get('button[data-testid="find-all-landscape-images"]').click()
|
cy.get('button[data-testid="find-all-landscape-images"]').click()
|
||||||
cy.get('div[data-testid="found-nodes"]').should('exist')
|
cy.get('div[data-testid="found-nodes"]').should('exist')
|
||||||
cy.get('div[data-testid="found-node"]').should('have.length', 2)
|
cy.get('div[data-testid="found-node"]').should('have.length', 2)
|
||||||
cy.get('div[data-testid="found-node"]').eq(0).should('contain', 'https://unsplash.it/260/200')
|
cy.get('div[data-testid="found-node"]').eq(0).should('contain', 'https://placehold.co/260x200')
|
||||||
cy.get('div[data-testid="found-node"]').eq(1).should('contain', 'https://unsplash.it/260/200')
|
cy.get('div[data-testid="found-node"]').eq(1).should('contain', 'https://placehold.co/260x200')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ context('/src/Examples/NodePos/React/', () => {
|
|||||||
cy.get('button[data-testid="find-first-landscape-image-with-all-query"]').click()
|
cy.get('button[data-testid="find-first-landscape-image-with-all-query"]').click()
|
||||||
cy.get('div[data-testid="found-nodes"]').should('exist')
|
cy.get('div[data-testid="found-nodes"]').should('exist')
|
||||||
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
||||||
cy.get('div[data-testid="found-node"]').should('contain', 'https://unsplash.it/260/200')
|
cy.get('div[data-testid="found-node"]').should('contain', 'https://placehold.co/260x200')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ context('/src/Examples/NodePos/React/', () => {
|
|||||||
cy.get('button[data-testid="find-portrait-image-inside-blockquote"]').click()
|
cy.get('button[data-testid="find-portrait-image-inside-blockquote"]').click()
|
||||||
cy.get('div[data-testid="found-nodes"]').should('exist')
|
cy.get('div[data-testid="found-nodes"]').should('exist')
|
||||||
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
cy.get('div[data-testid="found-node"]').should('have.length', 1)
|
||||||
cy.get('div[data-testid="found-node"]').should('contain', 'https://unsplash.it/100/200')
|
cy.get('div[data-testid="found-node"]').should('contain', 'https://placehold.co/100x200')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -11,5 +24,80 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Image styles */
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
height: auto;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
&.ProseMirror-selectednode {
|
||||||
|
outline: 3px solid var(--purple);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ export default () => {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
→ With the Typography extension, tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side.
|
→ With the Typography extension, Tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Try it out and type <code>(c)</code>, <code>-></code>, <code>>></code>, <code>1/2</code>, <code>!=</code>, <code>--</code> or <code>1x1</code> here:
|
Try it out and type <code>(c)</code>, <code>-></code>, <code>>></code>, <code>1/2</code>, <code>!=</code>, <code>--</code> or <code>1x1</code> here:
|
||||||
|
@ -1,26 +1,20 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Color swatches */
|
/* Color swatches */
|
||||||
.color {
|
.color {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
@ -35,4 +29,5 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ export default {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
→ With the Typography extension, tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side.
|
→ With the Typography extension, Tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Try it out and type <code>(c)</code>, <code>-></code>, <code>>></code>, <code>1/2</code>, <code>!=</code>, <code>--</code> or <code>1x1</code> here:
|
Try it out and type <code>(c)</code>, <code>-></code>, <code>>></code>, <code>1/2</code>, <code>!=</code>, <code>--</code> or <code>1x1</code> here:
|
||||||
@ -64,40 +64,35 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Color swatches */
|
/* Color swatches */
|
||||||
.color {
|
.color {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: ' ';
|
|
||||||
display: inline-block;
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
border: 1px solid rgba(128, 128, 128, 0.3);
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 0.1em;
|
|
||||||
margin-bottom: 0.15em;
|
|
||||||
border-radius: 2px;
|
|
||||||
background-color: var(--color);
|
background-color: var(--color);
|
||||||
|
border: 1px solid rgba(128, 128, 128, 0.3);
|
||||||
|
border-radius: 2px;
|
||||||
|
content: " ";
|
||||||
|
display: inline-block;
|
||||||
|
height: 1em;
|
||||||
|
margin-bottom: 0.15em;
|
||||||
|
margin-right: 0.1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -60,69 +60,71 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button onClick={() => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}>
|
<button onClick={() => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}>
|
||||||
insertTable
|
Insert table
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().insertContent(tableHTML, {
|
<button onClick={() => editor.chain().focus().insertContent(tableHTML, {
|
||||||
parseOptions: {
|
parseOptions: {
|
||||||
preserveWhitespace: false,
|
preserveWhitespace: false,
|
||||||
},
|
},
|
||||||
}).run()}>
|
}).run()}>
|
||||||
insertHTMLTable
|
Insert HTML table
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().addColumnBefore().run()} disabled={!editor.can().addColumnBefore()}>
|
<button onClick={() => editor.chain().focus().addColumnBefore().run()} disabled={!editor.can().addColumnBefore()}>
|
||||||
addColumnBefore
|
Add column before
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().addColumnAfter().run()} disabled={!editor.can().addColumnAfter()}>
|
<button onClick={() => editor.chain().focus().addColumnAfter().run()} disabled={!editor.can().addColumnAfter()}>
|
||||||
addColumnAfter
|
Add column after
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().deleteColumn().run()} disabled={!editor.can().deleteColumn()}>
|
<button onClick={() => editor.chain().focus().deleteColumn().run()} disabled={!editor.can().deleteColumn()}>
|
||||||
deleteColumn
|
Delete column
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().addRowBefore().run()} disabled={!editor.can().addRowBefore()}>
|
<button onClick={() => editor.chain().focus().addRowBefore().run()} disabled={!editor.can().addRowBefore()}>
|
||||||
addRowBefore
|
Add row before
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().addRowAfter().run()} disabled={!editor.can().addRowAfter()}>
|
<button onClick={() => editor.chain().focus().addRowAfter().run()} disabled={!editor.can().addRowAfter()}>
|
||||||
addRowAfter
|
Add row after
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().deleteRow().run()} disabled={!editor.can().deleteRow()}>
|
<button onClick={() => editor.chain().focus().deleteRow().run()} disabled={!editor.can().deleteRow()}>
|
||||||
deleteRow
|
Delete row
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().deleteTable().run()} disabled={!editor.can().deleteTable()}>
|
<button onClick={() => editor.chain().focus().deleteTable().run()} disabled={!editor.can().deleteTable()}>
|
||||||
deleteTable
|
Delete table
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().mergeCells().run()} disabled={!editor.can().mergeCells()}>
|
<button onClick={() => editor.chain().focus().mergeCells().run()} disabled={!editor.can().mergeCells()}>
|
||||||
mergeCells
|
Merge cells
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().splitCell().run()} disabled={!editor.can().splitCell()}>
|
<button onClick={() => editor.chain().focus().splitCell().run()} disabled={!editor.can().splitCell()}>
|
||||||
splitCell
|
Split cell
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHeaderColumn().run()} disabled={!editor.can().toggleHeaderColumn()}>
|
<button onClick={() => editor.chain().focus().toggleHeaderColumn().run()} disabled={!editor.can().toggleHeaderColumn()}>
|
||||||
toggleHeaderColumn
|
ToggleHeaderColumn
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHeaderRow().run()} disabled={!editor.can().toggleHeaderRow()}>
|
<button onClick={() => editor.chain().focus().toggleHeaderRow().run()} disabled={!editor.can().toggleHeaderRow()}>
|
||||||
toggleHeaderRow
|
Toggle header row
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHeaderCell().run()} disabled={!editor.can().toggleHeaderCell()}>
|
<button onClick={() => editor.chain().focus().toggleHeaderCell().run()} disabled={!editor.can().toggleHeaderCell()}>
|
||||||
toggleHeaderCell
|
Toggle header cell
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().mergeOrSplit().run()} disabled={!editor.can().mergeOrSplit()}>
|
<button onClick={() => editor.chain().focus().mergeOrSplit().run()} disabled={!editor.can().mergeOrSplit()}>
|
||||||
mergeOrSplit
|
Merge or split
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setCellAttribute('backgroundColor', '#FAF594').run()} disabled={!editor.can().setCellAttribute('backgroundColor', '#FAF594')}>
|
<button onClick={() => editor.chain().focus().setCellAttribute('backgroundColor', '#FAF594').run()} disabled={!editor.can().setCellAttribute('backgroundColor', '#FAF594')}>
|
||||||
setCellAttribute
|
Set cell attribute
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().fixTables().run()} disabled={!editor.can().fixTables()}>
|
<button onClick={() => editor.chain().focus().fixTables().run()} disabled={!editor.can().fixTables()}>
|
||||||
fixTables
|
Fix tables
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().goToNextCell().run()} disabled={!editor.can().goToNextCell()}>
|
<button onClick={() => editor.chain().focus().goToNextCell().run()} disabled={!editor.can().goToNextCell()}>
|
||||||
goToNextCell
|
Go to next cell
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().goToPreviousCell().run()} disabled={!editor.can().goToPreviousCell()}>
|
<button onClick={() => editor.chain().focus().goToPreviousCell().run()} disabled={!editor.can().goToPreviousCell()}>
|
||||||
goToPreviousCell
|
Go to previous cell
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +147,9 @@ export default () => {
|
|||||||
Have you seen our tables? They are amazing!
|
Have you seen our tables? They are amazing!
|
||||||
</h3>
|
</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>tables with rows, cells and headers (optional)</li>
|
<li>Tables with rows, cells and headers (optional)</li>
|
||||||
<li>support for <code>colgroup</code> and <code>rowspan</code></li>
|
<li>Support for <code>colgroup</code> and <code>rowspan</code></li>
|
||||||
<li>and even resizable columns (optional)</li>
|
<li>And even resizable columns (optional)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Here is an example:
|
Here is an example:
|
||||||
@ -160,20 +162,20 @@ export default () => {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cyndi Lauper</td>
|
<td>Cyndi Lauper</td>
|
||||||
<td>singer</td>
|
<td>Singer</td>
|
||||||
<td>songwriter</td>
|
<td>Songwriter</td>
|
||||||
<td>actress</td>
|
<td>Actress</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Marie Curie</td>
|
<td>Marie Curie</td>
|
||||||
<td>scientist</td>
|
<td>Scientist</td>
|
||||||
<td>chemist</td>
|
<td>Chemist</td>
|
||||||
<td>physicist</td>
|
<td>Physicist</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Indira Gandhi</td>
|
<td>Indira Gandhi</td>
|
||||||
<td>prime minister</td>
|
<td>Prime minister</td>
|
||||||
<td colspan="2">politician</td>
|
<td colspan="2">Politician</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -181,9 +183,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ context('/src/Examples/Tables/React/', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.get('.tiptap').then(([{ editor }]) => {
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
editor.commands.clearContent()
|
editor.commands.clearContent()
|
||||||
cy.get('button').contains('insertTable').click()
|
cy.get('button').contains('Insert table').click()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -28,15 +28,15 @@ context('/src/Examples/Tables/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('adds & delete columns', () => {
|
it('adds & delete columns', () => {
|
||||||
cy.get('button').contains('addColumnBefore').click()
|
cy.get('button').contains('Add column before').click()
|
||||||
cy.get('.tiptap table th')
|
cy.get('.tiptap table th')
|
||||||
.should('have.length', 4)
|
.should('have.length', 4)
|
||||||
|
|
||||||
cy.get('button').contains('addColumnAfter').click()
|
cy.get('button').contains('Add column after').click()
|
||||||
cy.get('.tiptap table th')
|
cy.get('.tiptap table th')
|
||||||
.should('have.length', 5)
|
.should('have.length', 5)
|
||||||
|
|
||||||
cy.get('button').contains('deleteColumn')
|
cy.get('button').contains('Delete column')
|
||||||
.click()
|
.click()
|
||||||
.click()
|
.click()
|
||||||
cy.get('.tiptap table th')
|
cy.get('.tiptap table th')
|
||||||
@ -44,15 +44,15 @@ context('/src/Examples/Tables/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('adds & delete rows', () => {
|
it('adds & delete rows', () => {
|
||||||
cy.get('button').contains('addRowBefore').click()
|
cy.get('button').contains('Add row before').click()
|
||||||
cy.get('.tiptap table tr')
|
cy.get('.tiptap table tr')
|
||||||
.should('have.length', 4)
|
.should('have.length', 4)
|
||||||
|
|
||||||
cy.get('button').contains('addRowAfter').click()
|
cy.get('button').contains('Add row after').click()
|
||||||
cy.get('.tiptap table tr')
|
cy.get('.tiptap table tr')
|
||||||
.should('have.length', 5)
|
.should('have.length', 5)
|
||||||
|
|
||||||
cy.get('button').contains('deleteRow')
|
cy.get('button').contains('Delete row')
|
||||||
.click()
|
.click()
|
||||||
.click()
|
.click()
|
||||||
cy.get('.tiptap table tr')
|
cy.get('.tiptap table tr')
|
||||||
@ -60,21 +60,21 @@ context('/src/Examples/Tables/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should delete table', () => {
|
it('should delete table', () => {
|
||||||
cy.get('button').contains('deleteTable').click()
|
cy.get('button').contains('Delete table').click()
|
||||||
cy.get('.tiptap table').should('not.exist')
|
cy.get('.tiptap table').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should merge cells', () => {
|
it('should merge cells', () => {
|
||||||
cy.get('.tiptap').type('{shift}{rightArrow}')
|
cy.get('.tiptap').type('{shift}{rightArrow}')
|
||||||
cy.get('button').contains('mergeCells').click()
|
cy.get('button').contains('Merge cells').click()
|
||||||
cy.get('.tiptap table th').should('have.length', 2)
|
cy.get('.tiptap table th').should('have.length', 2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should split cells', () => {
|
it('should split cells', () => {
|
||||||
cy.get('.tiptap').type('{shift}{rightArrow}')
|
cy.get('.tiptap').type('{shift}{rightArrow}')
|
||||||
cy.get('button').contains('mergeCells').click()
|
cy.get('button').contains('Merge cells').click()
|
||||||
cy.get('.tiptap table th').should('have.length', 2)
|
cy.get('.tiptap table th').should('have.length', 2)
|
||||||
cy.get('button').contains('splitCell').click()
|
cy.get('button').contains('Split cell').click()
|
||||||
cy.get('.tiptap table th').should('have.length', 3)
|
cy.get('.tiptap table th').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,11 +94,11 @@ context('/src/Examples/Tables/React/', () => {
|
|||||||
|
|
||||||
it('should merge split', () => {
|
it('should merge split', () => {
|
||||||
cy.get('.tiptap').type('{shift}{rightArrow}')
|
cy.get('.tiptap').type('{shift}{rightArrow}')
|
||||||
cy.get('button').contains('mergeCells').click()
|
cy.get('button').contains('Merge cells').click()
|
||||||
cy.get('.tiptap th[colspan="2"]')
|
cy.get('.tiptap th[colspan="2"]')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
cy.get('button')
|
cy.get('button')
|
||||||
.contains('mergeOrSplit')
|
.contains('Merge or split')
|
||||||
.click()
|
.click()
|
||||||
cy.get('.tiptap th[colspan="2"]')
|
cy.get('.tiptap th[colspan="2"]')
|
||||||
.should('not.exist')
|
.should('not.exist')
|
||||||
@ -106,15 +106,15 @@ context('/src/Examples/Tables/React/', () => {
|
|||||||
|
|
||||||
it('should set cell attribute', () => {
|
it('should set cell attribute', () => {
|
||||||
cy.get('.tiptap').type('{downArrow}')
|
cy.get('.tiptap').type('{downArrow}')
|
||||||
cy.get('button').contains('setCellAttribute').click()
|
cy.get('button').contains('Set cell attribute').click()
|
||||||
cy.get('.tiptap table td[style]').should('have.attr', 'style', 'background-color: #FAF594')
|
cy.get('.tiptap table td[style]').should('have.attr', 'style', 'background-color: #FAF594')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should move focus to next or prev cell', () => {
|
it('should move focus to next or prev cell', () => {
|
||||||
cy.get('.tiptap').type('Column 1')
|
cy.get('.tiptap').type('Column 1')
|
||||||
cy.get('button').contains('goToNextCell').click()
|
cy.get('button').contains('Go to next cell').click()
|
||||||
cy.get('.tiptap').type('Column 2')
|
cy.get('.tiptap').type('Column 2')
|
||||||
cy.get('button').contains('goToPreviousCell').click()
|
cy.get('button').contains('Go to previous cell').click()
|
||||||
|
|
||||||
cy.get('.tiptap th').then(elements => {
|
cy.get('.tiptap th').then(elements => {
|
||||||
expect(elements[0].innerText).to.equal('Column 1')
|
expect(elements[0].innerText).to.equal('Column 1')
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
margin: 1rem 0;
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
> * + * {
|
|
||||||
margin-top: 0.75em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -18,62 +24,87 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Table-specific styling */
|
/* Table-specific styling */
|
||||||
.tiptap {
|
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
table-layout: fixed;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
min-width: 1em;
|
border: 1px solid var(--gray-3);
|
||||||
border: 2px solid #ced4da;
|
|
||||||
padding: 3px 5px;
|
|
||||||
vertical-align: top;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
min-width: 1em;
|
||||||
|
padding: 6px 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -81,37 +112,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
|
background-color: var(--gray-1);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: #f1f3f5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedCell:after {
|
.selectedCell:after {
|
||||||
z-index: 2;
|
background: var(--gray-2);
|
||||||
position: absolute;
|
|
||||||
content: "";
|
content: "";
|
||||||
left: 0; right: 0; top: 0; bottom: 0;
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
background: rgba(200, 200, 255, 0.4);
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-resize-handle {
|
.column-resize-handle {
|
||||||
|
background-color: var(--purple);
|
||||||
|
bottom: -2px;
|
||||||
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -2px;
|
right: -2px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: -2px;
|
|
||||||
width: 4px;
|
width: 4px;
|
||||||
background-color: #adf;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.tableWrapper {
|
.tableWrapper {
|
||||||
|
margin: 1.5rem 0;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-cursor {
|
.resize-cursor {
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
cursor: col-resize;
|
cursor: col-resize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ context('/src/Examples/Tables/Vue/', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.get('.tiptap').then(([{ editor }]) => {
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
editor.commands.clearContent()
|
editor.commands.clearContent()
|
||||||
cy.get('button').contains('insertTable').click()
|
cy.get('button').contains('Insert table').click()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -28,15 +28,15 @@ context('/src/Examples/Tables/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('adds & delete columns', () => {
|
it('adds & delete columns', () => {
|
||||||
cy.get('button').contains('addColumnBefore').click()
|
cy.get('button').contains('Add column before').click()
|
||||||
cy.get('.tiptap table th')
|
cy.get('.tiptap table th')
|
||||||
.should('have.length', 4)
|
.should('have.length', 4)
|
||||||
|
|
||||||
cy.get('button').contains('addColumnAfter').click()
|
cy.get('button').contains('Add column after').click()
|
||||||
cy.get('.tiptap table th')
|
cy.get('.tiptap table th')
|
||||||
.should('have.length', 5)
|
.should('have.length', 5)
|
||||||
|
|
||||||
cy.get('button').contains('deleteColumn')
|
cy.get('button').contains('Delete column')
|
||||||
.click()
|
.click()
|
||||||
.click()
|
.click()
|
||||||
cy.get('.tiptap table th')
|
cy.get('.tiptap table th')
|
||||||
@ -44,15 +44,15 @@ context('/src/Examples/Tables/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('adds & delete rows', () => {
|
it('adds & delete rows', () => {
|
||||||
cy.get('button').contains('addRowBefore').click()
|
cy.get('button').contains('Add row before').click()
|
||||||
cy.get('.tiptap table tr')
|
cy.get('.tiptap table tr')
|
||||||
.should('have.length', 4)
|
.should('have.length', 4)
|
||||||
|
|
||||||
cy.get('button').contains('addRowAfter').click()
|
cy.get('button').contains('Add row after').click()
|
||||||
cy.get('.tiptap table tr')
|
cy.get('.tiptap table tr')
|
||||||
.should('have.length', 5)
|
.should('have.length', 5)
|
||||||
|
|
||||||
cy.get('button').contains('deleteRow')
|
cy.get('button').contains('Delete row')
|
||||||
.click()
|
.click()
|
||||||
.click()
|
.click()
|
||||||
cy.get('.tiptap table tr')
|
cy.get('.tiptap table tr')
|
||||||
@ -60,21 +60,21 @@ context('/src/Examples/Tables/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should delete table', () => {
|
it('should delete table', () => {
|
||||||
cy.get('button').contains('deleteTable').click()
|
cy.get('button').contains('Delete table').click()
|
||||||
cy.get('.tiptap table').should('not.exist')
|
cy.get('.tiptap table').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should merge cells', () => {
|
it('should merge cells', () => {
|
||||||
cy.get('.tiptap').type('{shift}{rightArrow}')
|
cy.get('.tiptap').type('{shift}{rightArrow}')
|
||||||
cy.get('button').contains('mergeCells').click()
|
cy.get('button').contains('Merge cells').click()
|
||||||
cy.get('.tiptap table th').should('have.length', 2)
|
cy.get('.tiptap table th').should('have.length', 2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should split cells', () => {
|
it('should split cells', () => {
|
||||||
cy.get('.tiptap').type('{shift}{rightArrow}')
|
cy.get('.tiptap').type('{shift}{rightArrow}')
|
||||||
cy.get('button').contains('mergeCells').click()
|
cy.get('button').contains('Merge cells').click()
|
||||||
cy.get('.tiptap table th').should('have.length', 2)
|
cy.get('.tiptap table th').should('have.length', 2)
|
||||||
cy.get('button').contains('splitCell').click()
|
cy.get('button').contains('Split cell').click()
|
||||||
cy.get('.tiptap table th').should('have.length', 3)
|
cy.get('.tiptap table th').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,11 +94,11 @@ context('/src/Examples/Tables/Vue/', () => {
|
|||||||
|
|
||||||
it('should merge split', () => {
|
it('should merge split', () => {
|
||||||
cy.get('.tiptap').type('{shift}{rightArrow}')
|
cy.get('.tiptap').type('{shift}{rightArrow}')
|
||||||
cy.get('button').contains('mergeCells').click()
|
cy.get('button').contains('Merge cells').click()
|
||||||
cy.get('.tiptap th[colspan="2"]')
|
cy.get('.tiptap th[colspan="2"]')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
cy.get('button')
|
cy.get('button')
|
||||||
.contains('mergeOrSplit')
|
.contains('Merge or split')
|
||||||
.click()
|
.click()
|
||||||
cy.get('.tiptap th[colspan="2"]')
|
cy.get('.tiptap th[colspan="2"]')
|
||||||
.should('not.exist')
|
.should('not.exist')
|
||||||
@ -106,15 +106,15 @@ context('/src/Examples/Tables/Vue/', () => {
|
|||||||
|
|
||||||
it('should set cell attribute', () => {
|
it('should set cell attribute', () => {
|
||||||
cy.get('.tiptap').type('{downArrow}')
|
cy.get('.tiptap').type('{downArrow}')
|
||||||
cy.get('button').contains('setCellAttribute').click()
|
cy.get('button').contains('Set cell attribute').click()
|
||||||
cy.get('.tiptap table td[style]').should('have.attr', 'style', 'background-color: #FAF594')
|
cy.get('.tiptap table td[style]').should('have.attr', 'style', 'background-color: #FAF594')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should move focus to next or prev cell', () => {
|
it('should move focus to next or prev cell', () => {
|
||||||
cy.get('.tiptap').type('Column 1')
|
cy.get('.tiptap').type('Column 1')
|
||||||
cy.get('button').contains('goToNextCell').click()
|
cy.get('button').contains('Go to next cell').click()
|
||||||
cy.get('.tiptap').type('Column 2')
|
cy.get('.tiptap').type('Column 2')
|
||||||
cy.get('button').contains('goToPreviousCell').click()
|
cy.get('button').contains('Go to previous cell').click()
|
||||||
|
|
||||||
cy.get('.tiptap th').then(elements => {
|
cy.get('.tiptap th').then(elements => {
|
||||||
expect(elements[0].innerText).to.equal('Column 1')
|
expect(elements[0].innerText).to.equal('Column 1')
|
||||||
|
@ -1,61 +1,70 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()">
|
<button @click="editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()">
|
||||||
insertTable
|
Insert table
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="editor.chain().focus().insertContent(tableHTML, { parseOptions: { preserveWhitespace: false }}).run()"
|
||||||
|
>
|
||||||
|
Insert HTML table
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().addColumnBefore().run()" :disabled="!editor.can().addColumnBefore()">
|
<button @click="editor.chain().focus().addColumnBefore().run()" :disabled="!editor.can().addColumnBefore()">
|
||||||
addColumnBefore
|
Add column before
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().addColumnAfter().run()" :disabled="!editor.can().addColumnAfter()">
|
<button @click="editor.chain().focus().addColumnAfter().run()" :disabled="!editor.can().addColumnAfter()">
|
||||||
addColumnAfter
|
Add column after
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().deleteColumn().run()" :disabled="!editor.can().deleteColumn()">
|
<button @click="editor.chain().focus().deleteColumn().run()" :disabled="!editor.can().deleteColumn()">
|
||||||
deleteColumn
|
Delete column
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().addRowBefore().run()" :disabled="!editor.can().addRowBefore()">
|
<button @click="editor.chain().focus().addRowBefore().run()" :disabled="!editor.can().addRowBefore()">
|
||||||
addRowBefore
|
Add row before
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().addRowAfter().run()" :disabled="!editor.can().addRowAfter()">
|
<button @click="editor.chain().focus().addRowAfter().run()" :disabled="!editor.can().addRowAfter()">
|
||||||
addRowAfter
|
Add row after
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().deleteRow().run()" :disabled="!editor.can().deleteRow()">
|
<button @click="editor.chain().focus().deleteRow().run()" :disabled="!editor.can().deleteRow()">
|
||||||
deleteRow
|
Delete row
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().deleteTable().run()" :disabled="!editor.can().deleteTable()">
|
<button @click="editor.chain().focus().deleteTable().run()" :disabled="!editor.can().deleteTable()">
|
||||||
deleteTable
|
Delete table
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().mergeCells().run()" :disabled="!editor.can().mergeCells()">
|
<button @click="editor.chain().focus().mergeCells().run()" :disabled="!editor.can().mergeCells()">
|
||||||
mergeCells
|
Merge cells
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().splitCell().run()" :disabled="!editor.can().splitCell()">
|
<button @click="editor.chain().focus().splitCell().run()" :disabled="!editor.can().splitCell()">
|
||||||
splitCell
|
Split cell
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeaderColumn().run()" :disabled="!editor.can().toggleHeaderColumn()">
|
<button @click="editor.chain().focus().toggleHeaderColumn().run()" :disabled="!editor.can().toggleHeaderColumn()">
|
||||||
toggleHeaderColumn
|
Toggle header column
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeaderRow().run()" :disabled="!editor.can().toggleHeaderRow()">
|
<button @click="editor.chain().focus().toggleHeaderRow().run()" :disabled="!editor.can().toggleHeaderRow()">
|
||||||
toggleHeaderRow
|
Toggle header row
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeaderCell().run()" :disabled="!editor.can().toggleHeaderCell()">
|
<button @click="editor.chain().focus().toggleHeaderCell().run()" :disabled="!editor.can().toggleHeaderCell()">
|
||||||
toggleHeaderCell
|
Toggle header cell
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().mergeOrSplit().run()" :disabled="!editor.can().mergeOrSplit()">
|
<button @click="editor.chain().focus().mergeOrSplit().run()" :disabled="!editor.can().mergeOrSplit()">
|
||||||
mergeOrSplit
|
Merge or split
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setCellAttribute('backgroundColor', '#FAF594').run()" :disabled="!editor.can().setCellAttribute('backgroundColor', '#FAF594')">
|
<button @click="editor.chain().focus().setCellAttribute('backgroundColor', '#FAF594').run()" :disabled="!editor.can().setCellAttribute('backgroundColor', '#FAF594')">
|
||||||
setCellAttribute
|
Set cell attribute
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().fixTables().run()" :disabled="!editor.can().fixTables()">
|
<button @click="editor.chain().focus().fixTables().run()" :disabled="!editor.can().fixTables()">
|
||||||
fixTables
|
Fix tables
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().goToNextCell().run()" :disabled="!editor.can().goToNextCell()">
|
<button @click="editor.chain().focus().goToNextCell().run()" :disabled="!editor.can().goToNextCell()">
|
||||||
goToNextCell
|
Go to next cell
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().goToPreviousCell().run()" :disabled="!editor.can().goToPreviousCell()">
|
<button @click="editor.chain().focus().goToPreviousCell().run()" :disabled="!editor.can().goToPreviousCell()">
|
||||||
goToPreviousCell
|
Go to previous cell
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -95,6 +104,29 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editor: null,
|
editor: null,
|
||||||
|
tableHTML: `
|
||||||
|
<table style="width:100%">
|
||||||
|
<tr>
|
||||||
|
<th>Firstname</th>
|
||||||
|
<th>Lastname</th>
|
||||||
|
<th>Age</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Jill</td>
|
||||||
|
<td>Smith</td>
|
||||||
|
<td>50</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Eve</td>
|
||||||
|
<td>Jackson</td>
|
||||||
|
<td>94</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>John</td>
|
||||||
|
<td>Doe</td>
|
||||||
|
<td>80</td>
|
||||||
|
</tr>
|
||||||
|
</table>`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -117,9 +149,9 @@ export default {
|
|||||||
Have you seen our tables? They are amazing!
|
Have you seen our tables? They are amazing!
|
||||||
</h3>
|
</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>tables with rows, cells and headers (optional)</li>
|
<li>Tables with rows, cells and headers (optional)</li>
|
||||||
<li>support for <code>colgroup</code> and <code>rowspan</code></li>
|
<li>Support for <code>colgroup</code> and <code>rowspan</code></li>
|
||||||
<li>and even resizable columns (optional)</li>
|
<li>And even resizable columns (optional)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Here is an example:
|
Here is an example:
|
||||||
@ -132,20 +164,20 @@ export default {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cyndi Lauper</td>
|
<td>Cyndi Lauper</td>
|
||||||
<td>singer</td>
|
<td>Singer</td>
|
||||||
<td>songwriter</td>
|
<td>Songwriter</td>
|
||||||
<td>actress</td>
|
<td>Actress</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Marie Curie</td>
|
<td>Marie Curie</td>
|
||||||
<td>scientist</td>
|
<td>Scientist</td>
|
||||||
<td>chemist</td>
|
<td>Chemist</td>
|
||||||
<td>physicist</td>
|
<td>Physicist</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Indira Gandhi</td>
|
<td>Indira Gandhi</td>
|
||||||
<td>prime minister</td>
|
<td>Prime minister</td>
|
||||||
<td colspan="2">politician</td>
|
<td colspan="2">Politician</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -162,17 +194,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
margin: 1rem 0;
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
> * + * {
|
|
||||||
margin-top: 0.75em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -180,62 +218,87 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Table-specific styling */
|
/* Table-specific styling */
|
||||||
.tiptap {
|
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
table-layout: fixed;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
min-width: 1em;
|
border: 1px solid var(--gray-3);
|
||||||
border: 2px solid #ced4da;
|
|
||||||
padding: 3px 5px;
|
|
||||||
vertical-align: top;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
min-width: 1em;
|
||||||
|
padding: 6px 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -243,42 +306,39 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
|
background-color: var(--gray-1);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: #f1f3f5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedCell:after {
|
.selectedCell:after {
|
||||||
z-index: 2;
|
background: var(--gray-2);
|
||||||
position: absolute;
|
|
||||||
content: "";
|
content: "";
|
||||||
left: 0; right: 0; top: 0; bottom: 0;
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
background: rgba(200, 200, 255, 0.4);
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-resize-handle {
|
.column-resize-handle {
|
||||||
|
background-color: var(--purple);
|
||||||
|
bottom: -2px;
|
||||||
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -2px;
|
right: -2px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: -2px;
|
|
||||||
width: 4px;
|
width: 4px;
|
||||||
background-color: #adf;
|
}
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
.tableWrapper {
|
||||||
margin: 0;
|
margin: 1.5rem 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tableWrapper {
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-cursor {
|
.resize-cursor {
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
cursor: col-resize;
|
cursor: col-resize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,30 @@
|
|||||||
ul[data-type="taskList"] {
|
/* Basic editor styles */
|
||||||
|
.tiptap {
|
||||||
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Task list specific styles */
|
||||||
|
ul[data-type="taskList"] {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
> label {
|
> label {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@ -20,4 +40,5 @@ ul[data-type="taskList"] {
|
|||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,13 +59,33 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
ul[data-type="taskList"] {
|
/* Basic editor styles */
|
||||||
|
.tiptap {
|
||||||
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Task list specific styles */
|
||||||
|
ul[data-type="taskList"] {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
> label {
|
> label {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@ -81,5 +101,6 @@ ul[data-type="taskList"] {
|
|||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,70 +1,72 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div v-if="editor" class="container">
|
||||||
<div v-if="editor" class="menu">
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().clearNodes().run()">
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
h6
|
h6
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHardBreak().run()">
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().undo().run()">
|
<button @click="editor.chain().focus().undo().run()">
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().redo().run()">
|
<button @click="editor.chain().focus().redo().run()">
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -176,7 +178,7 @@ export default {
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -232,26 +234,26 @@ export default {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cyndi Lauper</td>
|
<td>Cyndi Lauper</td>
|
||||||
<td>singer</td>
|
<td>Singer</td>
|
||||||
<td>songwriter</td>
|
<td>Songwriter</td>
|
||||||
<td>actress</td>
|
<td>Actress</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Marie Curie</td>
|
<td>Marie Curie</td>
|
||||||
<td>scientist</td>
|
<td>Scientist</td>
|
||||||
<td>chemist</td>
|
<td>Chemist</td>
|
||||||
<td>physicist</td>
|
<td>Physicist</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Indira Gandhi</td>
|
<td>Indira Gandhi</td>
|
||||||
<td>prime minister</td>
|
<td>Prime minister</td>
|
||||||
<td colspan="2">politician</td>
|
<td colspan="2">Politician</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>This is a basic example of implementing images. Drag to re-order.</p>
|
<p>This is a basic example of implementing images. Drag to re-order.</p>
|
||||||
<img src="https://source.unsplash.com/8xznAGy4HcY/800x400" />
|
<img src="https://placehold.co/800x400" />
|
||||||
<img src="https://source.unsplash.com/K9QHL52rE2k/800x400" />
|
<img src="https://placehold.co/800x400/6A00F5/white" />
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -263,16 +265,73 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Placeholder (on every new line) */
|
||||||
|
.is-empty::before {
|
||||||
|
color: var(--gray-4);
|
||||||
|
content: attr(data-placeholder);
|
||||||
|
float: left;
|
||||||
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--purple);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--purple-contrast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Task list specific styles */
|
||||||
|
ul[data-type="taskList"] {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul[data-type="taskList"] {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -280,27 +339,64 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display empty p */
|
||||||
|
p:empty::before {
|
||||||
|
content: '\00a0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code styling */
|
||||||
.hljs-comment,
|
.hljs-comment,
|
||||||
.hljs-quote {
|
.hljs-quote {
|
||||||
color: #616161;
|
color: #616161;
|
||||||
@ -316,7 +412,7 @@ export default {
|
|||||||
.hljs-name,
|
.hljs-name,
|
||||||
.hljs-selector-id,
|
.hljs-selector-id,
|
||||||
.hljs-selector-class {
|
.hljs-selector-class {
|
||||||
color: #F98181;
|
color: #f98181;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-number,
|
.hljs-number,
|
||||||
@ -326,23 +422,23 @@ export default {
|
|||||||
.hljs-literal,
|
.hljs-literal,
|
||||||
.hljs-type,
|
.hljs-type,
|
||||||
.hljs-params {
|
.hljs-params {
|
||||||
color: #FBBC88;
|
color: #fbbc88;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-string,
|
.hljs-string,
|
||||||
.hljs-symbol,
|
.hljs-symbol,
|
||||||
.hljs-bullet {
|
.hljs-bullet {
|
||||||
color: #B9F18D;
|
color: #b9f18d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-title,
|
.hljs-title,
|
||||||
.hljs-section {
|
.hljs-section {
|
||||||
color: #FAF594;
|
color: #faf594;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-keyword,
|
.hljs-keyword,
|
||||||
.hljs-selector-tag {
|
.hljs-selector-tag {
|
||||||
color: #70CFF8;
|
color: #70cff8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-emphasis {
|
.hljs-emphasis {
|
||||||
@ -354,37 +450,91 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.code-block {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
select {
|
||||||
|
position: absolute;
|
||||||
|
background-color: var(--white);
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="Black" d="M7 10l5 5 5-5z"/></svg>');
|
||||||
|
right: 0.5rem;
|
||||||
|
top: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background-color: #FAF594;
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
box-decoration-break: clone;
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
display: block;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
&.ProseMirror-selectednode {
|
||||||
|
outline: 3px solid var(--purple);
|
||||||
|
transition: outline 0.15s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mention {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
box-decoration-break: clone;
|
||||||
|
color: var(--purple);
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color swatches */
|
||||||
|
.color {
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background-color: var(--color);
|
||||||
|
border: 1px solid rgba(128, 128, 128, 0.3);
|
||||||
|
border-radius: 2px;
|
||||||
|
content: " ";
|
||||||
|
display: inline-block;
|
||||||
|
height: 1em;
|
||||||
|
margin-bottom: 0.15em;
|
||||||
|
margin-right: 0.1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table-specific styling */
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
table-layout: fixed;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
min-width: 1em;
|
border: 1px solid var(--gray-3);
|
||||||
border: 2px solid #ced4da;
|
|
||||||
padding: 3px 5px;
|
|
||||||
vertical-align: top;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
min-width: 1em;
|
||||||
|
padding: 6px 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -392,87 +542,91 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
|
background-color: var(--gray-1);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: #f1f3f5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedCell:after {
|
.selectedCell:after {
|
||||||
z-index: 2;
|
background: var(--gray-2);
|
||||||
position: absolute;
|
|
||||||
content: "";
|
content: "";
|
||||||
left: 0; right: 0; top: 0; bottom: 0;
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
background: rgba(200, 200, 255, 0.4);
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-resize-handle {
|
.column-resize-handle {
|
||||||
|
background-color: var(--purple);
|
||||||
|
bottom: -2px;
|
||||||
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -2px;
|
right: -2px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: -2px;
|
|
||||||
width: 4px;
|
width: 4px;
|
||||||
background-color: #adf;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul[data-type="taskList"] {
|
.tableWrapper {
|
||||||
list-style: none;
|
margin: 1.5rem 0;
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
> label {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
> div {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tiptap p.is-empty::before {
|
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
|
||||||
color: #adb5bd;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tableWrapper {
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-cursor {
|
.resize-cursor {
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
cursor: col-resize;
|
cursor: col-resize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mention {
|
/* Floating/Bubble Menus */
|
||||||
border: 1px solid #000;
|
.bubble-menu {
|
||||||
border-radius: 0.4rem;
|
background-color: var(--white);
|
||||||
padding: 0.1rem 0.3rem;
|
border: 1px solid var(--gray-1);
|
||||||
box-decoration-break: clone;
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
display: flex;
|
||||||
|
padding: 0.2rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: unset;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background-color: var(--purple);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--purple-contrast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.floating-menu {
|
||||||
position: sticky;
|
display: flex;
|
||||||
top: 0;
|
background-color: var(--gray-3);
|
||||||
background: #fff;
|
padding: 0.1rem;
|
||||||
z-index: 1;
|
border-radius: 0.5rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: unset;
|
||||||
|
padding: 0.275rem 0.425rem;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background-color: var(--white);
|
||||||
|
color: var(--purple);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--purple-contrast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -15,7 +15,7 @@ context('/src/Experiments/CollaborationAnnotation/Vue/', () => {
|
|||||||
cy.window().then(win => {
|
cy.window().then(win => {
|
||||||
cy.stub(win, 'prompt', () => 'This is a test comment')
|
cy.stub(win, 'prompt', () => 'This is a test comment')
|
||||||
cy.get('.editor-1 .tiptap').type('{selectall}{backspace}Hello world{selectall}')
|
cy.get('.editor-1 .tiptap').type('{selectall}{backspace}Hello world{selectall}')
|
||||||
cy.get('button').contains('comment').eq(0).click()
|
cy.get('button').contains('Comment').eq(0).click()
|
||||||
cy.get('.editor-1 .tiptap').type('{end}')
|
cy.get('.editor-1 .tiptap').type('{end}')
|
||||||
cy.get('.tiptap .annotation').should('have.length', 2)
|
cy.get('.tiptap .annotation').should('have.length', 2)
|
||||||
cy.get('.comment').should('exist').contains('This is a test comment')
|
cy.get('.comment').should('exist').contains('This is a test comment')
|
||||||
@ -42,11 +42,11 @@ context('/src/Experiments/CollaborationAnnotation/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
cy.get('.editor-1 .tiptap').type('{selectall}{backspace}Hello world{selectall}')
|
cy.get('.editor-1 .tiptap').type('{selectall}{backspace}Hello world{selectall}')
|
||||||
cy.get('button').contains('comment').eq(0).click()
|
cy.get('button').contains('Comment').eq(0).click()
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('.editor-1 .tiptap').find('.annotation').click()
|
cy.get('.editor-1 .tiptap').find('.annotation').click()
|
||||||
cy.get('.comment').should('exist').contains('This is a test comment')
|
cy.get('.comment').should('exist').contains('This is a test comment')
|
||||||
cy.get('button').contains('update').click()
|
cy.get('button').contains('Update').click()
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('.comment').should('exist').contains('This is the new comment')
|
cy.get('.comment').should('exist').contains('This is the new comment')
|
||||||
})
|
})
|
||||||
@ -57,11 +57,11 @@ context('/src/Experiments/CollaborationAnnotation/Vue/', () => {
|
|||||||
cy.stub(win, 'prompt', () => 'This is a test comment')
|
cy.stub(win, 'prompt', () => 'This is a test comment')
|
||||||
|
|
||||||
cy.get('.editor-1 .tiptap').type('{selectall}{backspace}Hello world{selectall}')
|
cy.get('.editor-1 .tiptap').type('{selectall}{backspace}Hello world{selectall}')
|
||||||
cy.get('button').contains('comment').eq(0).click()
|
cy.get('button').contains('Comment').eq(0).click()
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('.editor-1 .tiptap').find('.annotation').click()
|
cy.get('.editor-1 .tiptap').find('.annotation').click()
|
||||||
cy.get('.comment').should('exist').contains('This is a test comment')
|
cy.get('.comment').should('exist').contains('This is a test comment')
|
||||||
cy.get('button').contains('remove').click()
|
cy.get('button').contains('Remove').click()
|
||||||
cy.get('.tiptap .annotation').should('not.exist')
|
cy.get('.tiptap .annotation').should('not.exist')
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
cy.get('.comment').should('not.exist')
|
cy.get('.comment').should('not.exist')
|
||||||
|
@ -1,31 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
<h2>
|
<div class="control-group">
|
||||||
Original Editor
|
<h2>Original Editor</h2>
|
||||||
</h2>
|
<div class="button-group">
|
||||||
<button @click="addComment" :disabled="!editor.can().addAnnotation()">
|
<button @click="addComment" :disabled="!editor.can().addAnnotation()">
|
||||||
comment
|
Comment
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content class="editor-1" :editor="editor" />
|
<editor-content class="editor-1" :editor="editor" />
|
||||||
<div class="comment" v-for="comment in comments" :key="comment.id">
|
|
||||||
|
<div class="output-group" v-for="comment in comments" :key="comment.id">
|
||||||
{{ comment }}
|
{{ comment }}
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
<button @click="updateComment(comment.id)">
|
<button @click="updateComment(comment.id)">
|
||||||
update
|
Update
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button @click="deleteComment(comment.id)">
|
<button @click="deleteComment(comment.id)">
|
||||||
remove
|
Remove
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>
|
<div class="control-group">
|
||||||
Another Editor
|
<h2>Another Editor</h2>
|
||||||
</h2>
|
<div class="button-group">
|
||||||
<button @click="addAnotherComment" :disabled="!anotherEditor.can().addAnnotation()">
|
<button @click="addAnotherComment" :disabled="!anotherEditor.can().addAnnotation()">
|
||||||
comment
|
Comment
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content class="editor-2" :editor="anotherEditor" />
|
<editor-content class="editor-2" :editor="anotherEditor" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -80,7 +87,7 @@ export default {
|
|||||||
Annotations can be used to add additional information to the content, for example comments. They live on a different level than the actual editor content.
|
Annotations can be used to add additional information to the content, for example comments. They live on a different level than the actual editor content.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This example allows you to add plain text, but you’re free to add more complex data, for example JSON from another tiptap instance. :-)
|
This example allows you to add plain text, but you’re free to add more complex data, for example JSON from another Tiptap instance. :-)
|
||||||
</p>
|
</p>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
@ -138,8 +145,44 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="items">
|
<div class="dropdown-menu">
|
||||||
<template v-if="items.length">
|
<template v-if="items.length">
|
||||||
<button
|
<button
|
||||||
class="item"
|
|
||||||
:class="{ 'is-selected': index === selectedIndex }"
|
:class="{ 'is-selected': index === selectedIndex }"
|
||||||
v-for="(item, index) in items"
|
v-for="(item, index) in items"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="selectItem(index)"
|
@click="selectItem(index)"
|
||||||
>
|
>
|
||||||
{{ item }}
|
{{ item.title }}
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<div class="item" v-else>
|
<div class="item" v-else>
|
||||||
@ -87,32 +86,35 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.items {
|
/* Dropdown menu */
|
||||||
padding: 0.2rem;
|
.dropdown-menu {
|
||||||
|
background: var(--white);
|
||||||
|
border: 1px solid var(--gray-1);
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.4rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 0.5rem;
|
|
||||||
background: #FFF;
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(0, 0, 0, 0.05),
|
|
||||||
0px 10px 20px rgba(0, 0, 0, 0.1),
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
button {
|
||||||
display: block;
|
align-items: center;
|
||||||
margin: 0;
|
background-color: transparent;
|
||||||
width: 100%;
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background: transparent;
|
width: 100%;
|
||||||
border-radius: 0.4rem;
|
|
||||||
border: 1px solid transparent;
|
&:hover,
|
||||||
padding: 0.2rem 0.4rem;
|
&:hover.is-selected {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
&.is-selected {
|
&.is-selected {
|
||||||
border-color: #000;
|
background-color: var(--gray-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -19,8 +19,8 @@ context('/src/Experiments/Commands/Vue/', () => {
|
|||||||
|
|
||||||
items.forEach((item, i) => {
|
items.forEach((item, i) => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}/')
|
cy.get('.tiptap').type('{selectall}{backspace}/')
|
||||||
cy.get('.tippy-content .items').should('exist')
|
cy.get('.tippy-content .dropdown-menu').should('exist')
|
||||||
cy.get('.tippy-content .items .item').eq(i).click()
|
cy.get('.tippy-content .dropdown-menu button').eq(i).click()
|
||||||
cy.get('.tiptap').type(`I am a ${item.tag}`)
|
cy.get('.tiptap').type(`I am a ${item.tag}`)
|
||||||
cy.get(`.tiptap ${item.tag}`).should('exist').should('have.text', `I am a ${item.tag}`)
|
cy.get(`.tiptap ${item.tag}`).should('exist').should('have.text', `I am a ${item.tag}`)
|
||||||
})
|
})
|
||||||
@ -28,17 +28,17 @@ context('/src/Experiments/Commands/Vue/', () => {
|
|||||||
|
|
||||||
it('should close the popup without any command via esc', () => {
|
it('should close the popup without any command via esc', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}/')
|
cy.get('.tiptap').type('{selectall}{backspace}/')
|
||||||
cy.get('.tippy-content .items').should('exist')
|
cy.get('.tippy-content .dropdown-menu').should('exist')
|
||||||
cy.get('.tiptap').type('{esc}')
|
cy.get('.tiptap').type('{esc}')
|
||||||
cy.get('.tippy-content .items').should('not.exist')
|
cy.get('.tippy-content .dropdown-menu').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should open the popup when the cursor is after a slash', () => {
|
it('should open the popup when the cursor is after a slash', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}/')
|
cy.get('.tiptap').type('{selectall}{backspace}/')
|
||||||
cy.get('.tippy-content .items').should('exist')
|
cy.get('.tippy-content .dropdown-menu').should('exist')
|
||||||
cy.get('.tiptap').type('{leftArrow}')
|
cy.get('.tiptap').type('{leftArrow}')
|
||||||
cy.get('.tippy-content .items').should('not.exist')
|
cy.get('.tippy-content .dropdown-menu').should('not.exist')
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('.tippy-content .items').should('exist')
|
cy.get('.tippy-content .dropdown-menu').should('exist')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -45,16 +45,95 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mention {
|
|
||||||
border: 1px solid #000;
|
|
||||||
border-radius: 0.4rem;
|
|
||||||
padding: 0.1rem 0.3rem;
|
|
||||||
box-decoration-break: clone;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -7,7 +7,7 @@ export default {
|
|||||||
items: ({ query }) => {
|
items: ({ query }) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: 'H1',
|
title: 'Heading 1',
|
||||||
command: ({ editor, range }) => {
|
command: ({ editor, range }) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
@ -18,7 +18,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'H2',
|
title: 'Heading 2',
|
||||||
command: ({ editor, range }) => {
|
command: ({ editor, range }) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
@ -29,7 +29,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bold',
|
title: 'Bold',
|
||||||
command: ({ editor, range }) => {
|
command: ({ editor, range }) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
@ -40,7 +40,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'italic',
|
title: 'Italic',
|
||||||
command: ({ editor, range }) => {
|
command: ({ editor, range }) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="() => editor.chain().toggleBold().focus().run()">Make bold</button>
|
<button @click="() => editor.chain().toggleBold().focus().run()">Make bold</button>
|
||||||
<button @click="() => editor.destroy()">Destroy editor</button>
|
<button @click="() => editor.destroy()">Destroy editor</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="editor">
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -41,9 +43,95 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="addIframe">
|
<button @click="addIframe">
|
||||||
add iframe
|
Add iFrame
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -18,7 +18,7 @@ export default () => {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
This is a radically reduced version of tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
This is a radically reduced version of Tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
||||||
@ -28,8 +28,10 @@ export default () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
reactive storage: {editor?.storage.custom.foo}
|
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
|
<div className="output-group">
|
||||||
|
Reactive storage: {editor?.storage.custom.foo}
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
reactive storage: {{ editor?.storage.custom.foo }}
|
<div class="container">
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
<div class="output-group">
|
||||||
|
Reactive storage: {{ editor?.storage.custom.foo }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -32,7 +36,7 @@ export default {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
This is a radically reduced version of tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
This is a radically reduced version of Tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
The paragraph extension is not really required, but you need at least one node. Sure, that node can be something different.
|
||||||
@ -50,8 +54,8 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="addFigure">
|
<button @click="addFigure">
|
||||||
figure
|
Add image with caption
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="editor.chain().focus().imageToFigure().run()"
|
@click="editor.chain().focus().imageToFigure().run()"
|
||||||
:disabled="!editor.can().imageToFigure()"
|
:disabled="!editor.can().imageToFigure()"
|
||||||
>
|
>
|
||||||
image to figure
|
Add caption to image
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="editor.chain().focus().figureToImage().run()"
|
@click="editor.chain().focus().figureToImage().run()"
|
||||||
:disabled="!editor.can().figureToImage()"
|
:disabled="!editor.can().figureToImage()"
|
||||||
>
|
>
|
||||||
figure to image
|
Remove caption from image
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
|
||||||
<h2>HTML</h2>
|
<div class="output-group">
|
||||||
{{ editor.getHTML() }}
|
<label>HTML</label>
|
||||||
|
<code>{{ editor.getHTML() }}</code>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -65,14 +71,14 @@ export default {
|
|||||||
content: `
|
content: `
|
||||||
<p>Figure + Figcaption</p>
|
<p>Figure + Figcaption</p>
|
||||||
<figure>
|
<figure>
|
||||||
<img src="https://source.unsplash.com/8xznAGy4HcY/800x400" alt="Random photo of something" title="Who’s dat?">
|
<img src="https://placehold.co/800x400/orange/white" alt="Random photo of something" title="Who’s dat?">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
<p>Amazing caption</p>
|
<p>Amazing caption</p>
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
<img src="https://source.unsplash.com/K9QHL52rE2k/800x400">
|
<img src="https://placehold.co/800x400/green/white">
|
||||||
<img src="https://source.unsplash.com/8xznAGy4HcY/800x400">
|
<img src="https://placehold.co/800x400/blue/white">
|
||||||
<img src="https://source.unsplash.com/K9QHL52rE2k/800x400">
|
<img src="https://placehold.co/800x400/black/white">
|
||||||
<p>That’s it.</p>
|
<p>That’s it.</p>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
@ -85,32 +91,136 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
figure {
|
/* List styles */
|
||||||
max-width: 25rem;
|
ul,
|
||||||
border: 3px solid #0D0D0D;
|
ol {
|
||||||
border-radius: 0.5rem;
|
padding: 0 1rem;
|
||||||
margin: 1rem 0;
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
padding: 0.5rem;
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
figcaption {
|
/* Heading styles */
|
||||||
margin-top: 0.25rem;
|
h1,
|
||||||
text-align: center;
|
h2,
|
||||||
padding: 0.5rem;
|
h3,
|
||||||
border: 2px dashed #0D0D0D20;
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: min(100%, 25rem);
|
|
||||||
height: auto;
|
height: auto;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
&.ProseMirror-selectednode {
|
||||||
|
outline: 3px solid var(--purple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure */
|
||||||
|
figure {
|
||||||
|
align-items: start;
|
||||||
|
border: 2px solid var(--black);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding: 0.5rem;
|
||||||
|
width: fit-content;
|
||||||
|
|
||||||
|
> *:not(figcaption) {
|
||||||
|
margin: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:has(figcaption:active) {
|
||||||
|
border-color: var(--purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
figcaption {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border: 2px dashed #0D0D0D20;
|
||||||
|
padding: 0.5rem;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="addCapturedTable">
|
<button @click="addCapturedTable">
|
||||||
add table
|
Add table with caption
|
||||||
</button>
|
</button>
|
||||||
<button @click="addCapturedImage">
|
<button @click="addCapturedImage">
|
||||||
add image
|
Add image with caption
|
||||||
</button>
|
</button>
|
||||||
<button @click="removeCapturedTable">
|
<button @click="removeCapturedTable">
|
||||||
remove table
|
Remove table with caption
|
||||||
</button>
|
</button>
|
||||||
<button @click="removeCapturedImage">
|
<button @click="removeCapturedImage">
|
||||||
remove image
|
Remove image with caption
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -62,14 +66,14 @@ export default {
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: 'image caption',
|
text: 'Image caption',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'image',
|
type: 'image',
|
||||||
attrs: {
|
attrs: {
|
||||||
src: 'https://source.unsplash.com/K9QHL52rE2k/800x400',
|
src: 'https://placehold.co/800x400/orange/white',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -89,7 +93,7 @@ export default {
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: 'table caption',
|
text: 'Table caption',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -107,7 +111,7 @@ export default {
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: 'cell 1',
|
text: 'Cell 1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -121,7 +125,7 @@ export default {
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: 'cell 2',
|
text: 'Cell 2',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -172,10 +176,10 @@ export default {
|
|||||||
<figcaption>
|
<figcaption>
|
||||||
Image caption
|
Image caption
|
||||||
</figcaption>
|
</figcaption>
|
||||||
<img src="https://source.unsplash.com/8xznAGy4HcY/800x400" alt="Random photo of something" title="Who’s dat?">
|
<img src="https://placehold.co/800x400/black/white" alt="Random photo of something" title="Who’s dat?">
|
||||||
</figure>
|
</figure>
|
||||||
<p>Some text</p>
|
<p>Some text</p>
|
||||||
<img src="https://source.unsplash.com/K9QHL52rE2k/800x400">
|
<img src="https://placehold.co/800x400">
|
||||||
<p>Some text</p>
|
<p>Some text</p>
|
||||||
<figure data-type="capturedTable">
|
<figure data-type="capturedTable">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
@ -189,20 +193,20 @@ export default {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cyndi Lauper</td>
|
<td>Cyndi Lauper</td>
|
||||||
<td>singer</td>
|
<td>Singer</td>
|
||||||
<td>songwriter</td>
|
<td>Songwriter</td>
|
||||||
<td>actress</td>
|
<td>Actress</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Marie Curie</td>
|
<td>Marie Curie</td>
|
||||||
<td>scientist</td>
|
<td>Scientist</td>
|
||||||
<td>chemist</td>
|
<td>Chemist</td>
|
||||||
<td>physicist</td>
|
<td>Physicist</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Indira Gandhi</td>
|
<td>Indira Gandhi</td>
|
||||||
<td>prime minister</td>
|
<td>Prime minister</td>
|
||||||
<td colspan="2">politician</td>
|
<td colspan="2">Politician</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -216,20 +220,20 @@ export default {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cyndi Lauper</td>
|
<td>Cyndi Lauper</td>
|
||||||
<td>singer</td>
|
<td>Singer</td>
|
||||||
<td>songwriter</td>
|
<td>Songwriter</td>
|
||||||
<td>actress</td>
|
<td>Actress</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Marie Curie</td>
|
<td>Marie Curie</td>
|
||||||
<td>scientist</td>
|
<td>Scientist</td>
|
||||||
<td>chemist</td>
|
<td>Chemist</td>
|
||||||
<td>physicist</td>
|
<td>Physicist</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Indira Gandhi</td>
|
<td>Indira Gandhi</td>
|
||||||
<td>prime minister</td>
|
<td>Prime minister</td>
|
||||||
<td colspan="2">politician</td>
|
<td colspan="2">Politician</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -244,57 +248,123 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
|
||||||
max-width: 25rem;
|
|
||||||
border: 3px solid #0D0D0D;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
padding: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
figcaption {
|
|
||||||
margin: 0.25rem 0;
|
|
||||||
text-align: center;
|
|
||||||
padding: 0.5rem;
|
|
||||||
border: 2px dashed #0D0D0D20;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
/* List styles */
|
||||||
margin-bottom: 0;
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: min(100%, 25rem);
|
|
||||||
height: auto;
|
height: auto;
|
||||||
border-radius: 0.5rem;
|
margin: 1.5rem 0;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
&.ProseMirror-selectednode {
|
||||||
|
outline: 3px solid var(--purple);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
table-layout: fixed;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
min-width: 1em;
|
border: 1px solid var(--gray-3);
|
||||||
border: 2px solid #ced4da;
|
|
||||||
padding: 3px 5px;
|
|
||||||
vertical-align: top;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
min-width: 1em;
|
||||||
|
padding: 6px 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -302,28 +372,68 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
|
background-color: var(--gray-1);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: #f1f3f5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedCell:after {
|
.selectedCell:after {
|
||||||
z-index: 2;
|
background: var(--gray-2);
|
||||||
position: absolute;
|
|
||||||
content: "";
|
content: "";
|
||||||
left: 0; right: 0; top: 0; bottom: 0;
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
background: rgba(200, 200, 255, 0.4);
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-resize-handle {
|
.column-resize-handle {
|
||||||
|
background-color: var(--purple);
|
||||||
|
bottom: -2px;
|
||||||
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -2px;
|
right: -2px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: -2px;
|
|
||||||
width: 4px;
|
width: 4px;
|
||||||
background-color: #adf;
|
}
|
||||||
pointer-events: none;
|
}
|
||||||
|
|
||||||
|
.tableWrapper {
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-cursor {
|
||||||
|
cursor: ew-resize;
|
||||||
|
cursor: col-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure */
|
||||||
|
figure {
|
||||||
|
align-items: start;
|
||||||
|
border: 2px solid var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding: 0.5rem;
|
||||||
|
width: fit-content;
|
||||||
|
|
||||||
|
> *:not(figcaption) {
|
||||||
|
margin: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:has(figcaption:active) {
|
||||||
|
border-color: var(--purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
figcaption {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border: 2px dashed #0D0D0D20;
|
||||||
|
padding: 0.5rem;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,14 @@ export default {
|
|||||||
DragHandle,
|
DragHandle,
|
||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>paragraph 1</p>
|
<p>Paragraph 1</p>
|
||||||
<p>paragraph 2</p>
|
<p>Paragraph 2</p>
|
||||||
<p>paragraph 3</p>
|
<p>Paragraph 3</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>list item 1</li>
|
<li>List item 1</li>
|
||||||
<li>list item 2</li>
|
<li>List item 2</li>
|
||||||
</ul>
|
</ul>
|
||||||
<pre>code</pre>
|
<pre>Code</pre>
|
||||||
`,
|
`,
|
||||||
onUpdate: () => {
|
onUpdate: () => {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
|
@ -33,7 +33,8 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
disabled={
|
disabled={
|
||||||
@ -45,7 +46,7 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('bold') ? 'is-active' : ''}
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
@ -58,7 +59,7 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('italic') ? 'is-active' : ''}
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
@ -71,7 +72,7 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('strike') ? 'is-active' : ''}
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
@ -84,85 +85,85 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('code') ? 'is-active' : ''}
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||||
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().undo().run()}
|
onClick={() => editor.chain().focus().undo().run()}
|
||||||
@ -174,7 +175,7 @@ const MenuBar = ({ editor }) => {
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().redo().run()}
|
onClick={() => editor.chain().focus().redo().run()}
|
||||||
@ -186,15 +187,16 @@ const MenuBar = ({ editor }) => {
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setColor('#958DF1').run()}
|
onClick={() => editor.chain().focus().setColor('#958DF1').run()}
|
||||||
className={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
className={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
purple
|
Purple
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,9 +212,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user