1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-16 03:06:27 +00:00

Merge pull request #2586 from GuilhermeJSilva/feature/autoBracketMatching

Feature/auto bracket matching
This commit is contained in:
Junyoung Choi
2018-12-25 00:24:37 +09:00
committed by GitHub
8 changed files with 259 additions and 73 deletions

View File

@@ -5,7 +5,11 @@ import CodeMirror from 'codemirror'
import 'codemirror-mode-elixir' import 'codemirror-mode-elixir'
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement' import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
import convertModeName from 'browser/lib/convertModeName' import convertModeName from 'browser/lib/convertModeName'
import { options, TableEditor, Alignment } from '@susisu/mte-kernel' import {
options,
TableEditor,
Alignment
} from '@susisu/mte-kernel'
import TextEditorInterface from 'browser/lib/TextEditorInterface' import TextEditorInterface from 'browser/lib/TextEditorInterface'
import eventEmitter from 'browser/main/lib/eventEmitter' import eventEmitter from 'browser/main/lib/eventEmitter'
import iconv from 'iconv-lite' import iconv from 'iconv-lite'
@@ -18,12 +22,16 @@ import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
const spellcheck = require('browser/lib/spellcheck') const spellcheck = require('browser/lib/spellcheck')
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder') const buildEditorContextMenu = require('browser/lib/contextMenuBuilder')
import TurndownService from 'turndown' import TurndownService from 'turndown'
import { gfm } from 'turndown-plugin-gfm' import {
gfm
} from 'turndown-plugin-gfm'
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
const buildCMRulers = (rulers, enableRulers) => const buildCMRulers = (rulers, enableRulers) =>
(enableRulers ? rulers.map(ruler => ({ column: ruler })) : []) (enableRulers ? rulers.map(ruler => ({
column: ruler
})) : [])
function translateHotkey (hotkey) { function translateHotkey (hotkey) {
return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl') return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl')
@@ -54,7 +62,10 @@ export default class CodeEditor extends React.Component {
} }
this.props.onBlur != null && this.props.onBlur(e) this.props.onBlur != null && this.props.onBlur(e)
const { storageKey, noteKey } = this.props const {
storageKey,
noteKey
} = this.props
attachmentManagement.deleteAttachmentsNotPresentInNote( attachmentManagement.deleteAttachmentsNotPresentInNote(
this.editor.getValue(), this.editor.getValue(),
storageKey, storageKey,
@@ -124,7 +135,9 @@ export default class CodeEditor extends React.Component {
} }
handleFormatTable () { handleFormatTable () {
this.tableEditor.formatAll(options({textWidthOptions: {}})) this.tableEditor.formatAll(options({
textWidthOptions: {}
}))
} }
handleEditorActivity () { handleEditorActivity () {
@@ -253,9 +266,9 @@ export default class CodeEditor extends React.Component {
foldGutter: true, foldGutter: true,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
autoCloseBrackets: { autoCloseBrackets: {
pairs: '()[]{}\'\'""$$**``', pairs: this.props.matchingPairs,
triples: '```"""\'\'\'', triples: this.props.matchingTriples,
explode: '[]{}``$$', explode: this.props.explodingPairs,
override: true override: true
}, },
extraKeys: this.defaultKeyMap extraKeys: this.defaultKeyMap
@@ -298,43 +311,117 @@ export default class CodeEditor extends React.Component {
}) })
this.editorKeyMap = CodeMirror.normalizeKeyMap({ this.editorKeyMap = CodeMirror.normalizeKeyMap({
'Tab': () => { this.tableEditor.nextCell(this.tableEditorOptions) }, 'Tab': () => {
'Shift-Tab': () => { this.tableEditor.previousCell(this.tableEditorOptions) }, this.tableEditor.nextCell(this.tableEditorOptions)
'Enter': () => { this.tableEditor.nextRow(this.tableEditorOptions) }, },
'Ctrl-Enter': () => { this.tableEditor.escape(this.tableEditorOptions) }, 'Shift-Tab': () => {
'Cmd-Enter': () => { this.tableEditor.escape(this.tableEditorOptions) }, this.tableEditor.previousCell(this.tableEditorOptions)
'Shift-Ctrl-Left': () => { this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions) }, },
'Shift-Cmd-Left': () => { this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions) }, 'Enter': () => {
'Shift-Ctrl-Right': () => { this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions) }, this.tableEditor.nextRow(this.tableEditorOptions)
'Shift-Cmd-Right': () => { this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions) }, },
'Shift-Ctrl-Up': () => { this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions) }, 'Ctrl-Enter': () => {
'Shift-Cmd-Up': () => { this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions) }, this.tableEditor.escape(this.tableEditorOptions)
'Shift-Ctrl-Down': () => { this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions) }, },
'Shift-Cmd-Down': () => { this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions) }, 'Cmd-Enter': () => {
'Ctrl-Left': () => { this.tableEditor.moveFocus(0, -1, this.tableEditorOptions) }, this.tableEditor.escape(this.tableEditorOptions)
'Cmd-Left': () => { this.tableEditor.moveFocus(0, -1, this.tableEditorOptions) }, },
'Ctrl-Right': () => { this.tableEditor.moveFocus(0, 1, this.tableEditorOptions) }, 'Shift-Ctrl-Left': () => {
'Cmd-Right': () => { this.tableEditor.moveFocus(0, 1, this.tableEditorOptions) }, this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions)
'Ctrl-Up': () => { this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions) }, },
'Cmd-Up': () => { this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions) }, 'Shift-Cmd-Left': () => {
'Ctrl-Down': () => { this.tableEditor.moveFocus(1, 0, this.tableEditorOptions) }, this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions)
'Cmd-Down': () => { this.tableEditor.moveFocus(1, 0, this.tableEditorOptions) }, },
'Ctrl-K Ctrl-I': () => { this.tableEditor.insertRow(this.tableEditorOptions) }, 'Shift-Ctrl-Right': () => {
'Cmd-K Cmd-I': () => { this.tableEditor.insertRow(this.tableEditorOptions) }, this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions)
'Ctrl-L Ctrl-I': () => { this.tableEditor.deleteRow(this.tableEditorOptions) }, },
'Cmd-L Cmd-I': () => { this.tableEditor.deleteRow(this.tableEditorOptions) }, 'Shift-Cmd-Right': () => {
'Ctrl-K Ctrl-J': () => { this.tableEditor.insertColumn(this.tableEditorOptions) }, this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions)
'Cmd-K Cmd-J': () => { this.tableEditor.insertColumn(this.tableEditorOptions) }, },
'Ctrl-L Ctrl-J': () => { this.tableEditor.deleteColumn(this.tableEditorOptions) }, 'Shift-Ctrl-Up': () => {
'Cmd-L Cmd-J': () => { this.tableEditor.deleteColumn(this.tableEditorOptions) }, this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions)
'Alt-Shift-Ctrl-Left': () => { this.tableEditor.moveColumn(-1, this.tableEditorOptions) }, },
'Alt-Shift-Cmd-Left': () => { this.tableEditor.moveColumn(-1, this.tableEditorOptions) }, 'Shift-Cmd-Up': () => {
'Alt-Shift-Ctrl-Right': () => { this.tableEditor.moveColumn(1, this.tableEditorOptions) }, this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions)
'Alt-Shift-Cmd-Right': () => { this.tableEditor.moveColumn(1, this.tableEditorOptions) }, },
'Alt-Shift-Ctrl-Up': () => { this.tableEditor.moveRow(-1, this.tableEditorOptions) }, 'Shift-Ctrl-Down': () => {
'Alt-Shift-Cmd-Up': () => { this.tableEditor.moveRow(-1, this.tableEditorOptions) }, this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions)
'Alt-Shift-Ctrl-Down': () => { this.tableEditor.moveRow(1, this.tableEditorOptions) }, },
'Alt-Shift-Cmd-Down': () => { this.tableEditor.moveRow(1, this.tableEditorOptions) } 'Shift-Cmd-Down': () => {
this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions)
},
'Ctrl-Left': () => {
this.tableEditor.moveFocus(0, -1, this.tableEditorOptions)
},
'Cmd-Left': () => {
this.tableEditor.moveFocus(0, -1, this.tableEditorOptions)
},
'Ctrl-Right': () => {
this.tableEditor.moveFocus(0, 1, this.tableEditorOptions)
},
'Cmd-Right': () => {
this.tableEditor.moveFocus(0, 1, this.tableEditorOptions)
},
'Ctrl-Up': () => {
this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions)
},
'Cmd-Up': () => {
this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions)
},
'Ctrl-Down': () => {
this.tableEditor.moveFocus(1, 0, this.tableEditorOptions)
},
'Cmd-Down': () => {
this.tableEditor.moveFocus(1, 0, this.tableEditorOptions)
},
'Ctrl-K Ctrl-I': () => {
this.tableEditor.insertRow(this.tableEditorOptions)
},
'Cmd-K Cmd-I': () => {
this.tableEditor.insertRow(this.tableEditorOptions)
},
'Ctrl-L Ctrl-I': () => {
this.tableEditor.deleteRow(this.tableEditorOptions)
},
'Cmd-L Cmd-I': () => {
this.tableEditor.deleteRow(this.tableEditorOptions)
},
'Ctrl-K Ctrl-J': () => {
this.tableEditor.insertColumn(this.tableEditorOptions)
},
'Cmd-K Cmd-J': () => {
this.tableEditor.insertColumn(this.tableEditorOptions)
},
'Ctrl-L Ctrl-J': () => {
this.tableEditor.deleteColumn(this.tableEditorOptions)
},
'Cmd-L Cmd-J': () => {
this.tableEditor.deleteColumn(this.tableEditorOptions)
},
'Alt-Shift-Ctrl-Left': () => {
this.tableEditor.moveColumn(-1, this.tableEditorOptions)
},
'Alt-Shift-Cmd-Left': () => {
this.tableEditor.moveColumn(-1, this.tableEditorOptions)
},
'Alt-Shift-Ctrl-Right': () => {
this.tableEditor.moveColumn(1, this.tableEditorOptions)
},
'Alt-Shift-Cmd-Right': () => {
this.tableEditor.moveColumn(1, this.tableEditorOptions)
},
'Alt-Shift-Ctrl-Up': () => {
this.tableEditor.moveRow(-1, this.tableEditorOptions)
},
'Alt-Shift-Cmd-Up': () => {
this.tableEditor.moveRow(-1, this.tableEditorOptions)
},
'Alt-Shift-Ctrl-Down': () => {
this.tableEditor.moveRow(1, this.tableEditorOptions)
},
'Alt-Shift-Cmd-Down': () => {
this.tableEditor.moveRow(1, this.tableEditorOptions)
}
}) })
if (this.props.enableTableEditor) { if (this.props.enableTableEditor) {
@@ -423,8 +510,14 @@ export default class CodeEditor extends React.Component {
return { return {
text: wordBeforeCursor, text: wordBeforeCursor,
range: { range: {
from: { line: lineNumber, ch: originCursorPosition }, from: {
to: { line: lineNumber, ch: cursorPosition } line: lineNumber,
ch: originCursorPosition
},
to: {
line: lineNumber,
ch: cursorPosition
}
} }
} }
} }
@@ -450,7 +543,10 @@ export default class CodeEditor extends React.Component {
componentDidUpdate (prevProps, prevState) { componentDidUpdate (prevProps, prevState) {
let needRefresh = false let needRefresh = false
const { rulers, enableRulers } = this.props const {
rulers,
enableRulers
} = this.props
if (prevProps.mode !== this.props.mode) { if (prevProps.mode !== this.props.mode) {
this.setMode(this.props.mode) this.setMode(this.props.mode)
} }
@@ -491,6 +587,18 @@ export default class CodeEditor extends React.Component {
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd) this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
} }
if (prevProps.matchingPairs !== this.props.matchingPairs ||
prevProps.matchingTriples !== this.props.matchingTriples ||
prevProps.explodingPairs !== this.props.explodingPairs) {
const bracketObject = {
pairs: this.props.matchingPairs,
triples: this.props.matchingTriples,
explode: this.props.explodingPairs,
override: true
}
this.editor.setOption('autoCloseBrackets', bracketObject)
}
if (prevProps.enableTableEditor !== this.props.enableTableEditor) { if (prevProps.enableTableEditor !== this.props.enableTableEditor) {
if (this.props.enableTableEditor) { if (this.props.enableTableEditor) {
this.editor.on('cursorActivity', this.editorActivityHandler) this.editor.on('cursorActivity', this.editorActivityHandler)
@@ -523,7 +631,7 @@ export default class CodeEditor extends React.Component {
if (prevProps.spellCheck !== this.props.spellCheck) { if (prevProps.spellCheck !== this.props.spellCheck) {
if (this.props.spellCheck === false) { if (this.props.spellCheck === false) {
spellcheck.setLanguage(this.editor, spellcheck.SPELLCHECK_DISABLED) spellcheck.setLanguage(this.editor, spellcheck.SPELLCHECK_DISABLED)
let elem = document.getElementById('editor-bottom-panel') const elem = document.getElementById('editor-bottom-panel')
elem.parentNode.removeChild(elem) elem.parentNode.removeChild(elem)
} else { } else {
this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'}) this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'})
@@ -672,7 +780,10 @@ export default class CodeEditor extends React.Component {
handleDropImage (dropEvent) { handleDropImage (dropEvent) {
dropEvent.preventDefault() dropEvent.preventDefault()
const { storageKey, noteKey } = this.props const {
storageKey,
noteKey
} = this.props
attachmentManagement.handleAttachmentDrop( attachmentManagement.handleAttachmentDrop(
this, this,
storageKey, storageKey,
@@ -695,15 +806,21 @@ export default class CodeEditor extends React.Component {
const isInLinkTag = editor => { const isInLinkTag = editor => {
const startCursor = editor.getCursor('start') const startCursor = editor.getCursor('start')
const prevChar = editor.getRange( const prevChar = editor.getRange({
{ line: startCursor.line, ch: startCursor.ch - 2 }, line: startCursor.line,
{ line: startCursor.line, ch: startCursor.ch } ch: startCursor.ch - 2
) }, {
line: startCursor.line,
ch: startCursor.ch
})
const endCursor = editor.getCursor('end') const endCursor = editor.getCursor('end')
const nextChar = editor.getRange( const nextChar = editor.getRange({
{ line: endCursor.line, ch: endCursor.ch }, line: endCursor.line,
{ line: endCursor.line, ch: endCursor.ch + 1 } ch: endCursor.ch
) }, {
line: endCursor.line,
ch: endCursor.ch + 1
})
return prevChar === '](' && nextChar === ')' return prevChar === '](' && nextChar === ')'
} }
@@ -919,20 +1036,28 @@ export default class CodeEditor extends React.Component {
} }
render () { render () {
const {className, fontSize} = this.props const {
className,
fontSize
} = this.props
const fontFamily = normalizeEditorFontFamily(this.props.fontFamily) const fontFamily = normalizeEditorFontFamily(this.props.fontFamily)
const width = this.props.width const width = this.props.width
return ( return (<
<div div className={
className={className == null ? 'CodeEditor' : `CodeEditor ${className}`} className == null ? 'CodeEditor' : `CodeEditor ${className}`
ref='root' }
tabIndex='-1' ref='root'
style={{ tabIndex='-1'
fontFamily, style={
fontSize: fontSize, {
width: width fontFamily,
}} fontSize: fontSize,
onDrop={e => this.handleDropImage(e)} width: width
}
}
onDrop={
e => this.handleDropImage(e)
}
/> />
) )
} }

View File

@@ -293,6 +293,9 @@ class MarkdownEditor extends React.Component {
enableRulers={config.editor.enableRulers} enableRulers={config.editor.enableRulers}
rulers={config.editor.rulers} rulers={config.editor.rulers}
displayLineNumbers={config.editor.displayLineNumbers} displayLineNumbers={config.editor.displayLineNumbers}
matchingPairs={config.editor.matchingPairs}
matchingTriples={config.editor.matchingTriples}
explodingPairs={config.editor.explodingPairs}
scrollPastEnd={config.editor.scrollPastEnd} scrollPastEnd={config.editor.scrollPastEnd}
storageKey={storageKey} storageKey={storageKey}
noteKey={noteKey} noteKey={noteKey}

View File

@@ -160,6 +160,9 @@ class MarkdownSplitEditor extends React.Component {
fontFamily={config.editor.fontFamily} fontFamily={config.editor.fontFamily}
fontSize={editorFontSize} fontSize={editorFontSize}
displayLineNumbers={config.editor.displayLineNumbers} displayLineNumbers={config.editor.displayLineNumbers}
matchingPairs={config.editor.matchingPairs}
matchingTriples={config.editor.matchingTriples}
explodingPairs={config.editor.explodingPairs}
indentType={config.editor.indentType} indentType={config.editor.indentType}
indentSize={editorIndentSize} indentSize={editorIndentSize}
enableRulers={config.editor.enableRulers} enableRulers={config.editor.enableRulers}

View File

@@ -722,6 +722,9 @@ class SnippetNoteDetail extends React.Component {
indentType={config.editor.indentType} indentType={config.editor.indentType}
indentSize={editorIndentSize} indentSize={editorIndentSize}
displayLineNumbers={config.editor.displayLineNumbers} displayLineNumbers={config.editor.displayLineNumbers}
matchingPairs={config.editor.matchingPairs}
matchingTriples={config.editor.matchingTriples}
explodingPairs={config.editor.explodingPairs}
keyMap={config.editor.keyMap} keyMap={config.editor.keyMap}
scrollPastEnd={config.editor.scrollPastEnd} scrollPastEnd={config.editor.scrollPastEnd}
fetchUrlTitle={config.editor.fetchUrlTitle} fetchUrlTitle={config.editor.fetchUrlTitle}

View File

@@ -45,6 +45,9 @@ export const DEFAULT_CONFIG = {
enableRulers: false, enableRulers: false,
rulers: [80, 120], rulers: [80, 120],
displayLineNumbers: true, displayLineNumbers: true,
matchingPairs: '()[]{}\'\'""$$**``',
matchingTriples: '```"""\'\'\'',
explodingPairs: '[]{}``$$',
switchPreview: 'BLUR', // 'BLUR', 'DBL_CLICK', 'RIGHTCLICK' switchPreview: 'BLUR', // 'BLUR', 'DBL_CLICK', 'RIGHTCLICK'
delfaultStatus: 'PREVIEW', // 'PREVIEW', 'CODE' delfaultStatus: 'PREVIEW', // 'PREVIEW', 'CODE'
scrollPastEnd: false, scrollPastEnd: false,

View File

@@ -28,9 +28,9 @@ class SnippetEditor extends React.Component {
foldGutter: true, foldGutter: true,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
autoCloseBrackets: { autoCloseBrackets: {
pairs: '()[]{}\'\'""$$**``', pairs: this.props.matchingPairs,
triples: '```"""\'\'\'', triples: this.props.matchingTriples,
explode: '[]{}``$$', explode: this.props.explodingPairs,
override: true override: true
}, },
mode: 'null' mode: 'null'

View File

@@ -136,6 +136,9 @@ class SnippetTab extends React.Component {
enableRulers={config.editor.enableRulers} enableRulers={config.editor.enableRulers}
rulers={config.editor.rulers} rulers={config.editor.rulers}
displayLineNumbers={config.editor.displayLineNumbers} displayLineNumbers={config.editor.displayLineNumbers}
matchingPairs={config.editor.matchingPairs}
matchingTriples={config.editor.matchingTriples}
explodingPairs={config.editor.explodingPairs}
scrollPastEnd={config.editor.scrollPastEnd} scrollPastEnd={config.editor.scrollPastEnd}
onRef={ref => { this.snippetEditor = ref }} /> onRef={ref => { this.snippetEditor = ref }} />
</div> </div>

View File

@@ -96,6 +96,9 @@ class UiTab extends React.Component {
enableTableEditor: this.refs.enableTableEditor.checked, enableTableEditor: this.refs.enableTableEditor.checked,
enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked, enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked,
frontMatterTitleField: this.refs.frontMatterTitleField.value, frontMatterTitleField: this.refs.frontMatterTitleField.value,
matchingPairs: this.refs.matchingPairs.value,
matchingTriples: this.refs.matchingTriples.value,
explodingPairs: this.refs.explodingPairs.value,
spellcheck: this.refs.spellcheck.checked, spellcheck: this.refs.spellcheck.checked,
enableSmartPaste: this.refs.enableSmartPaste.checked enableSmartPaste: this.refs.enableSmartPaste.checked
}, },
@@ -576,6 +579,48 @@ class UiTab extends React.Component {
</label> </label>
</div> </div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Matching character pairs')}
</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
value={this.state.config.editor.matchingPairs}
ref='matchingPairs'
onChange={(e) => this.handleUIChange(e)}
type='text'
/>
</div>
</div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Matching character triples')}
</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
value={this.state.config.editor.matchingTriples}
ref='matchingTriples'
onChange={(e) => this.handleUIChange(e)}
type='text'
/>
</div>
</div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Exploding character pairs')}
</div>
<div styleName='group-section-control'>
<input styleName='group-section-control-input'
value={this.state.config.editor.explodingPairs}
ref='explodingPairs'
onChange={(e) => this.handleUIChange(e)}
type='text'
/>
</div>
</div>
<div styleName='group-header2'>{i18n.__('Preview')}</div> <div styleName='group-header2'>{i18n.__('Preview')}</div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'> <div styleName='group-section-label'>
@@ -603,6 +648,7 @@ class UiTab extends React.Component {
/> />
</div> </div>
</div> </div>
<div styleName='group-section'> <div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Code Block Theme')}</div> <div styleName='group-section-label'>{i18n.__('Code Block Theme')}</div>
<div styleName='group-section-control'> <div styleName='group-section-control'>