-
Notifications
You must be signed in to change notification settings - Fork 0
Added ability to create extensions #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
ac4273d
20e5514
1f1df16
655734f
1017f00
58141d5
85530c3
83ee5a3
52d1f66
1a4027d
11ffe5a
5a0109f
3e74294
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import EditorJS from '@editorjs/editorjs'; | ||
import StandAPI from '../src/Stand/StandAPI/StandAPI'; | ||
import Extension, { Control } from '../src/types/extension'; | ||
|
||
/** | ||
* Extension for toggle read only mode | ||
*/ | ||
export default class ReadOnlyExtension implements Extension { | ||
/** | ||
* Editor.js instance | ||
*/ | ||
public readonly editor: EditorJS; | ||
/** | ||
* Stand API with editor.js wrapper | ||
*/ | ||
public readonly stand: StandAPI; | ||
|
||
/** | ||
* Constructor for read only extension | ||
* | ||
* @param {EditorJS} editor - editor.js instance | ||
slaveeks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @param {StandAPI} stand - stand API instance | ||
*/ | ||
constructor(editor: EditorJS, stand: StandAPI) { | ||
this.editor = editor; | ||
this.stand = stand; | ||
} | ||
|
||
/** | ||
* Get extension control | ||
*/ | ||
public get control(): Control { | ||
return { | ||
icon: '🔒', | ||
title: 'Read Only', | ||
onActivate: () => { | ||
this.editor.readOnly.toggle(); | ||
}, | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,9 @@ import { Plugin } from '../types/editorjs/Plugin.js'; | |
import FileData from '../utils/FileData.js'; | ||
|
||
// Templates for html and script files | ||
const STAND_TEMPLATE = path.resolve('./src/stand/stand-template.html'); | ||
const STAND_SCRIPT_TEMPLATE = path.resolve('./src/stand/stand-template.js'); | ||
const STAND_TEMPLATE = path.resolve('./src/stand/templates/stand-template.html'); | ||
const STAND_SCRIPT_TEMPLATE = path.resolve('./src/stand/templates/stand-template.js'); | ||
const STAND_STYLE_TEMPLATE = path.resolve('./src/stand/templates/stand-template.css'); | ||
|
||
/** | ||
* Stand is the environment for testing editor.js and its plugins | ||
|
@@ -32,6 +33,11 @@ export default class Stand { | |
*/ | ||
private JSData: FileData; | ||
|
||
/** | ||
* Data to store into stand style file | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Description is not clear. What kind of data? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed it |
||
*/ | ||
private CSSData: FileData; | ||
|
||
/** | ||
* Initiate stand | ||
* | ||
|
@@ -47,6 +53,11 @@ export default class Stand { | |
*/ | ||
this.HTMLFileData = new FileData(STAND_TEMPLATE); | ||
|
||
/** | ||
* Get style template file | ||
*/ | ||
this.CSSData = new FileData(STAND_STYLE_TEMPLATE); | ||
|
||
/** | ||
* Get script template file | ||
*/ | ||
|
@@ -73,24 +84,26 @@ export default class Stand { | |
/** | ||
* Add editor.js core initiation to script | ||
*/ | ||
this.JSData.insert(`\nconst editor = new Core(editorConfig)`); | ||
this.JSData.insert(`const editor = new Core(editorConfig)`, '{{{ Core }}}'); | ||
|
||
/** | ||
* File names for stand environment | ||
*/ | ||
const bundleName = 'stand.js'; | ||
const indexName = 'index.html'; | ||
const styleName = 'stand.css'; | ||
|
||
/** | ||
* Add stand.js script to index.html | ||
*/ | ||
this.addScript(bundleName); | ||
|
||
/** | ||
* Write file data to index.html and stand.js files | ||
* Write file data to index.html, stand.js and stand.css files | ||
*/ | ||
this.HTMLFileData.saveFile(indexName); | ||
this.JSData.saveFile(bundleName); | ||
this.CSSData.saveFile(styleName); | ||
} | ||
|
||
/** | ||
|
@@ -99,7 +112,7 @@ export default class Stand { | |
* @param {string} scriptPath - script path | ||
*/ | ||
private addScript(scriptPath: string): void { | ||
const script =`\n<script src="${scriptPath}" type="module"></script>`; | ||
const script =`<script src="${scriptPath}" type="module"></script>`; | ||
|
||
this.HTMLFileData.insert(script, '<body>'); | ||
} | ||
|
@@ -120,7 +133,7 @@ export default class Stand { | |
importSource = tool.packageName; | ||
} | ||
|
||
const str = `\nimport ${className} from '${importSource}'`; | ||
const str = `import ${className} from '${importSource}'`; | ||
|
||
/** | ||
* Regular comment to insert import after it | ||
|
@@ -145,15 +158,12 @@ export default class Stand { | |
const toolName = this.plugins[i].name; | ||
|
||
/** | ||
* If tool object is undefined, create empty object | ||
* Add tool to tools object in editorConfig | ||
*/ | ||
this.JSData.insert(`\nif (typeof editorConfig.tools.${toolName} === 'undefined') {`); | ||
this.JSData.insert(`\n\teditorConfig.tools.${toolName} = {}\n}`); | ||
const data = `if (!editorConfig.tools.${toolName}) editorConfig.tools.${toolName} = {} | ||
editorConfig.tools.${toolName}.class = Tool${i}`; | ||
|
||
/** | ||
* Create plugin object in tools | ||
*/ | ||
this.JSData.insert(`\neditorConfig.tools.${toolName}.class = Tool${i}`); | ||
this.JSData.insert(data, '// {{{ Tools configuration }}}'); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,18 @@ | ||||||
/** | ||||||
* Class for stand API, which is used to interact with editor.js wrapper | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||||
*/ | ||||||
export default class StandAPI { | ||||||
/** | ||||||
* Editor.js wrapper | ||||||
*/ | ||||||
public editorWrapper: HTMLDivElement; | ||||||
|
||||||
/** | ||||||
* Constructor for stand API | ||||||
* | ||||||
* @param {string} holder - editor.js holder name | ||||||
*/ | ||||||
constructor(holder: string) { | ||||||
this.editorWrapper = document.getElementById(holder) as HTMLDivElement; | ||||||
} | ||||||
} |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
:root { | ||
--color-bg-main: #fff; | ||
--color-border-light: #E8E8EB; | ||
--color-text-main: #000; | ||
} | ||
|
||
body { | ||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; | ||
font-size: 14px; | ||
line-height: 1.5em; | ||
margin: 0; | ||
background: var(--color-bg-main); | ||
color: var(--color-text-main); | ||
} | ||
|
||
.dev-stand { | ||
font-size: 16.2px; | ||
} | ||
|
||
.dev-stand__extensions { | ||
display: flex; | ||
align-items: center; | ||
position: fixed; | ||
bottom: 0; | ||
right: 0; | ||
left: 0; | ||
background: var(--color-bg-main); | ||
border-radius: 8px 8px 0 0; | ||
border-top: 1px solid var(--color-border-light); | ||
box-shadow: 0 2px 6px var(--color-border-light); | ||
font-size: 13px; | ||
padding: 8px 15px; | ||
z-index: 1; | ||
user-select: none; | ||
} | ||
|
||
.dev-stand__extensions-item:not(:last-of-type)::after { | ||
content: '|'; | ||
color: #ddd; | ||
margin: 0 15px 0 12px; | ||
} | ||
|
||
.dev-stand__extensions-item { | ||
display: flex; | ||
align-items: center; | ||
gap: 10px; | ||
} | ||
|
||
.dev-stand__extensions-button { | ||
display: inline-block; | ||
padding: 3px 12px; | ||
transition: all 150ms ease; | ||
cursor: pointer; | ||
border-radius: 31px; | ||
background: #eff1f4; | ||
text-align: center; | ||
user-select: none; | ||
border: 1px solid #e1e3e8; | ||
} | ||
|
||
.dev-stand__extensions-button--active { | ||
background: gray; | ||
} | ||
|
||
.dev-stand__content { | ||
max-width: 1100px; | ||
margin: 0 auto; | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Editor.js Dev Stand</title> | ||
<link rel="stylesheet" href="stand.css"> | ||
</head> | ||
<body> | ||
<div class="dev-stand"> | ||
<div class="dev-stand__content__content"> | ||
<div id="editorjs"></div> | ||
</div> | ||
<div class="dev-stand__extensions"></div> | ||
</div> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import config from './editorjs.config'; | ||
import StandAPI from './src/stand/StandAPI/StandAPI'; | ||
|
||
// {{{ Tools }}} | ||
|
||
const editorConfig = config().editorConfig; | ||
const extensions = config().extensions; | ||
|
||
if (typeof editorConfig.tools === 'undefined') { | ||
editorConfig.tools = {} | ||
} | ||
|
||
// {{{ Tools configuration }}} | ||
|
||
// {{{ Core }}} | ||
|
||
const standAPI = new StandAPI('editorjs'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think editorWrapper should not be hardcoded here, but passed from somewhere as link There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
/** | ||
* Create style element to add styles from extensions | ||
*/ | ||
const styleElement = document.createElement('style'); | ||
|
||
/** | ||
* Iterate over all extensions | ||
*/ | ||
for (const extensionClass of extensions) { | ||
/** | ||
* Create extension | ||
*/ | ||
const extension = new extensionClass(editor, standAPI); | ||
|
||
/** | ||
* If extension has styles, add them to the stand | ||
*/ | ||
if (extension.styles) { | ||
styleElement.textContent += extension.styles; | ||
} | ||
|
||
/** | ||
* Create button to toggle extension | ||
*/ | ||
const btn = document.createElement('button'); | ||
btn.addEventListener('click', () => { | ||
extension.control.onActivate(); | ||
btn.classList.toggle('dev-stand__extensions-button--active'); | ||
}); | ||
btn.innerHTML = extension.control.icon; | ||
btn.classList.add('dev-stand__extensions-button'); | ||
|
||
/** | ||
* Create container for extension | ||
*/ | ||
const extensionContainer = document.createElement('div'); | ||
extensionContainer.classList.add('dev-stand__extensions-item'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code could be organised better with classes or methods There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
/** | ||
* Add title to the extension | ||
*/ | ||
const extensionTitle = document.createElement('div'); | ||
extensionTitle.innerText = extension.control.title; | ||
|
||
/** | ||
* Append extension to the stand | ||
*/ | ||
extensionContainer.appendChild(extensionTitle); | ||
extensionContainer.appendChild(btn); | ||
document.querySelector('.dev-stand__extensions').appendChild(extensionContainer); | ||
} | ||
document.head.appendChild(styleElement); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is the default value, could be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done