1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-08-08 06:55:26 +02:00

Landing + mobile adoptation

This commit is contained in:
Peter Savchenko 2019-02-14 17:42:02 +03:00
parent d1e48cbb64
commit 5fbae537c2
No known key found for this signature in database
GPG key ID: 63E739583C761566
26 changed files with 1492 additions and 1038 deletions

View file

@ -1,5 +1,5 @@
{
"title": "CodeX Editor   🤩🧦🤨",
"title": "Editor.js   🤩🧦🤨",
"menu": [
"Guides",
"API",

1
.gitignore vendored
View file

@ -70,3 +70,4 @@ typings/
# Cache of babel and others
.cache/
.eslintcache
.DS_Store

View file

@ -14,7 +14,12 @@
"@babel/polyfill": "^7.0.0",
"body-parser": "latest",
"codex.editor": "^2.1.3",
"codex.editor.delimiter": "^1.0.2",
"codex.editor.embed": "^2.1.2",
"codex.editor.header": "^2.0.5",
"codex.editor.image": "^2.0.3",
"codex.editor.quote": "^2.1.5",
"codex.editor.raw": "^2.0.2",
"cookie-parser": "~1.4.3",
"debug": "~4.1.0",
"eslint-plugin-standard": "^4.0.0",
@ -40,8 +45,8 @@
"chai": "^4.1.2",
"chai-http": "^4.0.0",
"codex.editor.code": "^2.0.0",
"codex.editor.inline-code": "^1.0.1",
"codex.editor.list": "^1.0.2",
"codex.editor.inline-code": "^1.2.0",
"codex.editor.list": "^1.2.3",
"codex.editor.marker": "^1.0.1",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",

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

View file

@ -14,6 +14,7 @@ import ModuleDispatcher from 'module-dispatcher';
*/
import Writing from './modules/writing';
import Page from './modules/page';
import Landing from './modules/landing';
/**
* Main app class
@ -23,14 +24,15 @@ class Docs {
* @constructor
*/
constructor() {
console.log('CodeX Docs initialized');
this.writing = new Writing();
this.page = new Page();
this.landing = new Landing();
document.addEventListener('DOMContentLoaded', (event) => {
this.docReady();
});
console.log('CodeX Docs initialized');
}
/**

View file

@ -0,0 +1,52 @@
/**
* Module to compose output JSON preview
*/
const cPreview = (function() {
/**
* Shows JSON in pretty preview
* @param {object} output - what to show
* @param {Element} holder - where to show
*/
function show(output, holder) {
/** Make JSON pretty */
output = JSON.stringify(output, null, 4);
/** Encode HTML entities */
output = encodeHTMLEntities(output);
/** Stylize! */
output = stylize(output);
holder.innerHTML = output;
};
/**
* Converts '>', '<', '&' symbols to entities
*/
function encodeHTMLEntities(string) {
return string.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
/**
* Some styling magic
*/
function stylize(string) {
/** Stylize JSON keys */
string = string.replace(/"(\w+)"\s?:/g, '"<span class=sc_key>$1</span>" :');
/** Stylize tool names */
string = string.replace(/"(paragraph|quote|list|header|link|code|image|delimiter|raw|table)"/g, '"<span class=sc_toolname>$1</span>"');
/** Stylize HTML tags */
string = string.replace(/(&lt;[/a-z]+(&gt;)?)/gi, '<span class=sc_tag>$1</span>');
/** Stylize strings */
string = string.replace(/"([^"]+)"/gi, '"<span class=sc_attr>$1</span>"');
/** Boolean/Null */
string = string.replace(/\b(true|false|null)\b/gi, '<span class=sc_bool>$1</span>');
string = string.replace(/\b(\d+)\b/gi, '<span class=sc_digit>$1</span>');
return string;
}
return {
show
};
})();
export default cPreview;

View file

@ -1,9 +1,18 @@
import CodeXEditor from 'codex.editor';
import Header from 'codex.editor.header';
import CodeTool from 'codex.editor.code';
import InlineCode from 'codex.editor.inline-code';
import Marker from 'codex.editor.marker';
import ListTool from 'codex.editor.list';
/**
* Tools for the Editor
*/
const Header = require('codex.editor.header');
const Quote = require('codex.editor.quote');
const Marker = require('codex.editor.marker');
const CodeTool = require('codex.editor.code');
const Delimiter = require('codex.editor.delimiter');
const InlineCode = require('codex.editor.inline-code');
const List = require('codex.editor.list');
const RawTool = require('codex.editor.raw');
const ImageTool = require('codex.editor.image');
const Embed = require('codex.editor.embed');
/**
* Class for working with Editor.js
@ -11,32 +20,59 @@ import ListTool from 'codex.editor.list';
export default class Editor {
/**
* Creates Editor instance
* @property {object} initialData - data to start with
* @param {object} editorConfig - configuration object for Editor.js
* @param {object} data.blocks - data to start with
* @param {object} options
* @param {string} options.headerPlaceholder - placeholder for Header tool
*/
constructor({initialData}) {
this.editor = new CodeXEditor({
constructor(editorConfig = {}, options = {}) {
const defaultConfig = {
tools: {
header: {
class: Header,
inlineToolbar: ['link', 'marker'],
config: {
placeholder: 'Enter a title'
placeholder: options.headerPlaceholder || ''
}
},
code: CodeTool,
// image: {
// class: ImageTool,
// inlineToolbar: true,
// config: {
// endpoints: {
// byFile: '/editor/transport',
// byUrl: '/editor/transport'
// }
// }
// },
list: {
class: List,
inlineToolbar: true
},
quote: {
class: Quote,
inlineToolbar: true
},
code: {
class: CodeTool,
shortcut: 'CMD+SHIFT+D'
},
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+I'
shortcut: 'CMD+SHIFT+C'
},
Marker: {
rawTool: {
class: RawTool,
shortcut: 'CMD+SHIFT+R'
},
marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M'
},
list: {
class: ListTool,
inlineToolbar: true
}
delimiter: Delimiter,
embed: Embed
},
data: initialData || {
data: {
blocks: [
{
type: 'header',
@ -47,7 +83,9 @@ export default class Editor {
}
]
}
});
};
this.editor = new CodeXEditor(Object.assign(defaultConfig, editorConfig));
}
/**
@ -57,4 +95,11 @@ export default class Editor {
save() {
return this.editor.saver.save();
}
/**
* Click on Editor's node to focus after Editor has loaded
*/
focus() {
document.querySelector('.codex-editor__redactor').click();
}
}

View file

@ -0,0 +1,90 @@
'use strict';
/**
* Module to compose output JSON preview
*/
const {default: cPreview} = require('../classes/cPreview');
/**
* Module for pages using Editor
*/
export default class Landing {
constructor() {
/**
* Editor class Instance
*/
this.editor = null;
/**
* DOM elements
*/
this.nodes = {
/**
* Container to output saved Editor data
*/
outputWrapper: null
};
}
/**
* @typedef {Object} editorLandingSettings - Editor landing class settings
* @property {String} editorLandingSettings.output_id - ID of container where Editor's saved data will be shown
* @property {function} editorLandingSettings.onChange - Modifications callback for the Editor
*/
/**
* Initialization. Called by Module Dispatcher
*/
init(editorLandingSettings) {
/**
* Prepare node to output Editor data preview
* @type {HTMLElement} - JSON preview container
*/
this.nodes.outputWrapper = document.getElementById(editorLandingSettings.output_id);
if (!this.nodes.outputWrapper) {
console.warn('Can\'t find output target with ID: «' + editorLandingSettings.output_id + '»');
}
this.loadEditor({
data: {
blocks: editorLandingSettings.blocks
},
/**
* Bind onchange callback to preview JSON data
*/
onChange: () => {
this.previewData();
},
/**
* When Editor is ready, preview JSON output with initial data
*/
onReady: () => {
this.previewData();
this.editor.focus();
}
}).then((editor) => {
this.editor = editor;
});
};
/**
* Load Editor from separate chunk
* @param settings - settings for Editor initialization
* @return {Promise<Editor>} - CodeX Editor promise
*/
async loadEditor(settings) {
const {default: Editor} = await import(/* webpackChunkName: "editor" */ './../classes/editor');
return new Editor(settings);
}
/**
* Shows JSON output of editor saved data
*/
previewData() {
this.editor.save().then((savedData) => {
cPreview.show(savedData, this.nodes.outputWrapper);
});
};
};

View file

@ -66,7 +66,7 @@ export default class Writing {
this.nodes.removeButton.addEventListener('click', () => {
const isUserAgree = confirm("Are you sure?");
if (!isUserAgree) {
return
return;
}
this.removeButtonClicked();
@ -85,8 +85,12 @@ export default class Writing {
async loadEditor() {
const {default: Editor} = await import(/* webpackChunkName: "editor" */ './../classes/editor');
return new Editor({
initialData: this.page ? this.page.body : null
const editorConfig = this.page ? {
data: this.page.body
} : {};
return new Editor(editorConfig, {
headerPlaceholder: 'Enter a title'
});
}

View file

@ -2,6 +2,16 @@
font-size: 15px;
color: var(--color-text-second);
@media (--mobile) {
font-size: 13px;
display: none;
margin-top: 20px;
}
&--toggled {
display: block !important;
}
a {
text-decoration: none;
}
@ -9,9 +19,21 @@
&__section {
margin-bottom: 30px;
@media (--mobile) {
margin-bottom: 20px;
}
&:last-of-type {
margin-bottom: 0;
}
&-title {
margin-bottom: 15px;
color: var(--color-link-active);
@media (--mobile) {
margin-bottom: 10px;
}
}
&-list {
@ -26,3 +48,18 @@
}
}
}
.docs-aside-toggler {
display: none;
font-size: 13px;
cursor: pointer;
color: var(--color-text-second);
@media (--mobile) {
display: block;
}
svg {
margin-right: 10px;
}
}

View file

@ -4,6 +4,8 @@
border-bottom: 1px solid var(--color-line-gray);
font-size: 15.8px;
line-height: 50px;
flex-wrap: wrap;
position: relative;
a {
display: inline-block;
@ -18,10 +20,38 @@
&__menu {
display: flex;
margin: 0 0 0 auto;
padding-left: 0;
@media (--mobile) {
flex-basis: 100%;
font-size: 12px;
}
li {
list-style: none;
margin-left: 20px;
@media (--mobile) {
margin-left: 0;
margin-right: 15px;
}
}
&-add {
@media (--mobile) {
position: absolute;
right: 15px;
top: 15px;
line-height: 1em;
margin: 0 !important;
}
a {
@media (--mobile) {
font-size: 0;
padding: 8px;
margin-right: 0;
}
}
}
a:not(.docs-header__button) {

View file

@ -0,0 +1,670 @@
/**
* Editor landing page
*/
.editor-landing {
width: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
a {
text-decoration: none;
}
&__logo {
position: relative;
content: '';
width: 84px;
height: 84px;
margin: auto;
@media (--mobile) {
width: 50px;
height: 50px;
}
&-main {
position: absolute;
animation: logoIn 1 500ms cubic-bezier(0.5, 1.05, 1, 1);
animation-fill-mode: forwards;
will-change: transform, filter;
z-index: 2;
left: 0;
@media (--mobile) {
svg {
width: 50px;
}
}
}
&-shadow {
position: absolute;
left: -38px;
z-index: 1;
animation: logoShadow 1 500ms cubic-bezier(0.5, 1.05, 1, 1);
animation-fill-mode: forwards;
will-change: transform, opacity;
@media (--mobile) {
left: -21px;
margin-top: -13px;
svg {
width: 92px;
}
}
}
}
/**
* Editor title and description block
*/
&__info {
padding-top: 300px;
padding-bottom: 70px;
background-image: linear-gradient(0deg, #FFFFFF 0%, #EEF7FF 100%);
text-align: center;
}
&__title {
margin: 20px 0 0;
line-height: 1.2em;
font-size: 50px;
letter-spacing: 0.23px;
color: #000;
font-weight: 600;
@media (--mobile) {
margin-top: 25px;
font-size: 30px;
}
}
&__description {
font-size: 17.3px;
letter-spacing: 0.13px;
line-height: 1.5em;
color: #868DA1;
margin-top: 20px;
@media (--mobile) {
font-size: 15px;
margin-top: 10px;
}
}
&__cta {
display: inline-block;
margin-top: 40px;
padding: 13px 19px;
border-radius: 30px;
background: #388ffe;
box-shadow: 0 9px 12px -6px rgba(11,132,242,0.78);
font-size: 16px;
color: #FFFFFF;
transition: all 150ms ease;
will-change: background-color, box-shadow;
&:hover {
color: #fff;
background: #3684fe;
box-shadow: 0 9px 16px -6px rgba(11,132,242,0.78);
}
}
&__menu {
text-align: left;
font-size: 14px;
position: fixed;
right: 7vw;
top: 150px;
@media (max-width: 1400px) {
right: 4.5vw;
}
@media (max-width: 1330px) {
position: absolute;
padding: 20px;
right: 45px;
top: 55px;
}
@media (--mobile) {
position: absolute;
padding: 20px;
left: 0;
top: 45px;
}
a {
color: inherit;
display: inline-block;
border-bottom: 1px solid rgba(93,100,134,0.20);
margin-bottom: 6px;
}
}
&__version {
display: inline-block;
padding: 5px 8px;
line-height: 1em;
border-radius: 30px;
background: #111111;
font-size: 10px;
color: #FFFFFF;
margin-right: -70px;
margin-left: 3px;
}
&__demo {
background: #eef5fa;
border-radius: 100px;
max-width: 950px;
margin: 0 auto;
padding: 70px 60px;
@media (max-width: 1550px) {
max-width: 850px;
}
@media (--mobile) {
padding: 15px;
border-radius: 0;
}
&-inner {
background: #fff;
border-radius: 8px;
box-shadow: 0 24px 24px -18px rgba(69,104,129,0.33), 0 9px 45px 0 rgba(114,119,160,0.12);
padding: 70px 50px;
font-size: 16px;
box-sizing: border-box;
@media (--mobile) {
padding: 20px;
}
}
&-inner,
.codex-editor__redactor {
min-height: 450px;
@media (--mobile) {
min-height: 100px;
}
}
}
&__preview {
max-width: var(--layout-width-main-col);
margin: 0 auto;
color: rgba(34, 78, 111, 0.75);
position: relative;
&::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 150px;
background: linear-gradient(90deg, rgba(238, 245, 250, 0), #eef5fa);
z-index: 2;
}
&-inner {
overflow: auto;
font-size: 14px;
line-height: 1.5em;
letter-spacing: 0.1px;
}
}
&__section-header {
font-size: 16px;
max-width: 375px;
margin: 50px auto;
line-height: 1.5em;
text-align: center;
color: #606578;
@media (--mobile) {
font-size: 14px;
max-width: 70vw;
}
header {
font-weight: 600;
margin-bottom: 13px;
@media (--mobile) {
font-size: 16px;
}
}
&--big {
margin: 130px auto;
line-height: 24px;
@media (--mobile) {
margin: 50px auto;
}
header {
font-size: 26px;
margin-bottom: 20px;
@media (--mobile) {
font-size: 20px;
margin-bottom: 10px;
}
}
}
}
/**
* JSON output code highlighting
*/
.sc_attr {
color: #373742;
}
.sc_toolname {
color: #db1029;
}
.sc_tag {
color: rgb(4, 131, 216);
}
.sc_key {
color: #6e4998;
}
.sc_bool {
color: rgb(247, 60, 173);
}
.sc_digit {
color: #196ff8;
}
/**
* Loved by section
*/
&__loved-by {
position: relative;
display: flex;
justify-content: center;
margin-top: 30px;
@media (--mobile) {
margin-bottom: 80px;
}
&-item {
display: flex;
height: 30px;
&:not(:last-of-type)::after {
content: '';
width: 3px;
height: 100%;
margin-right: 27px;
margin-left: 29px;
background: #e0e0e0;
}
}
}
/**
* Best plugins section
*/
&__plugins {
max-width: 650px;
margin: 0 auto;
@media (--mobile) {
padding: 20px;
}
&-title {
font-size: 24px;
margin-bottom: 15px;
@media (--mobile) {
font-size: 20px;
margin-bottom: 10px;
}
}
&-description {
margin-bottom: 30px;
font-size: 16px;
line-height: 1.65em;
color: #606578;
@media (--mobile) {
font-size: 14px;
}
}
&-filter {
margin: 30px 0;
@media (--mobile) {
margin: 15px 0 20px;
}
&-button {
font-size: 15px;
font-weight: 500;
color: #343434;
vertical-align: middle;
cursor: pointer;
svg {
vertical-align: middle;
margin: -3px 6px 0 3px;
}
&:not(:last-of-type) {
margin-right: 17px;
}
}
}
}
/**
* Links at the bottom of plugins list
*/
&__more-plugins,
&__contribute {
font-size: 15px;
color: #7b7e89;
cursor: pointer;
@media (--mobile) {
margin-top: 10px;
}
svg {
width: 9px;
height: 9px;
fill: currentColor;
vertical-align: middle;
@media (--mobile) {
display: none;
}
}
}
&__more-plugins {
float: left;
@media (--mobile) {
float: none;
}
}
&__contribute {
float: right;
@media (--mobile) {
display: none;
}
svg {
margin: -3px 3px 0 0;
}
}
/**
* Override default editor's padding-bottom
*/
.codex-editor__redactor {
padding-bottom: 120px;
}
&__star {
position: relative;
display: inline-block;
margin-top: 60px;
&-line {
position: absolute;
width: 130px;
height: 10px;
left: 51.5%;
top: 36%;
z-index: -1;
&:nth-of-type(1){
transform: translateX(-50%) rotate(-22deg);
}
&:nth-of-type(2){
transform: rotate(-90deg) ;
left: -11px;
top: 13px;
width: 90px;
}
&:nth-of-type(3){
transform: translateX(-50%) rotate(22deg);
}
&::before,
&::after {
content: '';
display: inline-block;
width: 15px;
height: 10px;
background-image: url("data:image/svg+xml,%3Csvg width='15' height='10' viewBox='0 0 15 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 5.5H0v-1h6v-4L15 5 6 9.5z' fill='%23B6B9C0' fill-rule='nonzero'/%3E%3C/svg%3E");
position: absolute;
top: 0;
}
&:before {
left: 0;
animation: arrow-moving-left infinite 1000ms ease;
}
&:after{
right: 0;
background-image: url("data:image/svg+xml,%3Csvg width='15' height='10' viewBox='0 0 15 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 4.5h6v1H9v4L0 5 9 .5v4z' fill='%23B6B9C0' fill-rule='nonzero'/%3E%3C/svg%3E");
animation: arrow-moving-right infinite 1000ms ease;
}
}
}
}
@keyframes arrow-moving-left {
50% {
transform: translateX(-10px);
}
}
@keyframes arrow-moving-right {
50% {
transform: translateX(10px);
}
}
/**
* Plugin items styles
*/
.editor-plugin {
position: relative;
display: flex;
flex-direction: column;
padding: 20px;
margin-bottom: 20px;
border-radius: 7px;
box-shadow: 0 3px 11px rgba(125, 128, 147, 0.23);
min-height: 90px;
padding-right: 120px;
@media (--mobile) {
padding-right: 100px;
}
&__title {
font-size: 18px;
color: #000;
margin: 0;
display: inline-block;
margin-bottom: 4px;
margin-right: 5px;
@media (--mobile) {
font-size: 16px;
}
}
&__label {
display: inline-block;
font-size: 18px;
color: #606578;
border-radius: 3px;
font-weight: 500;
opacity: 0.4;
line-height: 1em;
margin-top: -5px;
@media (--mobile) {
font-size: 16px;
}
}
&__description {
font-size: 14px;
color: #606578;
}
&__contributors {
display: flex;
margin-top: auto;
@media (--mobile) {
margin-top: 15px;
}
&-item {
display: inline-block;
overflow: hidden;
border-radius: 4px;
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
&:not(:last-of-type) {
margin-right: 6px;
}
}
}
&__demo {
position: absolute;
right: 20px;
top: 15px;
margin-left: 45px;
img,
video {
height: 90px;
@media (--mobile) {
height: 40px;
}
}
}
&--your-own {
^&__title {
color: #7b7e89;
}
^&__description {
display: inline-block;
}
^&__demo {
position: static;
margin-left: 0;
pre {
font-size: 12px;
line-height: 2em;
font-family: Menlo, Monaco, Consolas, Courier New, monospace;
margin: 15px 0;
font-weight: 500;
color: #484554;
@media (--mobile) {
font-size: 10px;
overflow: auto;
}
}
}
^&__footer {
margin-top: 20px;
}
}
}
@keyframes logoIn {
0% {
transform: translateY(-80px) scale(1, 1.3 );
filter: blur(4px);
}
60% {
transform: translateY(0) scale(1);
}
70% {
transform: translateY(5px) scale(1, 0.92);
}
80% {
transform: translateY(0) scale(1)
}
100% {
transform: translateY(-10px);
}
}
@keyframes logoShadow {
0% {
transform: scale(1.6, 0.9);
opacity: 0;
}
70% {
transform: scale(0.8, 0.8) translateY(-10px);
opacity: 1;
}
100% {
transform: translateY(-10px);
opacity: 1;
}
}

View file

@ -6,10 +6,18 @@
display: flex;
color: var(--color-text-second);
@media (--mobile) {
font-size: 13px;
}
&-nav {
color: inherit;
text-decoration: none;
@media (--mobile) {
display: none;
}
&:hover {
color: var(--color-link-active);
}
@ -24,6 +32,10 @@
&-time {
margin-left: auto;
@media (--mobile) {
margin-left: 0;
}
}
&-button {

View file

@ -2,14 +2,31 @@
display: flex;
padding: 0 var(--layout-padding-horisontal);
@media (--mobile) {
flex-wrap: wrap;
}
&__aside {
width: var(--layout-width-aside);
@media (--mobile) {
width: 100%;
flex-basis: 100%;
padding: 20px var(--layout-padding-horisontal) !important;
margin: 0 calc(-1 * var(--layout-padding-horisontal));
border-bottom: 1px solid var(--color-line-gray);
}
}
&__content {
flex-grow: 2;
word-wrap: break-word;
@media (--mobile) {
width: 100%;
flex-basis: 100%;
}
&-inner {
max-width: var(--layout-width-main-col);
margin: 0 auto;
@ -19,5 +36,9 @@
&__aside,
&__content {
padding: var(--layout-padding-vertical) 0;
@media (--mobile) {
padding: 20px 0;
}
}
}

View file

@ -5,6 +5,7 @@
@import url('components/aside.pcss');
@import url('components/writing.pcss');
@import url('components/page.pcss');
@import url('components/landing.pcss');
body {
font-family: system-ui, Helvetica, Arial, Verdana;

View file

@ -14,6 +14,11 @@
--layout-width-aside: 200px;
--layout-width-main-col: 650px;
@media (--mobile) {
--layout-padding-horisontal: 15px;
--layout-padding-vertical: 15px;
}
--button {
display: inline-block;
padding: 9px 15px;
@ -25,6 +30,7 @@
line-height: 1em;
text-decoration: none;
cursor: pointer;
white-space: nowrap;
svg {
margin: 0 0.3em 0 -0.05em;
@ -51,3 +57,11 @@
}
}
}
/**
* Custom media queries
*/
@custom-media --desktop all and (min-width: 1050px);
@custom-media --tablet all and (max-width: 1050px);
@custom-media --mobile all and (max-width: 980px);
@custom-media --retina all and (-webkit-min-device-pixel-ratio: 1.5);

View file

@ -0,0 +1 @@
<svg width="13" height="10" viewBox="0 0 13 10" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h13v2H0V0zm0 4h13v2H0V4zm0 4h13v2H0V8z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 164 B

View file

@ -3,7 +3,199 @@ const router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('index', { title: 'Express' });
/**
* Array of plugins contributors
*/
var contributors = {
polinaShneider: {
name: 'PolinaShneider',
photo: 'https://avatars3.githubusercontent.com/u/15448200?s=40&v=4'
},
specc: {
name: 'neSpecc',
photo: 'https://avatars0.githubusercontent.com/u/3684889?v=4&s=40'
},
n0str: {
name: 'n0str',
photo: 'https://avatars1.githubusercontent.com/u/988885?v=4&s=60'
},
talyguryn: {
name: 'talyguryn',
photo: 'https://avatars1.githubusercontent.com/u/15259299?v=4&s=40'
},
khaydarov: {
name: 'khaydarov',
photo: 'https://avatars1.githubusercontent.com/u/6507765?s=40&v=4'
},
horoyami: {
name: 'horoyami',
photo: 'https://avatars2.githubusercontent.com/u/34141926?s=40&v=4'
},
gohabereg: {
name: 'gohabereg',
photo: 'https://avatars1.githubusercontent.com/u/23050529?s=40&v=4'
}
};
var plugins = [
{
name: 'Header',
type: 'Block',
description: 'How will you live without headers?',
demo: '/public/app/landings/editor/demo/header.png',
url: 'https://github.com/codex-editor/header',
contributors: [
contributors['specc'],
contributors['talyguryn'],
contributors['n0str']
]
},
{
name: 'Simple Image',
type: 'Block',
description: 'Allow pasting image by URLs',
demo: 'https://capella.pics/f67bd749-0115-4ea8-b4b9-4375b20667bc.jpg',
url: 'https://github.com/codex-editor/simple-image',
contributors: [
contributors['specc']
]
},
{
name: 'Image',
type: 'Block',
description: 'Full featured image Block integrated with your backend',
demo: '/public/app/landings/editor/demo/image-tool.mp4',
url: 'https://github.com/codex-editor/image',
contributors: [
contributors['specc'],
contributors['talyguryn']
]
},
{
name: 'Embed',
type: 'Block',
description: 'Here is YouTube, Vimeo, Imgur, Gfycat, Twitch and other embeds',
demo: '/public/app/landings/editor/demo/embed.mp4',
url: 'https://github.com/codex-editor/embed',
contributors: [
contributors['gohabereg']
]
},
{
name: 'Quote',
type: 'Block',
description: 'Include quotes in your articles',
demo: '/public/app/landings/editor/demo/quote.png',
url: 'https://github.com/codex-editor/quote',
contributors: [
contributors['talyguryn']
]
},
{
name: 'Marker',
type: 'Inline Tool',
description: 'Highlight text fragments in your beautiful articles',
demo: '/public/app/landings/editor/demo/marker.gif',
url: 'https://github.com/codex-editor/marker',
contributors: [
contributors['polinaShneider']
]
},
{
name: 'Code',
type: 'Block',
description: 'Include code examples in your writings',
demo: 'https://capella.pics/8c48b0e0-4885-452d-9a78-d563d279d08d.jpg',
url: 'https://github.com/codex-editor/code',
contributors: [
contributors['talyguryn'],
contributors['polinaShneider']
]
},
{
name: 'Link',
type: 'Inline Tool',
description: 'Embed links in your articles',
demo: '/public/app/landings/editor/demo/link.gif',
url: 'https://github.com/codex-editor/link',
contributors: [
contributors['specc'],
contributors['talyguryn'],
contributors['khaydarov']
]
},
{
name: 'List',
type: 'Block',
description: 'Add ordered or bullet lists to your article',
demo: '/public/app/landings/editor/demo/list.png',
url: 'https://github.com/codex-editor/list',
contributors: [
contributors['specc'],
contributors['talyguryn'],
contributors['khaydarov']
]
},
{
name: 'Delimiter',
type: 'Block',
description: 'Separate blocks of text in your articles',
demo: 'https://capella.pics/825a3f47-ef7e-4c64-bc73-521c9c3faee4.jpg',
url: 'https://github.com/codex-editor/delimiter',
contributors: [
contributors['n0str'],
contributors['talyguryn'],
contributors['specc']
]
},
{
name: 'Inline Code',
type: 'Inline Tool',
description: 'Inline Tool for marking code-fragments',
demo: '/public/app/landings/editor/demo/inline-code.gif',
url: 'https://github.com/codex-editor/inline-code',
contributors: [
contributors['talyguryn']
]
},
{
name: 'HTML',
type: 'Block',
description: 'Include raw HTML code in your articles',
demo: 'https://capella.pics/7cf636b6-dad4-4798-bfa4-5273e6c0250f.jpg',
url: 'https://github.com/codex-editor/raw',
contributors: [
contributors['talyguryn'],
contributors['polinaShneider']
]
},
{
name: 'Warning',
type: 'Block',
description: 'Editorial notifications, appeals or warnings',
demo: 'https://capella.pics/ff210390-4b0b-4655-aaf0-cc4a0414e81b.jpg',
url: 'https://github.com/codex-editor/warning',
contributors: [
contributors['polinaShneider'],
contributors['specc']
]
},
{
name: 'Table',
type: 'Block',
description: 'Table constructor that you would enjoy',
demo: '/public/app/landings/editor/demo/table.mp4',
url: 'https://github.com/codex-editor/table',
contributors: [
contributors['horoyami'],
contributors['gohabereg']
]
}
];
res.render('index', {
plugins
});
});
module.exports = router;
module.exports = router;

View file

@ -1,3 +1,6 @@
<div class="docs-aside-toggler" onclick="document.querySelector('.docs-aside').classList.toggle('docs-aside--toggled')">
{{ svg('menu') }} Table of contents
</div>
<div class="docs-aside">
{% for firstLevelPage in menu %}
<section class="docs-aside__section">

View file

@ -3,7 +3,7 @@
{{ config.title }}
</a>
<ul class="docs-header__menu">
<li>
<li class="docs-header__menu-add">
<a class="docs-header__button" href="/page/new">
{{ svg('plus') }}
Add Page

View file

@ -1,6 +1,199 @@
{% extends 'layout.twig' %}
<!DOCTYPE html>
<html>
<head>
<title>{{ config.title }}</title>
<link rel="stylesheet" href="/dist/main.css" />
</head>
<body>
{% include "components/header.twig" %}
<div class="editor-landing">
<div class="editor-landing__info">
<div class="editor-landing__logo">
<span class="editor-landing__logo-main">
<svg width="84" height="84" viewBox="0 0 84 84" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="editorjs-logo-a"><stop stop-color="#39FFD7" offset="0%"/><stop stop-color="#308EFF" offset="100%"/></linearGradient></defs><g fill-rule="nonzero" fill="none"><circle fill="url(#editorjs-logo-a)" cx="42" cy="42" r="42"/><rect fill="#FFF" x="38" y="17" width="8" height="50" rx="4"/><rect fill="#FFF" x="17" y="38" width="50" height="8" rx="4"/></g></svg>
</span>
<span class="editor-landing__logo-shadow">
<svg width="158" height="160" viewBox="0 0 158 160" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="10.449%" x2="50%" y2="91.174%" id="edjls-a"><stop stop-color="#217DE9" stop-opacity=".919" offset="0%"/><stop stop-color="#308EFF" offset="100%"/></linearGradient><filter x="-81.4%" y="-81.4%" width="262.9%" height="262.9%" filterUnits="objectBoundingBox" id="edjls-b"><feGaussianBlur stdDeviation="19" in="SourceGraphic"/></filter></defs><circle filter="url(#edjls-b)" cx="163" cy="116" r="35" transform="translate(-84 -37)" fill="url(#edjls-a)" fill-rule="nonzero"/></svg>
</span>
</div>
<h1 class="editor-landing__title">
Editor.js
</h1>
<div class="editor-landing__description">
Next generation block styled editor. <br> Free. Use for pleasure.
</div>
<a class="editor-landing__cta" href="http://github.com/codex-team/codex.editor">
Get started
</a>
<div class="editor-landing__menu">
<a href="http://github.com/codex-team/codex.editor">
Current version
<span class="editor-landing__version">
?.?.?
</span>
</a>
<br>
<a class="editor-landing__links-item" target="_blank" href="https://github.com/codex-team/codex.editor/blob/master/docs/usage.md">
Documentation
</a>
<br>
<a class="editor-landing__links-item" target="_blank" href="https://github.com/codex-editor">
Plugins
</a>
<br>
<a class="editor-landing__links-item" target="_blank" href="https://github.com/codex-editor">
Changelog
</a>
</div>
</div>
<div class="editor-landing__demo" data-module="landing">
<module-settings hidden>
{
"output_id" : "output",
"blocks" : []
}
</module-settings>
<div class="editor-landing__demo-inner">
<div id="codex-editor"></div>
</div>
<section class="editor-landing__section-header">
<header>
And here is a generated CLEAN data
</header>
Use it in Web, mobile, APM, Instant Articles, speech readers — everywhere. Easy to sanitize, extend and integrate with your logic.
</section>
<div class="editor-landing__preview">
<div class="editor-landing__preview-inner">
<pre id="output"></pre>
</div>
</div>
</div>
<section class="editor-landing__section-header editor-landing__section-header--big">
<header>
API is the feature.
</header>
Each Block provided by plugin. It's really easy to create your own. Dozens of created.
</section>
<div class="editor-landing__plugins">
<h4 class="editor-landing__plugins-title">
Best plugins
</h4>
<div class="editor-landing__plugins-description">
Plugins can represent any Blocks: Quotes, Galleries, Polls, Embeds, Tables — anything you need. Also they can implement Inline Tools such as Marker, Term, Comments etc.
</div>
{% for plugin in plugins %}
<div class="editor-plugin clearfix">
<div class="editor-plugin__demo">
{% if 'mp4' in plugin.demo %}
<video autoplay loop muted playsinline>
<source src="{{ plugin.demo }}" type="video/mp4">
</video>
{% else %}
<img src="{{ plugin.demo }}" alt="{{ plugin.name }} Tool for Editor.js">
{% endif %}
</div>
<a href="{{ plugin.url }}" target="_blank">
<h3 class="editor-plugin__title">
{{ plugin.name }}
</h3>
<span class="editor-plugin__label">
{{ plugin.type }}
</span>
</a>
<div class="editor-plugin__description">
{{ plugin.description }}
</div>
<div class="editor-plugin__contributors">
{% for user in plugin.contributors %}
<a href="https://github.com/{{ user.name }}" class="editor-plugin__contributors-item" title="{{ user.name }}" target="_blank">
<img src="{{ user.photo }}" alt="{{ user.name }}">
</a>
{% endfor %}
</div>
</div>
{% endfor %}
{%
set ownTool = "<span style='color:#b83370'>class</span> <span style='color:#8c74b2'>MyTool</span> {
render() {
<span style='color:#b83370'>return</span> document.createElement(textarea);
}
save(textarea) {
<span style='color:#b83370;'>return</span> {
text: textarea.value
}
}
}"
%}
<div class="editor-plugin editor-plugin--your-own">
<h3 class="editor-plugin__title">
Your own plugin
</h3>
<div class="editor-plugin__description">
Just implement <i>render</i> and <i>save</i> methods.
</div>
<div class="editor-plugin__demo">
<pre>{{ ownTool }}</pre>
</div>
<div class="editor-plugin__footer">
To make it cool, take a look at the <a href="https://github.com/codex-team/codex.editor/blob/master/docs/tools.md">API</a>.
</div>
</div>
<div class="editor-landing__actions clearfix">
<a class="editor-landing__more-plugins" href="https://github.com/codex-editor" target="_blank">
View all plugins
</a>
<a class="editor-landing__contribute" href="#">
<? include(DOCROOT . '/public/app/landings/editor/svg/plus-icon.svg'); ?>
Contribute your plugin to this featured list
</a>
</div>
<section class="editor-landing__section-header editor-landing__section-header--big">
<header>
Loved by
</header>
Thousands of people already write with us.
<div class="editor-landing__loved-by">
<a rel="nofollow" class="editor-landing__loved-by-item" target="_blank" href="//tjournal.ru">
<svg width="27" height="28"><g fill-rule="nonzero" fill="none"><path fill="#3A3A3B" opacity=".5" d="M0 21.28h9.52V28H0z"/><path fill="#3A3A3B" d="M0 7.84h9.52V28l7.28-6.72V7.84h10.08V0H0z"/><path fill="#51535A" opacity=".604" d="M8.4 21.28h1.12V28z"/></g></svg>
</a>
<a rel="nofollow" class="editor-landing__loved-by-item" target="_blank" href="//dtf.ru">
<svg width="74" height="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.074 0H0v24h15.074c5.232 0 9.486-4.157 9.486-9.27V9.27C24.561 4.156 20.306 0 15.074 0zm3.309 14.73c0 1.783-1.483 3.235-3.308 3.235h-8.9V6.035h8.9c1.823 0 3.307 1.448 3.307 3.234v5.462h.001zm7.921-8.696h8.623V23.95h6.176V6.034h8.623V0H26.304v6.034zm46.74 0V0H53.101v23.95h6.175v-7.056h10.416v-6.031H59.277V6.034h13.766z" fill-rule="nonzero" fill="#51535A"/></svg>
</a>
<a rel="nofollow" class="editor-landing__loved-by-item" target="_blank" href="//vc.ru">
<svg width="31" height="29" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero" fill="#3A3A3B"><path d="M24.086 12.999c2.225 0 3.9-.932 5.135-2.556l-1.652-1.27a4.343 4.343 0 0 1-3.483 1.735c-2.416 0-4.16-1.977-4.16-4.408s1.72-4.52 4.233-4.52c1.115 0 1.906.263 2.595.694v2.137h2.078V1.697l-.398-.314C27.288.478 25.545 0 24.086 0c-3.562 0-6.46 2.916-6.46 6.5 0 3.583 2.898 6.499 6.46 6.499zM28.398 25.827l-.073-2.994v-7.307h-4.333v2.092h2.145v4.954c0 2.137-1.623 3.647-3.257 3.647-1.635 0-2.488-1.141-2.488-3.278v-7.415h-4.048v2.092h1.86v5.692c0 2.896 1.614 4.89 4.492 4.89 1.653 0 2.915-.92 3.667-2.348h.033l.297 1.992h3.327v-2.017h-1.622zM17.146.306H13.54l-3.14 9.174h-.049L7.226.306H3.379v2.091H5.54l3.724 10.457h1.98v-.002.001l3.881-10.456h2.021zM0 27.91h2.137v-2.15H0zM8.26 17.95h-.024L8.1 15.527H4.28v1.907h2.035v8.393H4.282v2.018h9.436v-1.981h-5.25v-5.067c.236-1.833 1.603-3.4 3.466-3.4h.034l-.035 1.874h2.078v-3.785h-1.64c-1.884 0-3.28 1.025-4.11 2.466z"/></g></svg>
</a>
</div>
</section>
<section class="editor-landing__section-header editor-landing__section-header--big">
<header>
Support Team
</header>
We will be really glad and inspired by <b>every</b> star of the project. It helps community to grow, build new cool plugins and core features.
<br>
<div class="editor-landing__star">
<div class="editor-landing__star-line"></div>
<div class="editor-landing__star-line"></div>
<div class="editor-landing__star-line"></div>
<a class="github-button" href="https://github.com/codex-team/codex.editor" data-icon="octicon-star" data-size="large" aria-label="Star codex-team/codex.editor on GitHub">Star</a>
<script async defer src="https://buttons.github.io/buttons.js"></script>
</div>
</section>
</div>
</div>
<script src="/dist/main.bundle.js"></script>
</body>
</html>
{% block body %}
{{title}}
<p>Welcome to {{title}}</p>
{% endblock %}

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
<title>{{ config.title }}</title>
<link rel="stylesheet" href="/dist/main.css" />
</head>
<body>

1016
yarn.lock

File diff suppressed because it is too large Load diff