mirror of
https://github.com/aljazceru/CTFd.git
synced 2026-02-15 11:14:20 +01:00
Switch from raw textareas to easymde for challenge/hint content (#1496)
* Convert textareas for hint content and challenge content into EasyMDE editors. * Works on #1493
This commit is contained in:
@@ -4,6 +4,7 @@ from CTFd.admin import admin
|
||||
from CTFd.models import Pages
|
||||
from CTFd.schemas.pages import PageSchema
|
||||
from CTFd.utils import markdown
|
||||
from CTFd.utils.config.pages import build_html
|
||||
from CTFd.utils.decorators import admins_only
|
||||
|
||||
|
||||
@@ -26,7 +27,7 @@ def pages_preview():
|
||||
data = request.form.to_dict()
|
||||
schema = PageSchema()
|
||||
page = schema.load(data)
|
||||
return render_template("page.html", content=markdown(page.data.content))
|
||||
return render_template("page.html", content=build_html(page.data["content"]))
|
||||
|
||||
|
||||
@admin.route("/admin/pages/<int:page_id>")
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
CTFd.plugin.run((_CTFd) => {
|
||||
const $ = _CTFd.lib.$
|
||||
const md = _CTFd.lib.markdown()
|
||||
$('a[href="#new-desc-preview"]').on('shown.bs.tab', function (event) {
|
||||
if (event.target.hash == '#new-desc-preview') {
|
||||
var editor_value = $('#new-desc-editor').val();
|
||||
$(event.target.hash).html(
|
||||
md.render(editor_value)
|
||||
);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@import "~codemirror/lib/codemirror.css";
|
||||
.CodeMirror {
|
||||
@import "includes/easymde.scss";
|
||||
.CodeMirror.cm-s-default {
|
||||
font-size: 12px;
|
||||
border: 1px solid lightgray;
|
||||
}
|
||||
|
||||
382
CTFd/themes/admin/assets/css/includes/easymde.scss
Normal file
382
CTFd/themes/admin/assets/css/includes/easymde.scss
Normal file
@@ -0,0 +1,382 @@
|
||||
.CodeMirror.cm-s-easymde {
|
||||
box-sizing: border-box;
|
||||
height: auto;
|
||||
border: 1px solid lightgray;
|
||||
padding: 10px;
|
||||
font: inherit;
|
||||
z-index: 0;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.editor-toolbar {
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
padding: 0 10px;
|
||||
border-top: 1px solid #bbb;
|
||||
border-left: 1px solid #bbb;
|
||||
border-right: 1px solid #bbb;
|
||||
}
|
||||
|
||||
.editor-toolbar:after,
|
||||
.editor-toolbar:before {
|
||||
display: block;
|
||||
content: " ";
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.editor-toolbar:before {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.editor-toolbar:after {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.editor-toolbar.fullscreen {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
border: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 1;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.editor-toolbar.fullscreen::before {
|
||||
width: 20px;
|
||||
height: 50px;
|
||||
background: -moz-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 1) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
right top,
|
||||
color-stop(0%, rgba(255, 255, 255, 1)),
|
||||
color-stop(100%, rgba(255, 255, 255, 0))
|
||||
);
|
||||
background: -webkit-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 1) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: -o-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 1) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: -ms-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 1) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
rgba(255, 255, 255, 1) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.editor-toolbar.fullscreen::after {
|
||||
width: 20px;
|
||||
height: 50px;
|
||||
background: -moz-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 100%
|
||||
);
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
right top,
|
||||
color-stop(0%, rgba(255, 255, 255, 0)),
|
||||
color-stop(100%, rgba(255, 255, 255, 1))
|
||||
);
|
||||
background: -webkit-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 100%
|
||||
);
|
||||
background: -o-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 100%
|
||||
);
|
||||
background: -ms-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 100%
|
||||
);
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 100%
|
||||
);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.editor-toolbar button,
|
||||
.editor-toolbar .easymde-dropdown {
|
||||
background: transparent;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
height: 30px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.editor-toolbar button {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.editor-toolbar button.active,
|
||||
.editor-toolbar button:hover {
|
||||
background: #fcfcfc;
|
||||
border-color: #95a5a6;
|
||||
}
|
||||
|
||||
.editor-toolbar i.separator {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
border-left: 1px solid #d9d9d9;
|
||||
border-right: 1px solid #fff;
|
||||
color: transparent;
|
||||
text-indent: -10px;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.editor-toolbar button:after {
|
||||
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
|
||||
font-size: 65%;
|
||||
vertical-align: text-bottom;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.editor-toolbar button.heading-1:after {
|
||||
content: "1";
|
||||
}
|
||||
|
||||
.editor-toolbar button.heading-2:after {
|
||||
content: "2";
|
||||
}
|
||||
|
||||
.editor-toolbar button.heading-3:after {
|
||||
content: "3";
|
||||
}
|
||||
|
||||
.editor-toolbar button.heading-bigger:after {
|
||||
content: "▲";
|
||||
}
|
||||
|
||||
.editor-toolbar button.heading-smaller:after {
|
||||
content: "▼";
|
||||
}
|
||||
|
||||
.editor-toolbar.disabled-for-preview button:not(.no-disable) {
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px) {
|
||||
.editor-toolbar i.no-mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.editor-statusbar {
|
||||
padding: 8px 10px;
|
||||
font-size: 12px;
|
||||
color: #959694;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.editor-statusbar span {
|
||||
display: inline-block;
|
||||
min-width: 4em;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.editor-statusbar .lines:before {
|
||||
content: "lines: ";
|
||||
}
|
||||
|
||||
.editor-statusbar .words:before {
|
||||
content: "words: ";
|
||||
}
|
||||
|
||||
.editor-statusbar .characters:before {
|
||||
content: "characters: ";
|
||||
}
|
||||
|
||||
.editor-preview-full {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 7;
|
||||
overflow: auto;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.editor-preview-side {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 50%;
|
||||
top: 50px;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
overflow: auto;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ddd;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.editor-preview-active-side {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.editor-preview-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.editor-preview {
|
||||
padding: 10px;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.editor-preview > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.editor-preview pre {
|
||||
background: #eee;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.editor-preview table td,
|
||||
.editor-preview table th {
|
||||
border: 1px solid #ddd;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-tag {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-attribute {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-string {
|
||||
color: #183691;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-header-1 {
|
||||
font-size: 200%;
|
||||
line-height: 200%;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-header-2 {
|
||||
font-size: 160%;
|
||||
line-height: 160%;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-header-3 {
|
||||
font-size: 125%;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-header-4 {
|
||||
font-size: 110%;
|
||||
line-height: 110%;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-comment {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-link {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-url {
|
||||
color: #aab2b3;
|
||||
}
|
||||
|
||||
.cm-s-easymde .cm-quote {
|
||||
color: #7f8c8d;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.editor-toolbar .easymde-dropdown {
|
||||
position: relative;
|
||||
background: linear-gradient(
|
||||
to bottom right,
|
||||
#fff 0%,
|
||||
#fff 84%,
|
||||
#333 50%,
|
||||
#333 100%
|
||||
);
|
||||
border-radius: 0;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.editor-toolbar .easymde-dropdown:hover {
|
||||
background: linear-gradient(
|
||||
to bottom right,
|
||||
#fff 0%,
|
||||
#fff 84%,
|
||||
#333 50%,
|
||||
#333 100%
|
||||
);
|
||||
}
|
||||
|
||||
.easymde-dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #f9f9f9;
|
||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
|
||||
padding: 8px;
|
||||
z-index: 2;
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
.easymde-dropdown:active .easymde-dropdown-content,
|
||||
.easymde-dropdown:focus .easymde-dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
@@ -6,14 +6,13 @@ export function showHintModal(event) {
|
||||
event.preventDefault();
|
||||
$("#hint-edit-modal form")
|
||||
.find("input, textarea")
|
||||
.val("");
|
||||
.val("")
|
||||
// Trigger a change on the textarea to get codemirror to clone changes in
|
||||
.trigger("change");
|
||||
|
||||
// Markdown Preview
|
||||
$("#new-hint-edit").on("shown.bs.tab", function(event) {
|
||||
if (event.target.hash == "#hint-preview") {
|
||||
const renderer = CTFd.lib.markdown();
|
||||
const editor_value = $("#hint-write textarea").val();
|
||||
$(event.target.hash).html(renderer.render(editor_value));
|
||||
$("#hint-edit-form textarea").each(function(i, e) {
|
||||
if (e.hasOwnProperty("codemirror")) {
|
||||
e.codemirror.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -37,21 +36,33 @@ export function showEditHintModal(event) {
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.success) {
|
||||
$("#hint-edit-form input[name=content],textarea[name=content]").val(
|
||||
response.data.content
|
||||
);
|
||||
$("#hint-edit-form input[name=content],textarea[name=content]")
|
||||
.val(response.data.content)
|
||||
// Trigger a change on the textarea to get codemirror to clone changes in
|
||||
.trigger("change");
|
||||
|
||||
$("#hint-edit-modal")
|
||||
.on("shown.bs.modal", function() {
|
||||
$("#hint-edit-form textarea").each(function(i, e) {
|
||||
if (e.hasOwnProperty("codemirror")) {
|
||||
e.codemirror.refresh();
|
||||
}
|
||||
});
|
||||
})
|
||||
.on("hide.bs.modal", function() {
|
||||
$("#hint-edit-form textarea").each(function(i, e) {
|
||||
$(e)
|
||||
.val("")
|
||||
.trigger("change");
|
||||
if (e.hasOwnProperty("codemirror")) {
|
||||
e.codemirror.refresh();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#hint-edit-form input[name=cost]").val(response.data.cost);
|
||||
$("#hint-edit-form input[name=id]").val(response.data.id);
|
||||
|
||||
// Markdown Preview
|
||||
$("#new-hint-edit").on("shown.bs.tab", function(event) {
|
||||
if (event.target.hash == "#hint-preview") {
|
||||
const renderer = CTFd.lib.markdown();
|
||||
const editor_value = $("#hint-write textarea").val();
|
||||
$(event.target.hash).html(renderer.render(editor_value));
|
||||
}
|
||||
});
|
||||
|
||||
$("#hint-edit-modal").modal();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import { default as helpers } from "core/helpers";
|
||||
import { addFile, deleteFile } from "../challenges/files";
|
||||
import { addTag, deleteTag } from "../challenges/tags";
|
||||
import { addRequirement, deleteRequirement } from "../challenges/requirements";
|
||||
import { bindMarkdownEditors } from "../styles";
|
||||
import {
|
||||
showHintModal,
|
||||
editHint,
|
||||
@@ -133,6 +134,7 @@ function loadChalTemplate(challenge) {
|
||||
$.getScript(CTFd.config.urlRoot + challenge.scripts.view, function() {
|
||||
let template_data = challenge.create;
|
||||
$("#create-chal-entry-div").html(template_data);
|
||||
bindMarkdownEditors();
|
||||
|
||||
$.getScript(CTFd.config.urlRoot + challenge.scripts.create, function() {
|
||||
$("#create-chal-entry-div form").submit(function(event) {
|
||||
|
||||
@@ -1,6 +1,42 @@
|
||||
import "bootstrap/dist/js/bootstrap.bundle";
|
||||
import { makeSortableTables } from "core/utils";
|
||||
import $ from "jquery";
|
||||
import EasyMDE from "easymde";
|
||||
|
||||
export function bindMarkdownEditors() {
|
||||
$("textarea.markdown").each(function(_i, e) {
|
||||
if (e.hasOwnProperty("mde") === false) {
|
||||
let mde = new EasyMDE({
|
||||
autoDownloadFontAwesome: false,
|
||||
toolbar: [
|
||||
"bold",
|
||||
"italic",
|
||||
"heading",
|
||||
"|",
|
||||
"quote",
|
||||
"unordered-list",
|
||||
"ordered-list",
|
||||
"|",
|
||||
"link",
|
||||
"image",
|
||||
"|",
|
||||
"preview",
|
||||
"guide"
|
||||
],
|
||||
element: this,
|
||||
initialValue: $(this).val(),
|
||||
forceSync: true,
|
||||
minHeight: "200px"
|
||||
});
|
||||
this.mde = mde;
|
||||
this.codemirror = mde.codemirror;
|
||||
$(this).on("change keyup paste", function() {
|
||||
mde.codemirror.getDoc().setValue($(this).val());
|
||||
mde.codemirror.refresh();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default () => {
|
||||
// TODO: This is kind of a hack to mimic a React-like state construct.
|
||||
@@ -96,6 +132,7 @@ export default () => {
|
||||
}
|
||||
}
|
||||
|
||||
bindMarkdownEditors();
|
||||
makeSortableTables();
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
284
CTFd/themes/admin/static/js/vendor.bundle.min.js
vendored
284
CTFd/themes/admin/static/js/vendor.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -10,6 +10,7 @@
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme='core', path='css/fonts.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme='core', path='css/main.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme='admin', path='css/admin.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('views.themes', theme='admin', path='css/codemirror.css') }}">
|
||||
<script type="text/javascript">
|
||||
var init = {
|
||||
'urlRoot': "{{ request.script_root }}",
|
||||
|
||||
@@ -28,30 +28,14 @@
|
||||
|
||||
|
||||
{% block message %}
|
||||
<ul class="nav nav-tabs" role="tablist" id="new-desc-edit">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#new-desc-write" aria-controls="home" role="tab"
|
||||
data-toggle="tab" tabindex="-1">Write</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#new-desc-preview" aria-controls="home" role="tab" data-toggle="tab" tabindex="-1">Preview</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="new-desc-write">
|
||||
<div class="form-group">
|
||||
<label>
|
||||
Message:<br>
|
||||
<small class="form-text text-muted">
|
||||
Use this to give a brief introduction to your challenge.
|
||||
</small>
|
||||
</label>
|
||||
<textarea id="new-desc-editor" class="form-control" name="description" rows="10"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane content" id="new-desc-preview" style="height:234px; overflow-y: scroll;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
Message:<br>
|
||||
<small class="form-text text-muted">
|
||||
Use this to give a brief introduction to your challenge.
|
||||
</small>
|
||||
</label>
|
||||
<textarea id="new-desc-editor" class="form-control markdown" name="description" rows="10"></textarea>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
Use this to give a brief introduction to your challenge.
|
||||
</small>
|
||||
</label>
|
||||
<textarea id="desc-editor" class="form-control chal-desc-editor" name="description" rows="10">{{ challenge.description }}</textarea>
|
||||
<textarea id="desc-editor" class="form-control chal-desc-editor markdown" name="description" rows="10">{{ challenge.description }}</textarea>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('views.themes', theme='admin', path='css/codemirror.css') }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@@ -18,29 +18,12 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ul class="nav nav-tabs" role="tablist" id="new-hint-edit">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#hint-write" aria-controls="home" role="tab"
|
||||
data-toggle="tab">Write</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#hint-preview" aria-controls="home" role="tab"
|
||||
data-toggle="tab">Preview</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="hint-write">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">
|
||||
Hint<br>
|
||||
<small>Markdown & HTML are supported</small>
|
||||
</label>
|
||||
<textarea type="text" class="form-control" name="content" rows="7"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane content" id="hint-preview" style="height:234px; overflow-y: scroll;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="text-muted">
|
||||
Hint<br>
|
||||
<small>Markdown & HTML are supported</small>
|
||||
</label>
|
||||
<textarea type="text" class="form-control markdown" name="content" rows="7"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"bootstrap-multimodal": "~1.0.4",
|
||||
"codemirror": "~5.42.2",
|
||||
"css-loader": "~2.1.0",
|
||||
"easymde": "^2.10.1",
|
||||
"echarts": "^4.8.0",
|
||||
"eslint": "~5.12.0",
|
||||
"event-source-polyfill": "~1.0.7",
|
||||
|
||||
31
yarn.lock
31
yarn.lock
@@ -1489,6 +1489,18 @@ code-point-at@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codemirror-spell-checker@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz#1c660f9089483ccb5113b9ba9ca19c3f4993371e"
|
||||
integrity sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=
|
||||
dependencies:
|
||||
typo-js "*"
|
||||
|
||||
codemirror@^5.52.2:
|
||||
version "5.54.0"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.54.0.tgz#82b6adf662b29eeb7b867fe7839d49e25e4a0b38"
|
||||
integrity sha512-Pgf3surv4zvw+KaW3doUU7pGjF0BPU8/sj7eglWJjzni46U/DDW8pu3nZY0QgQKUcICDXRkq8jZmq0y6KhxM3Q==
|
||||
|
||||
codemirror@~5.42.2:
|
||||
version "5.42.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.42.2.tgz#801ab715a7a7e1c7ed4162b78e9d8138b98de8f0"
|
||||
@@ -2103,6 +2115,15 @@ duplexify@^3.4.2, duplexify@^3.6.0:
|
||||
readable-stream "^2.0.0"
|
||||
stream-shift "^1.0.0"
|
||||
|
||||
easymde@^2.10.1:
|
||||
version "2.10.1"
|
||||
resolved "https://registry.yarnpkg.com/easymde/-/easymde-2.10.1.tgz#671836ed08033def1a4379bfa2d193994c46471d"
|
||||
integrity sha512-khKYfB18ZYbkJAGEeQXaV2ZZ1QS7BavNj2xdcPGpO8GXi30qA9bVxzswGW8QNZQRmPtaXiQDG236Yv/BQY7P2A==
|
||||
dependencies:
|
||||
codemirror "^5.52.2"
|
||||
codemirror-spell-checker "1.1.2"
|
||||
marked "^0.8.2"
|
||||
|
||||
ecc-jsbn@~0.1.1:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
|
||||
@@ -3755,6 +3776,11 @@ markdown-it@~10.0.0:
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
marked@^0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-0.8.2.tgz#4faad28d26ede351a7a1aaa5fec67915c869e355"
|
||||
integrity sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==
|
||||
|
||||
md5.js@^1.3.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||
@@ -6188,6 +6214,11 @@ typeface-raleway@~0.0.54:
|
||||
resolved "https://registry.yarnpkg.com/typeface-raleway/-/typeface-raleway-0.0.54.tgz#f166c517becc81f34d14e72736d28b8923c79c65"
|
||||
integrity sha512-oilrvv0fV+z4eYvfTAl6t9Oq1mE/ZrLDPM71TrcAtqyVb0QzAJ6hQBS+FQcYdHxK2LGQE+gloQUPtwgY2I7WxA==
|
||||
|
||||
typo-js@*:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.1.0.tgz#a5a9f592bcb453666bf70c9694da58705d025ed8"
|
||||
integrity sha512-W3kLbx+ML9PBl5Bzso/lTvVxk4BCveSNAtQeht59FEtxCdGThmn6wSHA4Xq3eQYAK24NHdisMM4JmsK0GFy/pg==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
|
||||
Reference in New Issue
Block a user