Skip to content

Commit 043a4a0

Browse files
committed
feature/Replace highlight js with codemirror
1 parent 385c6ed commit 043a4a0

File tree

15 files changed

+147
-142
lines changed

15 files changed

+147
-142
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.CodeMirror.cm-s-one-light{color:#383a42;background-color:#fafafa}.cm-s-one-light .CodeMirror-selected{background-color:#c3c3c3}.cm-s-one-light .CodeMirror-gutter,.cm-s-one-light .CodeMirror-gutters{border:none;background-color:#fafafa}.cm-s-one-light .CodeMirror-linenumber,.cm-s-one-light .CodeMirror-linenumbers{color:#929292!important;background-color:transparent}.cm-s-one-light .CodeMirror-lines{color:#27292f!important;background-color:transparent}.cm-s-one-light .CodeMirror-cursor{border-left:2px solid #526fff!important}.cm-s-one-light .cm-header{color:#e45649}.cm-s-one-light .cm-quote{color:#a0a1a7;font-style:italic}.cm-s-one-light .cm-negative{color:#e45649}.cm-s-one-light .cm-positive{color:#e45649}.cm-s-one-light .cm-strong{color:#986801;font-weight:700}.cm-s-one-light .cm-header .cm-strong{color:#986801;font-weight:700}.cm-s-one-light .cm-em{color:#a626a4;font-style:italic}.cm-s-one-light .cm-header .cm-em{color:#a626a4;font-style:italic}.cm-s-one-light .cm-tag{color:#e45649}.cm-s-one-light .cm-attribute{color:#d19a66}.cm-s-one-light .cm-link{color:#4078f2;border-bottom:solid 1px #4078f2}.cm-s-one-light .cm-string.cm-url{color:#0184bc;border-bottom:solid 1px #0184bc}.cm-s-one-light .cm-builtin{color:#e45649}.cm-s-one-light .cm-keyword{color:#a626a4}.cm-s-one-light .cm-def{color:#4078f2}.cm-s-one-light .cm-atom{color:#d19a66}.cm-s-one-light .cm-number{color:#986801}.cm-s-one-light .cm-property{color:#4078f2}.cm-s-one-light .cm-qualifier{color:#986801}.cm-s-one-light .cm-variable{color:#e06c75}.cm-s-one-light .cm-variable-2{color:#e45649}.cm-s-one-light .cm-string{color:#50a14f}.cm-s-one-light .cm-punctuation{color:#383a42}.cm-s-one-light .cm-operator{color:#0184bc}.cm-s-one-light .cm-meta{color:#383a42}.cm-s-one-light .cm-bracket{color:#383a42}.cm-s-one-light .cm-comment{color:#a0a1a7;font-style:italic}.cm-s-one-light .cm-error{color:#e06c75}.cm-s-one-light .cm-m-css.cm-variable{color:#828997}.cm-s-one-light .cm-m-css.cm-property{color:#383a42}.cm-s-one-light .cm-m-css.cm-atom{color:#0184bc}.cm-s-one-light .cm-m-css.cm-builtin{color:#56b6c2}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Controller } from 'stimulus';
2+
import CodeMirror from 'codemirror';
3+
import 'codemirror/mode/ruby/ruby.js'
4+
// import 'codemirror/theme/duotone-dark.css'
5+
6+
export default class extends Controller {
7+
static targets = ["wrapper", "mirror", "body", "description"];
8+
static values = {
9+
code: String,
10+
initialized: Boolean,
11+
readOnly: Boolean
12+
}
13+
14+
connect() {
15+
if (this.shouldInitialize()) {
16+
this.initializeCodeMirror()
17+
this.setCodeMirrorValue()
18+
this.addEventListeners()
19+
}
20+
}
21+
22+
initializeCodeMirror() {
23+
this.codeMirror = CodeMirror.fromTextArea(this.mirrorTarget, {
24+
theme: 'one-light',
25+
mode: 'ruby',
26+
readOnly: this.readOnlyValue ? 'nocursor' : false
27+
});
28+
29+
this.initializedValue = true
30+
}
31+
32+
setCodeMirrorValue() {
33+
const value = this.hasCodeValue ? this.codeValue : ''
34+
this.codeMirror.setValue(value)
35+
}
36+
37+
shouldInitialize() {
38+
return !this.initializedValue
39+
}
40+
41+
addEventListeners() {
42+
var editor = document.querySelector('.CodeMirror');
43+
44+
editor.addEventListener("click", (event) => {
45+
event.stopPropagation()
46+
})
47+
}
48+
}

app/javascript/controllers/highlight_controller.js

Lines changed: 0 additions & 35 deletions
This file was deleted.

app/javascript/controllers/snippets_controller.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
import { Controller } from 'stimulus';
22
import { events } from "../mixins/events";
33
import axios from 'axios';
4+
import CodeMirror from 'codemirror';
5+
import 'codemirror/mode/javascript/javascript.js'
6+
47

58
export default class extends Controller {
69
static targets = ["moveButton", "listItem", "errors"];
710

811

912
initialize() {
13+
14+
// console.log(CodeMirror)
15+
16+
// var myCodeMirror = CodeMirror(this.element, {
17+
// value: "function myScript(){return 100;}\n",
18+
// mode: "javascript"
19+
// });
20+
1021
const csrfToken = document.querySelector("meta[name=csrf-token]").content
1122
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken
1223
}

app/javascript/packs/application.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// that code so it'll be compiled.
55
import 'controllers'
66

7+
require("codemirror")
78
require("axios")
89
require("lodash")
910
require("marked")

app/javascript/stylesheets/application.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
@import "tailwindcss/base";
22
@import "tailwindcss/components";
33
@import "tailwindcss/utilities";
4+
@import 'codemirror/lib/codemirror.css';
5+
6+
.CodeMirror {
7+
/* Set height, width, borders, and global font properties here */
8+
@apply font-mono p-2 rounded-lg border text-sm;
9+
height: auto;
10+
color: black;
11+
direction: ltr;
12+
// overflow-y: scroll;
13+
}
14+
15+
@import '../../assets/stylesheets/themes/one-light.scss';
416

517
// HEADINGS
618

app/models/snippet.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,9 @@ def language_label
5050
"<span style='border-radius: 5px; position: absolute; top: -13px; right: 25px; border: 1px solid lightgrey; font-family: monospace; padding: 4px 28px 4px 10px; background-color: snow;'><i style='position: absolute; right: 7px;' class='devicon-ruby-plain colored'></i>#{ language.name }</span>"
5151
end
5252

53-
def highlighted
54-
Pygments.highlight(
55-
body,
56-
lexer: language.lexer_alias,
57-
options: { encoding: 'utf-8', linenos: false }
58-
).html_safe
53+
# Prevent needing to do on the fly by saving to db
54+
def preview
55+
body.split("\n").first(15).join("\n")
5956
end
6057

6158
def client_id
Lines changed: 24 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,30 @@
1-
<div data-controller="tabs">
2-
<div class="tabs--headers-container">
3-
<div><h1></h1></div>
4-
<div class="tabs--headers-wrapper">
5-
<div data-target="tabs.tab" data-action="click->tabs#change" class="tabs--header tabs--header-active">
6-
<span>Write</span>
7-
</div>
8-
<div data-target="tabs.tab" data-action="click->tabs#change" class="tabs--header">
9-
<span>Preview</span>
10-
</div>
11-
</div>
12-
</div>
13-
14-
<div data-controller="highlight snippets">
15-
<div data-target="snippets.errors"></div>
16-
<%= form_for @snippet, remote: true, html: { data: { type: "html", action: "ajax:success->snippets#onUpdateSuccess ajax:error->snippets#onUpdateError" } } do |f| %>
17-
<div class="tabs-details">
18-
<div data-target="tabs.panel">
19-
<%= f.text_field :description, { class: "new-snippet--description", placeholder: "Snippet description..." } %>
20-
<%= f.text_area :body, { data: { action: "input->highlight#highlight" }, class: "new-snippet--body", placeholder: "Snippet body..." } %>
21-
<%= f.text_area :highlighted_body, { data: { target: "highlight.highlightedBody" }, class: "hidden" } %>
22-
</div>
1+
<div data-controller="snippets">
2+
<div data-snippets-target="errors"></div>
233

24-
<div data-target="tabs.panel" class="hidden">
25-
<div class="new-snippet--preview">
26-
<div class="code-highlight" data-target="highlight.code">
27-
<%= raw(@snippet.highlighted_body) %>
28-
</div>
29-
</div>
30-
</div>
31-
</div>
4+
<%= form_for @snippet, remote: true, html: { data: { type: "html", action: "ajax:success->snippets#onUpdateSuccess ajax:error->snippets#onUpdateError" } } do |f| %>
5+
<div>
6+
<%= f.text_field :description, { class: "new-snippet--description", placeholder: "Snippet description..." } %>
7+
<%= f.text_area :body, { data: { controller: "codemirror", codemirror_code_value: @snippet.body, codemirror_initialized_value: false, codemirror_read_only_value: false, codemirror_target: 'mirror' }, class: "font-mono h-80 block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" } %>
8+
</div>
329

33-
<div class="create-snippet--options-wrapper">
34-
<div class="flex v-center" style="cursor: pointer;"
35-
data-controller="checkbox"
36-
data-action="click->checkbox#toggle"
37-
data-checkbox-checked-text-value="Public"
38-
data-checkbox-checked-icon-value="/icons/lock-open.svg"
39-
data-checkbox-unchecked-text-value="Private"
40-
data-checkbox-unchecked-icon-value="/icons/lock-closed.svg"
41-
>
42-
<span data-checkbox-target="text">Public</span>
43-
<img data-checkbox-target="icon" src="/icons/lock-open.svg" width="20">
44-
<%= f.hidden_field :public, value: true, data: { checkbox_target: 'value' } %>
45-
</div>
46-
<div class="flex">
47-
<%= f.select :folder_id, options_from_collection_for_select(@folders, :id, :name, @folder.id), prompt: 'Select folder...' %>
48-
<%= f.submit 'Update', class: "button--cta-primary ml-4" %>
49-
</div>
10+
<div class="create-snippet--options-wrapper">
11+
<div class="flex v-center" style="cursor: pointer;"
12+
data-controller="checkbox"
13+
data-action="click->checkbox#toggle"
14+
data-checkbox-checked-text-value="Public"
15+
data-checkbox-checked-icon-value="/icons/lock-open.svg"
16+
data-checkbox-unchecked-text-value="Private"
17+
data-checkbox-unchecked-icon-value="/icons/lock-closed.svg"
18+
>
19+
<span data-checkbox-target="text">Public</span>
20+
<img data-checkbox-target="icon" src="/icons/lock-open.svg" width="20">
21+
<%= f.hidden_field :public, value: true, data: { checkbox_target: 'value' } %>
5022
</div>
23+
<div class="flex">
24+
<%= f.select :folder_id, options_from_collection_for_select(@folders, :id, :name, @folder.id), prompt: 'Select folder...' %>
25+
<%= f.submit 'Update', class: "button--cta-primary ml-4" %>
5126
</div>
52-
<% end %>
27+
</div>
28+
<% end %>
5329

54-
</div>
5530
</div>
Lines changed: 23 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,30 @@
11
<h3 class="text-center">New Snippet</h3>
22

3-
<div data-controller="tabs">
4-
<div class="flex justify-end">
5-
<div class="tabs--headers-wrapper">
6-
<div data-tabs-target="tab" data-action="click->tabs#change" class="tabs--header tabs--header-active">
7-
<span>Write</span>
8-
</div>
9-
<div data-tabs-target="tab" data-action="click->tabs#change" class="tabs--header">
10-
<span>Preview</span>
11-
</div>
3+
<div data-controller="codemirror snippets" class="mt-4">
4+
<div data-snippets-target="errors"></div>
5+
<%= form_for @snippet, remote: true, html: { data: { type: "html", action: "ajax:success->snippets#onCreateSuccess ajax:error->snippets#onCreateError" } } do |f| %>
6+
<div>
7+
<%= f.text_field :description, { data: { controller: "focus", focus_target: "focus" }, placeholder: "Snippet title", class: "block w-full mb-4 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" } %>
8+
<%= f.text_area :body, { data: { codemirror_target: 'mirror' }, class: "font-mono h-80 block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" } %>
129
</div>
13-
</div>
14-
15-
<div data-controller="highlight snippets" class="mt-4">
16-
<div data-snippets-target="errors"></div>
17-
<%= form_for @snippet, remote: true, html: { data: { type: "html", action: "ajax:success->snippets#onCreateSuccess ajax:error->snippets#onCreateError" } } do |f| %>
18-
<div class="tabs-details">
19-
<div data-tabs-target="panel">
20-
<%= f.text_field :description, { data: { controller: "focus", focus_target: "focus", action: "input->highlight#updateDescription" }, placeholder: "Snippet title", class: "block w-full mb-4 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" } %>
21-
<%= f.text_area :body, { data: { action: "input->highlight#highlight" }, placeholder: "Your world beating code goes here", class: "font-mono h-80 block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" } %>
22-
<%= f.text_area :highlighted_body, { data: { target: "highlight.highlightedBody" }, class: "hidden" } %>
23-
</div>
2410

25-
<div data-tabs-target="panel" class="hidden">
26-
<div class="new-snippet--preview">
27-
<h5 data-highlight-target="description" class="mt-4 mb-4"></h5>
28-
<div class="code-highlight" data-highlight-target="code"></div>
29-
</div>
30-
</div>
11+
<div class="create-snippet--options-wrapper">
12+
<div class="flex v-center" style="cursor: pointer;"
13+
data-controller="checkbox"
14+
data-action="click->checkbox#toggle"
15+
data-checkbox-checked-text-value="Public"
16+
data-checkbox-checked-icon-value="/icons/lock-open.svg"
17+
data-checkbox-unchecked-text-value="Private"
18+
data-checkbox-unchecked-icon-value="/icons/lock-closed.svg"
19+
>
20+
<span data-checkbox-target="text">Public</span>
21+
<img data-checkbox-target="icon" src="/icons/lock-open.svg" width="20">
22+
<%= f.hidden_field :public, value: true, data: { checkbox_target: 'value' } %>
3123
</div>
32-
33-
<div class="create-snippet--options-wrapper">
34-
<div class="flex v-center" style="cursor: pointer;"
35-
data-controller="checkbox"
36-
data-action="click->checkbox#toggle"
37-
data-checkbox-checked-text-value="Public"
38-
data-checkbox-checked-icon-value="/icons/lock-open.svg"
39-
data-checkbox-unchecked-text-value="Private"
40-
data-checkbox-unchecked-icon-value="/icons/lock-closed.svg"
41-
>
42-
<span data-checkbox-target="text">Public</span>
43-
<img data-checkbox-target="icon" src="/icons/lock-open.svg" width="20">
44-
<%= f.hidden_field :public, value: true, data: { checkbox_target: 'value' } %>
45-
</div>
46-
<div class="flex">
47-
<%= f.select :folder_id, options_from_collection_for_select(@folders, :id, :name, params[:folder_id]), prompt: 'Select folder...' %>
48-
<%= f.submit 'CREATE', class: "button--cta-primary ml-4" %>
49-
</div>
24+
<div class="flex">
25+
<%= f.select :folder_id, options_from_collection_for_select(@folders, :id, :name, params[:folder_id]), prompt: 'Select folder...' %>
26+
<%= f.submit 'CREATE', class: "button--cta-primary ml-4" %>
5027
</div>
51-
<% end %>
52-
53-
</div>
28+
</div>
29+
<% end %>
5430
</div>

app/views/shared/_code_highlight.html.erb

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)