Developing a legal IDE based on Atom
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
7.4 KiB

const fs = require('fs-plus')
const { CompositeDisposable } = require('atom')
const SuggestedDefinition = require('./suggested-definition')
let MarkdownPreviewView = null
let renderer = null
let Definitions = null
let definitionsMapper = {}
const isMarkdownPreviewView = function (object) {
if (MarkdownPreviewView == null) {
MarkdownPreviewView = require('./markdown-preview-view')
}
return object instanceof MarkdownPreviewView
}
const getDefinitionsHandler = function (editor) {
if (Definitions == null) {
Definitions = require('./definitions')
}
return new Definitions(editor)
}
module.exports = {
suggestedDefinitionView: null,
modalPanel: null,
activate (state) {
this.disposables = new CompositeDisposable()
this.commandSubscriptions = new CompositeDisposable()
this.disposables.add(
atom.config.observe('markdown-preview.grammars', grammars => {
this.commandSubscriptions.dispose()
this.commandSubscriptions = new CompositeDisposable()
if (grammars == null) {
grammars = []
}
for (const grammar of grammars.map(grammar =>
grammar.replace(/\./g, ' ')
)) {
this.commandSubscriptions.add(
atom.commands.add(`atom-text-editor[data-grammar='${grammar}']`, {
'markdown-preview:toggle': () => this.toggle(),
'markdown-preview:copy-html': {
displayName: 'Markdown Preview: Copy HTML',
didDispatch: () => this.copyHTML()
},
'markdown-preview:save-as-html': {
displayName: 'Markdown Preview: Save as HTML',
didDispatch: () => this.saveAsHTML()
},
'markdown-preview:toggle-break-on-single-newline': () => {
const keyPath = 'markdown-preview.breakOnSingleNewline'
atom.config.set(keyPath, !atom.config.get(keyPath))
},
'markdown-preview:toggle-github-style': () => {
const keyPath = 'markdown-preview.useGitHubStyle'
atom.config.set(keyPath, !atom.config.get(keyPath))
}
})
)
}
})
)
const previewFile = this.previewFile.bind(this)
for (const extension of [
'markdown',
'md',
'mdown',
'mkd',
'mkdown',
'ron',
'txt'
]) {
this.disposables.add(
atom.commands.add(
`.tree-view .file .name[data-name$=\\.${extension}]`,
'markdown-preview:preview-file',
previewFile
)
)
}
this.disposables.add(
atom.workspace.addOpener(uriToOpen => {
let [protocol, path] = uriToOpen.split('://')
if (protocol !== 'markdown-preview') {
return
}
try {
path = decodeURI(path)
} catch (error) {
return
}
if (path.startsWith('editor/')) {
return this.createMarkdownPreviewView({ editorId: path.substring(7) })
} else {
return this.createMarkdownPreviewView({ filePath: path })
}
})
)
this.suggestedDefinitionView = new SuggestedDefinition()
this.disposables.add(
atom.workspace.observeTextEditors(editor => {
if (editor.buffer && editor.buffer.file) {
const path = editor.buffer.file.path.split('.').pop()
if (path === 'md') { // @TODO Custom extension? Otherwise all markdown files will be handled.
this.bootContractHandler(editor)
}
}
})
)
},
deactivate () {
this.modalPanel.destroy()
this.disposables.dispose()
this.commandSubscriptions.dispose()
this.suggestedDefinitionView.destroy()
},
serialize () {},
createMarkdownPreviewView (state) {
if (state.editorId || fs.isFileSync(state.filePath)) {
if (MarkdownPreviewView == null) {
MarkdownPreviewView = require('./markdown-preview-view')
}
return new MarkdownPreviewView(state)
}
},
toggle () {
if (isMarkdownPreviewView(atom.workspace.getActivePaneItem())) {
atom.workspace.destroyActivePaneItem()
return
}
const editor = atom.workspace.getActiveTextEditor()
if (editor == null) {
return
}
const grammars = atom.config.get('markdown-preview.grammars') || []
if (!grammars.includes(editor.getGrammar().scopeName)) {
return
}
if (!this.removePreviewForEditor(editor)) {
return this.addPreviewForEditor(editor)
}
},
uriForEditor (editor) {
return `markdown-preview://editor/${editor.id}`
},
removePreviewForEditor (editor) {
const uri = this.uriForEditor(editor)
const previewPane = atom.workspace.paneForURI(uri)
if (previewPane != null) {
previewPane.destroyItem(previewPane.itemForURI(uri))
return true
} else {
return false
}
},
addPreviewForEditor (editor) {
const uri = this.uriForEditor(editor)
const previousActivePane = atom.workspace.getActivePane()
const options = { searchAllPanes: true }
if (atom.config.get('markdown-preview.openPreviewInSplitPane')) {
options.split = 'right'
}
return atom.workspace
.open(uri, options)
.then(function (markdownPreviewView) {
if (isMarkdownPreviewView(markdownPreviewView)) {
previousActivePane.activate()
}
})
},
previewFile ({ target }) {
const filePath = target.dataset.path
if (!filePath) {
return
}
for (const editor of atom.workspace.getTextEditors()) {
if (editor.getPath() === filePath) {
return this.addPreviewForEditor(editor)
}
}
atom.workspace.open(`markdown-preview://${encodeURI(filePath)}`, {
searchAllPanes: true
})
},
async copyHTML () {
const editor = atom.workspace.getActiveTextEditor()
if (editor == null) {
return
}
if (renderer == null) {
renderer = require('./renderer')
}
const text = editor.getSelectedText() || editor.getText()
const html = await renderer.toHTML(
text,
editor.getPath(),
editor.getGrammar()
)
atom.clipboard.write(html)
},
saveAsHTML () {
const activePaneItem = atom.workspace.getActivePaneItem()
if (isMarkdownPreviewView(activePaneItem)) {
atom.workspace.getActivePane().saveItemAs(activePaneItem)
return
}
const editor = atom.workspace.getActiveTextEditor()
if (editor == null) {
return
}
const grammars = atom.config.get('markdown-preview.grammars') || []
if (!grammars.includes(editor.getGrammar().scopeName)) {
return
}
const uri = this.uriForEditor(editor)
const markdownPreviewPane = atom.workspace.paneForURI(uri)
const markdownPreviewPaneItem =
markdownPreviewPane != null
? markdownPreviewPane.itemForURI(uri)
: undefined
if (isMarkdownPreviewView(markdownPreviewPaneItem)) {
return markdownPreviewPane.saveItemAs(markdownPreviewPaneItem)
}
},
bootContractHandler (editor) {
definitionsMapper[editor.id] = getDefinitionsHandler(editor)
definitionsMapper[editor.id].boot()
setInterval(() => {
definitionsMapper[editor.id].boot()
}, 5000)
const editorView = atom.views.getView(editor)
editorView.addEventListener('keypress', (event) => {
if (event.keyCode !== 95) {
return
}
this.suggestedDefinitionView.show(editor, definitionsMapper[editor.id].getDefinedDefinitions())
})
}
}