Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
* text=auto
*.ts text eol=crlf
*.tsx text eol=crlf
*.json text eol=crlf
*.css text eol=crlf
*.scss text eol=crlf
*.html text eol=crlf
*.yaml text eol=crlf
*.yml text eol=crlf
2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nodeLinker: node-modules
nodeLinker: node-modules
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"goober": "^2.1.18",
"preact": "^10.27.2",
"quill": "^2.0.3",
"sn-extension-api": "0.4.0"
"sn-extension-api": "0.4.0",
"highlight.js": "^11.11.1"
},
"devDependencies": {
"@babel/core": "^7.28.5",
Expand Down
33 changes: 31 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions public/ext.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"name": "Quill",
"content_type": "SN|Component",
"area": "editor-editor",
"note_type": "rich-text",
"file_type": "json",
"version": "$VERSION$",
"description": "A rich text editor using the quill library",
"url": "https://nienow.github.io/sn-quill/",
Expand Down
2 changes: 2 additions & 0 deletions public/local.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"name": "Quill (local)",
"content_type": "SN|Component",
"area": "editor-editor",
"note_type": "rich-text",
"file_type": "json",
"version": "0.0.1",
"url": "http://localhost:8080/"
}
84 changes: 65 additions & 19 deletions src/QuillEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,66 @@ import {styled} from "goober";

import Quill from 'quill';
import './quill.css';
import hljs from 'highlight.js';
import './hljs.css';

const CODE_LANGUAGES = [
{ key: 'plain', label: 'Plain' },
{ key: 'asciidoc', label: 'Asciidoc' },
{ key: 'bash', label: 'Bash' },
{ key: 'c', label: 'C' },
{ key: 'cpp', label: 'C++' },
{ key: 'csharp', label: 'C#' },
{ key: 'css', label: 'CSS' },
{ key: 'csv', label: 'CSV' },
{ key: 'diff', label: 'Diff' },
{ key: 'elixir', label: 'Elixir' },
{ key: 'go', label: 'Go' },
{ key: 'html', label: 'HTML' },
{ key: 'java', label: 'Java' },
{ key: 'javascript', label: 'JavaScript' },
{ key: 'json', label: 'JSON' },
{ key: 'jsx', label: 'JSX' },
{ key: 'kotlin', label: 'Kotlin' },
{ key: 'lua', label: 'Lua' },
{ key: 'markdown', label: 'Markdown' },
{ key: 'nix', label: 'Nix' },
{ key: 'perl', label: 'Perl' },
{ key: 'php', label: 'PHP' },
{ key: 'python', label: 'Python' },
{ key: 'ruby', label: 'Ruby' },
{ key: 'rust', label: 'Rust' },
{ key: 'scss', label: 'SCSS' },
{ key: 'shell', label: 'Shell' },
{ key: 'solidity', label: 'Solidity' },
{ key: 'sql', label: 'SQL' },
{ key: 'swift', label: 'Swift' },
{ key: 'toml', label: 'TOML' },
{ key: 'tsx', label: 'TSX' },
{ key: 'typescript', label: 'TypeScript' },
{ key: 'xml', label: 'XML' },
{ key: 'yaml', label: 'YAML' },
{ key: 'zig', label: 'Zig' },
];
import {MarkdownShortcuts} from "./quill-markdown";
import snApi from "sn-extension-api";
import {getPreviewText} from "./utils";

// Register Quill modules/formats once at module load time
const Font = Quill.import('attributors/class/font') as { whitelist: (string | boolean)[] };
Font.whitelist = [false, 'serif', 'sans-serif', 'monospace', 'arial', 'comic-sans'];
Quill.register(Font as any, true);
Quill.register('modules/markdown', MarkdownShortcuts, true);

const BlockEmbed = Quill.import('blots/block/embed') as { new(): any };
class DividerBlot extends BlockEmbed {
static blotName = 'divider';
static tagName = 'hr';
}
Quill.register(DividerBlot as any, true);

(Quill.import('ui/icons') as Record<string, string>).divider = '<svg viewBox="0 0 18 18" class="ql-fill"><rect height="2" width="14" x="2" y="8"></rect></svg>';

const Container = styled('div')`
position: absolute;
top: 0;
Expand All @@ -17,37 +73,27 @@ const Container = styled('div')`
flex-direction: column;
`;

const HLJS_MAX_LENGTH = 5000;

const QuillEditor = () => {
let quill;
useEffect(() => {
const Font = Quill.import('attributors/class/font');
Font.whitelist = [false, 'serif', 'sans-serif', 'monospace', 'arial', 'comic-sans'];
Quill.register(Font, true);
Quill.register('modules/markdown', MarkdownShortcuts);
const BlockEmbed = Quill.import('blots/block/embed');

class DividerBlot extends BlockEmbed {
}

DividerBlot.blotName = 'divider';
DividerBlot.tagName = 'hr';
Quill.register(DividerBlot);

Quill.import('ui/icons').divider = '<svg viewBox="0 0 18 18" class="ql-fill"><rect height="2" width="14" x="2" y="8"></rect></svg>';
const initialText = snApi.text;
const enableSyntax = !initialText || initialText.length <= HLJS_MAX_LENGTH;

quill = new Quill(`#quill`, {
readOnly: snApi.locked,
modules: {
toolbar: [
[{'font': Font.whitelist}, {'header': '1'}, {'header': '2'}, 'bold', 'italic', 'underline', 'strike', 'blockquote', 'code', 'link', 'image', 'divider', {'list': 'ordered'}, {'list': 'bullet'}, {'align': []}, {'color': []}, {'background': []}, 'clean'],
[{'font': Font.whitelist}, {'header': '1'}, {'header': '2'}, 'bold', 'italic', 'underline', 'strike', 'blockquote', 'code-block', 'link', 'image', 'divider', {'list': 'ordered'}, {'list': 'bullet'}, {'align': []}, {'color': []}, {'background': []}, 'clean'],
],
keyboard: {
bindings: {
'keep-font': {
key: 'Enter',
handler: function (range, context) {
handler: function (_range, context) {
setTimeout(() => {
// keep font style
// keep font style on new lines
this.quill.format('font', context.format.font, Quill.sources.USER);
});
return true;
Expand All @@ -56,10 +102,10 @@ const QuillEditor = () => {
}
},
markdown: {},
syntax: enableSyntax ? { hljs, languages: CODE_LANGUAGES } : false,
},
theme: 'snow',
});
const initialText = snApi.text;
if (initialText) {
try {
const data = JSON.parse(initialText);
Expand All @@ -84,7 +130,7 @@ const QuillEditor = () => {
snApi.text = JSON.stringify(quill.getContents());
snApi.preview = getPreviewText(quill.getText());
});
});
}, []);

return (
<Container>
Expand Down
23 changes: 23 additions & 0 deletions src/demo/test-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,29 @@ export const RICH = {
},
'insert': 'Red Background'
},
{
'insert': '\n\n'
},
{
'attributes': {
},
'insert': 'const language = "JavaScript";'
},
{
'attributes': {
'code-block': 'javascript'
},
'insert': '\n'
},
{
'insert': 'console.log("I love " + language + "!");'
},
{
'attributes': {
'code-block': true
},
'insert': '\n'
},
{
'insert': '\n'
}
Expand Down
84 changes: 84 additions & 0 deletions src/hljs.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}

code.hljs {
padding: 3px 5px
}

.hljs {
color: var(--sn-stylekit-foreground-color);
background: var(--sn-stylekit-background-color)
}

.hljs-comment,
.hljs-quote {
color: var(--sn-stylekit-passive-color-1);
font-style: italic
}

.hljs-doctag,
.hljs-formula,
.hljs-keyword {
color: var(--sn-stylekit-accessory-tint-color-4)
}

.hljs-deletion,
.hljs-name,
.hljs-section,
.hljs-selector-tag,
.hljs-subst {
color: var(--sn-stylekit-accessory-tint-color-2)
}

.hljs-literal {
color: var(--sn-stylekit-accessory-tint-color-1)
}

.hljs-addition,
.hljs-attribute,
.hljs-meta .hljs-string,
.hljs-regexp,
.hljs-string {
color: var(--sn-stylekit-accessory-tint-color-5)
}

.hljs-attr,
.hljs-number,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-pseudo,
.hljs-template-variable,
.hljs-type,
.hljs-variable {
color: var(--sn-stylekit-accessory-tint-color-6)
}

.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-symbol,
.hljs-title {
color: var(--sn-stylekit-accessory-tint-color-1)
}

.hljs-built_in,
.hljs-class .hljs-title,
.hljs-title.class_ {
color: var(--sn-stylekit-accessory-tint-color-3)
}

.hljs-emphasis {
font-style: italic
}

.hljs-strong {
font-weight: 700
}

.hljs-link {
text-decoration: underline
}
Loading