feat: codeblock 增加换行设置按钮
This commit is contained in:
parent
8bbb9d0dc4
commit
27798432aa
|
@ -370,6 +370,11 @@ abstract class CardEntry<T extends CardValue = {}> implements CardInterface {
|
|||
this.resizeModel?.render(container);
|
||||
}
|
||||
}
|
||||
this.toolbarModel?.hide();
|
||||
this.toolbarModel?.destroy();
|
||||
if (this.toolbar) {
|
||||
this.toolbarModel = new Toolbar(this.editor, this);
|
||||
}
|
||||
if (this.isEditable) {
|
||||
this.editor.nodeId.generateAll(this.getCenter().get<Element>()!);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,10 @@ import './index.css';
|
|||
export const isCardToolbarItemOptions = (
|
||||
item: ToolbarItemOptions | CardToolbarItemOptions,
|
||||
): item is CardToolbarItemOptions => {
|
||||
return ['button', 'input', 'dropdown', 'node'].indexOf(item.type) === -1;
|
||||
return (
|
||||
['button', 'input', 'dropdown', 'node', 'switch'].indexOf(item.type) ===
|
||||
-1
|
||||
);
|
||||
};
|
||||
|
||||
class CardToolbar implements CardToolbarInterface {
|
||||
|
|
|
@ -10,9 +10,11 @@ const template = (options: DropdownSwitchOptions) => {
|
|||
<span class="data-toolbar-dropdown-item-content"${
|
||||
options.disabled ? ' disabled="disabled"' : ''
|
||||
}>${options.content}</span>
|
||||
<button type="button" role="switch" aria-checked="true" class="switch-btn ${
|
||||
checked ? ' switch-checked' : ''
|
||||
}">
|
||||
<button type="button"${
|
||||
options.disabled ? ' disabled="disabled"' : ''
|
||||
} role="switch" aria-checked="true" class="switch-btn ${
|
||||
checked ? ' switch-checked' : ''
|
||||
}">
|
||||
<div class="switch-handle"></div>
|
||||
<span class="switch-inner"></span>
|
||||
</button>
|
||||
|
@ -30,7 +32,7 @@ export default class {
|
|||
|
||||
renderTo(container: NodeInterface) {
|
||||
this.root = $(template(this.options));
|
||||
this.switch = this.root.find('.ant-switch');
|
||||
this.switch = this.root.find('.switch-btn');
|
||||
container.append(this.root);
|
||||
this.root.on('mousedown', (e) => e.preventDefault());
|
||||
const { onClick } = this.options;
|
||||
|
@ -46,9 +48,9 @@ export default class {
|
|||
updateSwitch() {
|
||||
if (this.options.getState) {
|
||||
if (this.options.getState()) {
|
||||
this.switch?.addClass('ant-switch-checked');
|
||||
this.switch?.addClass('switch-checked');
|
||||
} else {
|
||||
this.switch?.removeClass('ant-switch-checked');
|
||||
this.switch?.removeClass('switch-checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
|
||||
.data-toolbar-dropdown-switch .data-toolbar-dropdown-item-content {
|
||||
flex: 1;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.data-toolbar-dropdown-switch .switch-btn {
|
||||
|
@ -231,4 +232,96 @@
|
|||
|
||||
.data-toolbar-dropdown-switch .switch-btn.switch-checked .switch-inner {
|
||||
margin: 0 18px 0 5px;
|
||||
}
|
||||
.data-toolbar-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.data-toolbar-switch:hover {
|
||||
background-color: #f4f4f4;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-content {
|
||||
flex: 1;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #595959;
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5;
|
||||
list-style: none;
|
||||
-webkit-font-feature-settings: "tnum";
|
||||
font-feature-settings: "tnum";
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
background-color: rgba(0,0,0,.25);
|
||||
border: 0;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
-webkit-transition: all .2s;
|
||||
transition: all .2s;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
min-width: 28px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn.switch-checked {
|
||||
background-color: #347EFF
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn .switch-handle {
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn .switch-handle, .data-toolbar-switch .switch-btn .switch-handle:before {
|
||||
position: absolute;
|
||||
-webkit-transition: all .2s ease-in-out;
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn.switch-checked .switch-handle {
|
||||
left: calc(100% - 14px);
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn .switch-handle:before {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
border-radius: 9px;
|
||||
-webkit-box-shadow: 0 2px 4px 0 rgb(0 35 11 / 20%);
|
||||
box-shadow: 0 2px 4px 0 rgb(0 35 11 / 20%);
|
||||
content: "";
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn .switch-inner {
|
||||
display: block;
|
||||
margin: 0 5px 0 18px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
-webkit-transition: margin .2s;
|
||||
transition: margin .2s;
|
||||
}
|
||||
|
||||
.data-toolbar-switch .switch-btn.switch-checked .switch-inner {
|
||||
margin: 0 18px 0 5px;
|
||||
}
|
|
@ -6,11 +6,13 @@ import {
|
|||
NodeOptions,
|
||||
ToolbarOptions,
|
||||
ToolbarInterface,
|
||||
SwitchOptions,
|
||||
} from '../types/toolbar';
|
||||
import Button from './button';
|
||||
import Dropdown from './dropdown';
|
||||
import Input from './input';
|
||||
import Tooltip from './tooltip';
|
||||
import Switch from './switch';
|
||||
import { DATA_ELEMENT } from '../constants';
|
||||
import { $ } from '../node';
|
||||
import './index.css';
|
||||
|
@ -22,7 +24,8 @@ const template = () => {
|
|||
class Toolbar implements ToolbarInterface {
|
||||
private options: ToolbarOptions;
|
||||
root: NodeInterface;
|
||||
private items: Array<NodeInterface | Button | Input | Dropdown> = [];
|
||||
private items: Array<NodeInterface | Button | Input | Dropdown | Switch> =
|
||||
[];
|
||||
|
||||
constructor(options: ToolbarOptions) {
|
||||
this.options = { ...options };
|
||||
|
@ -36,6 +39,10 @@ class Toolbar implements ToolbarInterface {
|
|||
item = new Button(options as ButtonOptions);
|
||||
item.render(node);
|
||||
}
|
||||
if (options.type === 'switch') {
|
||||
item = new Switch(options as SwitchOptions);
|
||||
item.render(node);
|
||||
}
|
||||
if (options.type === 'input') {
|
||||
const inputOptions = options as InputOptions;
|
||||
item = new Input(inputOptions);
|
||||
|
@ -102,4 +109,4 @@ class Toolbar implements ToolbarInterface {
|
|||
|
||||
export default Toolbar;
|
||||
|
||||
export { Button, Input, Dropdown, Tooltip };
|
||||
export { Button, Input, Dropdown, Tooltip, Switch };
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import { NodeInterface } from '../types/node';
|
||||
import { SwitchOptions } from '../types/toolbar';
|
||||
import { $ } from '../node';
|
||||
|
||||
const template = (options: SwitchOptions) => {
|
||||
let checked = !!options.checked;
|
||||
if (options.getState) checked = options.getState();
|
||||
return `
|
||||
<div class="data-toolbar-switch">
|
||||
<span class="switch-content"${
|
||||
options.disabled ? ' disabled="disabled"' : ''
|
||||
}>${options.content}</span>
|
||||
<button type="button" role="switch" aria-checked="true" class="switch-btn ${
|
||||
checked ? ' switch-checked' : ''
|
||||
}"${options.disabled ? ' disabled="disabled"' : ''}>
|
||||
<div class="switch-handle"></div>
|
||||
<span class="switch-inner"></span>
|
||||
</button>
|
||||
</div>`;
|
||||
};
|
||||
|
||||
export default class {
|
||||
private options: SwitchOptions;
|
||||
private root: NodeInterface;
|
||||
private switch: NodeInterface | undefined;
|
||||
|
||||
constructor(options: SwitchOptions) {
|
||||
this.options = options;
|
||||
this.root = $(template(options));
|
||||
this.switch = this.root.find('.switch-btn');
|
||||
if (options.class) {
|
||||
this.root.addClass(options.class);
|
||||
}
|
||||
}
|
||||
|
||||
render(container: NodeInterface) {
|
||||
const { didMount, onClick } = this.options;
|
||||
container.append(this.root);
|
||||
|
||||
this.root.on('mousedown', (e) => e.preventDefault());
|
||||
this.root.on('click', (e) => {
|
||||
e.stopPropagation();
|
||||
if (onClick) {
|
||||
onClick(e, this.root);
|
||||
this.updateSwitch();
|
||||
}
|
||||
});
|
||||
|
||||
if (didMount) {
|
||||
didMount(this.root);
|
||||
}
|
||||
}
|
||||
|
||||
updateSwitch() {
|
||||
if (this.options.getState) {
|
||||
if (this.options.getState()) {
|
||||
this.switch?.addClass('switch-checked');
|
||||
} else {
|
||||
this.switch?.removeClass('switch-checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,7 +41,40 @@ export type ButtonOptions = {
|
|||
*/
|
||||
didMount?: (node: NodeInterface) => void;
|
||||
};
|
||||
|
||||
export type SwitchOptions = {
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
type: 'switch';
|
||||
/**
|
||||
* 样式名称
|
||||
*/
|
||||
class?: string;
|
||||
/**
|
||||
* 是否禁用
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* 按钮内容
|
||||
*/
|
||||
content: string;
|
||||
/**
|
||||
* 是否选中
|
||||
*/
|
||||
checked?: boolean;
|
||||
/**
|
||||
* 获取当前状态
|
||||
*/
|
||||
getState?: () => boolean;
|
||||
/**
|
||||
* 单击事件
|
||||
*/
|
||||
onClick?: (event: MouseEvent, node: NodeInterface) => void;
|
||||
/**
|
||||
* 按钮渲染成功后的回调
|
||||
*/
|
||||
didMount?: (node: NodeInterface) => void;
|
||||
};
|
||||
/**
|
||||
* 输入框
|
||||
*/
|
||||
|
@ -190,7 +223,8 @@ export type ToolbarItemOptions =
|
|||
| ButtonOptions
|
||||
| InputOptions
|
||||
| DropdownOptions
|
||||
| NodeOptions;
|
||||
| NodeOptions
|
||||
| SwitchOptions;
|
||||
|
||||
/**
|
||||
* 工具栏
|
||||
|
|
|
@ -58,6 +58,9 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
return {
|
||||
tabSize,
|
||||
indentUnit: tabSize,
|
||||
scrollbarStyle: 'simple',
|
||||
readOnly: !isEngine(this.editor) || this.editor.readonly,
|
||||
viewportMargin: Infinity,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -77,9 +80,6 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
lineWrapping: false,
|
||||
autofocus: false,
|
||||
dragDrop: false,
|
||||
readOnly: !isEngine(this.editor) || this.editor.readonly,
|
||||
scrollbarStyle: 'null',
|
||||
viewportMargin: 1 / 0,
|
||||
...this.getConfig(value, syntaxMode),
|
||||
...options,
|
||||
},
|
||||
|
@ -141,6 +141,10 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
return this.codeMirror;
|
||||
}
|
||||
|
||||
setAutoWrap(value: boolean) {
|
||||
this.codeMirror?.setOption('lineWrapping', value);
|
||||
}
|
||||
|
||||
update(mode: string, code?: string) {
|
||||
this.mode = mode;
|
||||
if (code !== undefined) {
|
||||
|
@ -154,7 +158,7 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
if (code !== undefined) this.save();
|
||||
}
|
||||
|
||||
render(mode: string, value: string) {
|
||||
render(mode: string, value: string, options?: EditorConfiguration) {
|
||||
const root = this.container.find('.data-codeblock-content');
|
||||
mode = this.getSyntax(mode);
|
||||
const stage = $(
|
||||
|
@ -162,7 +166,10 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
);
|
||||
root.append(stage);
|
||||
const pre = stage.find('pre')[0];
|
||||
this.runMode(value || '', mode, pre, this.getConfig(value, mode));
|
||||
this.runMode(value || '', mode, pre, {
|
||||
...this.getConfig(value, mode),
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
save() {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@ import './index.css';
|
|||
export type CodeBlockValue = {
|
||||
mode?: string;
|
||||
code?: string;
|
||||
autoWrap?: boolean;
|
||||
};
|
||||
|
||||
class CodeBlcok extends Card<CodeBlockValue> {
|
||||
|
@ -85,10 +86,30 @@ class CodeBlcok extends Card<CodeBlockValue> {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
#viewAutoWrap?: boolean = undefined;
|
||||
toolbar(): Array<CardToolbarItemOptions | ToolbarItemOptions> {
|
||||
if (!isEngine(this.editor) || this.editor.readonly) {
|
||||
return [{ type: 'copy' }];
|
||||
return [
|
||||
{ type: 'copy' },
|
||||
{
|
||||
type: 'switch',
|
||||
content: this.editor.language.get<string>(
|
||||
CodeBlcok.cardName,
|
||||
'autoWrap',
|
||||
),
|
||||
getState: () => {
|
||||
if (this.#viewAutoWrap === undefined) {
|
||||
this.#viewAutoWrap = !!this.getValue()?.autoWrap;
|
||||
}
|
||||
return this.#viewAutoWrap;
|
||||
},
|
||||
onClick: () => {
|
||||
const autoWrap = !this.#viewAutoWrap;
|
||||
this.#viewAutoWrap = autoWrap;
|
||||
this.codeEditor?.setAutoWrap(autoWrap);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
{
|
||||
|
@ -120,6 +141,24 @@ class CodeBlcok extends Card<CodeBlockValue> {
|
|||
}, 100);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
content: this.editor.language.get<string>(
|
||||
CodeBlcok.cardName,
|
||||
'autoWrap',
|
||||
),
|
||||
getState: () => {
|
||||
return !!this.getValue()?.autoWrap;
|
||||
},
|
||||
onClick: () => {
|
||||
const value = this.getValue();
|
||||
const autoWrap = !value?.autoWrap;
|
||||
this.setValue({
|
||||
autoWrap,
|
||||
});
|
||||
this.codeEditor?.setAutoWrap(autoWrap);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -142,15 +181,18 @@ class CodeBlcok extends Card<CodeBlockValue> {
|
|||
if (isEngine(this.editor)) {
|
||||
if (this.mirror) {
|
||||
this.codeEditor.update(mode, code);
|
||||
this.codeEditor.setAutoWrap(!!value?.autoWrap);
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.mirror = this.codeEditor?.create(mode, code);
|
||||
// 创建后更新一下toolbar,不然无法选择语言
|
||||
if (this.activated) this.toolbarModel?.show();
|
||||
this.mirror = this.codeEditor?.create(mode, code, {
|
||||
lineWrapping: !!value?.autoWrap,
|
||||
});
|
||||
}, 50);
|
||||
} else {
|
||||
this.codeEditor.render(mode, code);
|
||||
this.codeEditor?.create(mode, code, {
|
||||
lineWrapping: !!value?.autoWrap,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,3 +30,5 @@ import 'codemirror/mode/vb/vb';
|
|||
import 'codemirror/mode/velocity/velocity';
|
||||
import 'codemirror/mode/xml/xml';
|
||||
import 'codemirror/mode/yaml/yaml';
|
||||
import 'codemirror/addon/scroll/simplescrollbars';
|
||||
import 'codemirror/addon/scroll/simplescrollbars.css';
|
||||
|
|
|
@ -23,7 +23,8 @@ export interface CodeBlockEditorInterface {
|
|||
getSyntax(mode: string): string;
|
||||
create(mode: string, value: string, options?: EditorConfiguration): Editor;
|
||||
update(mode: string, value?: string): void;
|
||||
render(mode: string, value: string): void;
|
||||
setAutoWrap(value: boolean): void;
|
||||
render(mode: string, value: string, options?: EditorConfiguration): void;
|
||||
save(): void;
|
||||
focus(): void;
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
decodeCardValue,
|
||||
} from '@aomao/engine';
|
||||
import CodeBlockComponent, { CodeBlockEditor } from './component';
|
||||
import locales from './locales';
|
||||
|
||||
export interface Options extends PluginOptions {
|
||||
hotkey?: string | Array<string>;
|
||||
|
@ -42,6 +43,7 @@ export default class extends Plugin<Options> {
|
|||
}
|
||||
|
||||
init() {
|
||||
this.editor.language.add(locales);
|
||||
this.editor.on('parse:html', (node) => this.parseHtml(node));
|
||||
this.editor.on('paste:schema', (schema) => this.pasteSchema(schema));
|
||||
this.editor.on('paste:each', (child) => this.pasteHtml(child));
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
codeblock: {
|
||||
autoWrap: 'Auto Wrap',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
import en from './en-US';
|
||||
import cn from './zh-CN';
|
||||
|
||||
export default {
|
||||
'en-US': en,
|
||||
'zh-CN': cn,
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
codeblock: {
|
||||
autoWrap: '自动换行',
|
||||
},
|
||||
};
|
|
@ -58,6 +58,9 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
return {
|
||||
tabSize,
|
||||
indentUnit: tabSize,
|
||||
scrollbarStyle: 'simple',
|
||||
readOnly: !isEngine(this.editor) || this.editor.readonly,
|
||||
viewportMargin: Infinity,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -77,9 +80,6 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
lineWrapping: false,
|
||||
autofocus: false,
|
||||
dragDrop: false,
|
||||
readOnly: !isEngine(this.editor) || this.editor.readonly,
|
||||
scrollbarStyle: 'null',
|
||||
viewportMargin: 1 / 0,
|
||||
...this.getConfig(value, syntaxMode),
|
||||
...options,
|
||||
},
|
||||
|
@ -142,6 +142,10 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
return this.codeMirror;
|
||||
}
|
||||
|
||||
setAutoWrap(value: boolean) {
|
||||
this.codeMirror?.setOption('lineWrapping', value);
|
||||
}
|
||||
|
||||
update(mode: string, code?: string) {
|
||||
this.mode = mode;
|
||||
if (code !== undefined) {
|
||||
|
@ -155,7 +159,7 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
if (code !== undefined) this.save();
|
||||
}
|
||||
|
||||
render(mode: string, value: string) {
|
||||
render(mode: string, value: string, options?: EditorConfiguration) {
|
||||
const root = this.container.find('.data-codeblock-content');
|
||||
mode = this.getSyntax(mode);
|
||||
const stage = $(
|
||||
|
@ -163,7 +167,10 @@ class CodeBlockEditor implements CodeBlockEditorInterface {
|
|||
);
|
||||
root.append(stage);
|
||||
const pre = stage.find('pre')[0];
|
||||
this.runMode(value || '', mode, pre, this.getConfig(value, mode));
|
||||
this.runMode(value || '', mode, pre, {
|
||||
...this.getConfig(value, mode),
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
save() {
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
|
||||
.am-engine .CodeMirror,
|
||||
.am-engine-view .CodeMirror {
|
||||
|
||||
/* \u5b57\u4f53\u53c2\u7167 github\uff0c\u8003\u8651\u548c 14px \u6587\u5b57\u5728\u4e00\u8d77\u6392\u7248\uff0c\u5b57\u53f7\u7528 13px */
|
||||
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: #595959;
|
||||
direction: ltr;
|
||||
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.am-engine .CodeMirror-lines,
|
||||
|
@ -374,15 +374,6 @@
|
|||
|
||||
}
|
||||
|
||||
.am-engine .CodeMirror,
|
||||
.am-engine-view .CodeMirror {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
background: transparent;
|
||||
|
||||
}
|
||||
|
||||
.am-engine .CodeMirror-scroll,
|
||||
.am-engine-view .CodeMirror-scroll {
|
||||
overflow: scroll !important;
|
||||
|
@ -431,7 +422,7 @@
|
|||
top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
display: none !important;
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
|
@ -441,7 +432,7 @@
|
|||
left: 0;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
display: none !important;
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
|
@ -466,7 +457,7 @@
|
|||
top: 0;
|
||||
min-height: 100%;
|
||||
background: #f9f9f9;
|
||||
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.am-engine .CodeMirror-gutter,
|
||||
|
@ -609,6 +600,11 @@
|
|||
|
||||
}
|
||||
|
||||
.am-engine .CodeMirror-simplescroll-horizontal, .am-engine-view .CodeMirror-simplescroll-horizontal {
|
||||
bottom: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.am-engine .CodeMirror-measure,
|
||||
.am-engine-view .CodeMirror-measure {
|
||||
position: absolute;
|
||||
|
@ -748,17 +744,6 @@
|
|||
|
||||
}
|
||||
|
||||
.am-engine-view .CodeMirror {
|
||||
padding: 16px;
|
||||
overflow: initial;
|
||||
|
||||
}
|
||||
|
||||
.am-engine-view .CodeMirror pre {
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
|
||||
.am-content-editor .am-engine .data-codeblock-container .CodeMirror-lines {
|
||||
min-height: 40px;
|
||||
}
|
|
@ -18,6 +18,7 @@ import './index.css';
|
|||
export type CodeBlockValue = {
|
||||
mode?: string;
|
||||
code?: string;
|
||||
autoWrap?: boolean;
|
||||
};
|
||||
|
||||
class CodeBlcok extends Card<CodeBlockValue> {
|
||||
|
@ -82,10 +83,30 @@ class CodeBlcok extends Card<CodeBlockValue> {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
#viewAutoWrap?: boolean = undefined;
|
||||
toolbar(): Array<CardToolbarItemOptions | ToolbarItemOptions> {
|
||||
if (!isEngine(this.editor) || this.editor.readonly) {
|
||||
return [{ type: 'copy' }];
|
||||
return [
|
||||
{ type: 'copy' },
|
||||
{
|
||||
type: 'switch',
|
||||
content: this.editor.language.get<string>(
|
||||
CodeBlcok.cardName,
|
||||
'autoWrap',
|
||||
),
|
||||
getState: () => {
|
||||
if (this.#viewAutoWrap === undefined) {
|
||||
this.#viewAutoWrap = !!this.getValue()?.autoWrap;
|
||||
}
|
||||
return this.#viewAutoWrap;
|
||||
},
|
||||
onClick: () => {
|
||||
const autoWrap = !this.#viewAutoWrap;
|
||||
this.#viewAutoWrap = autoWrap;
|
||||
this.codeEditor?.setAutoWrap(autoWrap);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
{
|
||||
|
@ -117,6 +138,24 @@ class CodeBlcok extends Card<CodeBlockValue> {
|
|||
}, 100);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
content: this.editor.language.get<string>(
|
||||
CodeBlcok.cardName,
|
||||
'autoWrap',
|
||||
),
|
||||
getState: () => {
|
||||
return !!this.getValue()?.autoWrap;
|
||||
},
|
||||
onClick: () => {
|
||||
const value = this.getValue();
|
||||
const autoWrap = !value?.autoWrap;
|
||||
this.setValue({
|
||||
autoWrap,
|
||||
});
|
||||
this.codeEditor?.setAutoWrap(autoWrap);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -139,13 +178,18 @@ class CodeBlcok extends Card<CodeBlockValue> {
|
|||
if (isEngine(this.editor)) {
|
||||
if (this.mirror) {
|
||||
this.codeEditor.update(mode, code);
|
||||
this.codeEditor.setAutoWrap(!!value?.autoWrap);
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.mirror = this.codeEditor?.create(mode, code);
|
||||
this.mirror = this.codeEditor?.create(mode, code, {
|
||||
lineWrapping: !!value?.autoWrap,
|
||||
});
|
||||
}, 50);
|
||||
} else {
|
||||
this.codeEditor.render(mode, code);
|
||||
this.codeEditor?.create(mode, code, {
|
||||
lineWrapping: !!value?.autoWrap,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,3 +30,5 @@ import 'codemirror/mode/vb/vb';
|
|||
import 'codemirror/mode/velocity/velocity';
|
||||
import 'codemirror/mode/xml/xml';
|
||||
import 'codemirror/mode/yaml/yaml';
|
||||
import 'codemirror/addon/scroll/simplescrollbars';
|
||||
import 'codemirror/addon/scroll/simplescrollbars.css';
|
||||
|
|
|
@ -23,7 +23,8 @@ export interface CodeBlockEditorInterface {
|
|||
getSyntax(mode: string): string;
|
||||
create(mode: string, value: string, options?: EditorConfiguration): Editor;
|
||||
update(mode: string, value?: string): void;
|
||||
render(mode: string, value: string): void;
|
||||
setAutoWrap(value: boolean): void;
|
||||
render(mode: string, value: string, options?: EditorConfiguration): void;
|
||||
save(): void;
|
||||
focus(): void;
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
decodeCardValue,
|
||||
} from '@aomao/engine';
|
||||
import CodeBlockComponent, { CodeBlockEditor } from './component';
|
||||
import locales from './locales';
|
||||
|
||||
export interface Options extends PluginOptions {
|
||||
hotkey?: string | Array<string>;
|
||||
|
@ -42,6 +43,7 @@ export default class extends Plugin<Options> {
|
|||
}
|
||||
|
||||
init() {
|
||||
this.editor.language.add(locales);
|
||||
this.editor.on('parse:html', (node) => this.parseHtml(node));
|
||||
this.editor.on('paste:schema', (schema) => this.pasteSchema(schema));
|
||||
this.editor.on('paste:each', (child) => this.pasteHtml(child));
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
codeblock: {
|
||||
autoWrap: 'Auto Wrap',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
import en from './en-US';
|
||||
import cn from './zh-CN';
|
||||
|
||||
export default {
|
||||
'en-US': en,
|
||||
'zh-CN': cn,
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
codeblock: {
|
||||
autoWrap: '自动换行',
|
||||
},
|
||||
};
|
|
@ -94,7 +94,7 @@ export default class FileCard extends Card<FileValue> {
|
|||
onBeforeRender = (action: 'preview' | 'download', url: string) => {
|
||||
const filePlugin = this.editor.plugin.components['file'];
|
||||
if (filePlugin) {
|
||||
const { onBeforeRender } = filePlugin['options'] || {};
|
||||
const { onBeforeRender } = (filePlugin['options'] || {}) as any;
|
||||
if (onBeforeRender) return onBeforeRender(action, url);
|
||||
}
|
||||
return url;
|
||||
|
|
|
@ -263,7 +263,8 @@ class ImageComponent extends Card<ImageValue> {
|
|||
onBeforeRender: (status, src) => {
|
||||
const imagePlugin = this.editor.plugin.components['image'];
|
||||
if (imagePlugin) {
|
||||
const { onBeforeRender } = imagePlugin['options'] || {};
|
||||
const { onBeforeRender } = (imagePlugin['options'] ||
|
||||
{}) as any;
|
||||
if (onBeforeRender) return onBeforeRender(status, src);
|
||||
}
|
||||
return src;
|
||||
|
|
|
@ -206,7 +206,7 @@ export default class extends Plugin<Options> {
|
|||
getUrl(value: ImageValue) {
|
||||
const imagePlugin = this.editor.plugin.components['image'];
|
||||
if (imagePlugin) {
|
||||
const { onBeforeRender } = imagePlugin['options'] || {};
|
||||
const { onBeforeRender } = (imagePlugin['options'] || {}) as any;
|
||||
if (onBeforeRender) return onBeforeRender(value.status, value.src);
|
||||
}
|
||||
return value.src;
|
||||
|
|
|
@ -160,6 +160,7 @@ class TableComponent extends Card<TableValue> implements TableInterface {
|
|||
return true;
|
||||
}
|
||||
nextIndex++;
|
||||
return false;
|
||||
},
|
||||
);
|
||||
if (nextTd) {
|
||||
|
@ -169,6 +170,7 @@ class TableComponent extends Card<TableValue> implements TableInterface {
|
|||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
});
|
||||
// 上键选择
|
||||
this.editor.on('keydown:up', (event) => {
|
||||
|
@ -204,6 +206,7 @@ class TableComponent extends Card<TableValue> implements TableInterface {
|
|||
return true;
|
||||
}
|
||||
prevIndex++;
|
||||
return false;
|
||||
},
|
||||
);
|
||||
if (prevTd) {
|
||||
|
@ -213,6 +216,7 @@ class TableComponent extends Card<TableValue> implements TableInterface {
|
|||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
});
|
||||
}
|
||||
if (this.colorTool) return;
|
||||
|
|
|
@ -177,7 +177,11 @@ class VideoComponent extends Card<VideoValue> {
|
|||
return `
|
||||
<div class="data-video">
|
||||
<div class="data-video-content data-video-done"></div>
|
||||
${videoPlugin && videoPlugin.options.showTitle !== false ? titleElement : ''}
|
||||
${
|
||||
videoPlugin && (videoPlugin.options as any).showTitle !== false
|
||||
? titleElement
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -185,7 +189,7 @@ class VideoComponent extends Card<VideoValue> {
|
|||
onBeforeRender = (action: 'query' | 'download' | 'cover', url: string) => {
|
||||
const videoPlugin = this.editor.plugin.components['video'];
|
||||
if (videoPlugin) {
|
||||
const { onBeforeRender } = videoPlugin['options'] || {};
|
||||
const { onBeforeRender } = (videoPlugin['options'] || {}) as any;
|
||||
if (onBeforeRender) return onBeforeRender(action, url);
|
||||
}
|
||||
return url;
|
||||
|
|
Loading…
Reference in New Issue