New import menu with HTML to Markdown conversion
This commit is contained in:
parent
5b6b9ebeb8
commit
1e8fa944a1
@ -2,7 +2,7 @@
|
||||
|
||||
[![Build Status](https://img.shields.io/travis/benweet/stackedit.svg?style=flat)](https://travis-ci.org/benweet/stackedit) [![NPM version](https://img.shields.io/npm/v/stackedit.svg?style=flat)](https://www.npmjs.org/package/stackedit)
|
||||
|
||||
StackEdit is a full-featured, open-source Markdown editor based on PageDown, the Markdown library used by Stack Overflow and the other Stack Exchange sites.
|
||||
> Full-featured, open-source Markdown editor based on PageDown, the Markdown library used by Stack Overflow and the other Stack Exchange sites.
|
||||
|
||||
https://stackedit.io/.
|
||||
|
||||
@ -14,7 +14,7 @@ https://stackedit.io/.
|
||||
- Edit existing Markdown files from Google Drive, Dropbox and your local hard drive
|
||||
- Post your Markdown file on Blogger/Blogspot, WordPress, Zendesk
|
||||
- Publish your Markdown file on GitHub, Gist, Google Drive, Dropbox
|
||||
- Share a workspace over Google Drive
|
||||
- Share a workspace over Google Drive, CouchDB
|
||||
|
||||
### Features:
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
<publish-menu v-else-if="panel === 'publish'"></publish-menu>
|
||||
<history-menu v-else-if="panel === 'history'"></history-menu>
|
||||
<export-menu v-else-if="panel === 'export'"></export-menu>
|
||||
<import-menu v-else-if="panel === 'import'"></import-menu>
|
||||
<more-menu v-else-if="panel === 'more'"></more-menu>
|
||||
<div v-else-if="panel === 'help'" class="side-bar__panel side-bar__panel--help">
|
||||
<pre class="markdown-highlighting" v-html="markdownSample"></pre>
|
||||
@ -39,6 +40,7 @@ import SyncMenu from './menus/SyncMenu';
|
||||
import PublishMenu from './menus/PublishMenu';
|
||||
import HistoryMenu from './menus/HistoryMenu';
|
||||
import ExportMenu from './menus/ExportMenu';
|
||||
import ImportMenu from './menus/ImportMenu';
|
||||
import MoreMenu from './menus/MoreMenu';
|
||||
import markdownSample from '../data/markdownSample.md';
|
||||
import markdownConversionSvc from '../services/markdownConversionSvc';
|
||||
@ -52,6 +54,7 @@ const panelNames = {
|
||||
publish: 'Publish',
|
||||
history: 'File history',
|
||||
export: 'Export to disk',
|
||||
import: 'Import from disk',
|
||||
more: 'More',
|
||||
};
|
||||
|
||||
@ -64,6 +67,7 @@ export default {
|
||||
PublishMenu,
|
||||
HistoryMenu,
|
||||
ExportMenu,
|
||||
ImportMenu,
|
||||
MoreMenu,
|
||||
},
|
||||
data: () => ({
|
||||
|
83
src/components/menus/ImportMenu.vue
Normal file
83
src/components/menus/ImportMenu.vue
Normal file
@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="side-bar__panel side-bar__panel--menu">
|
||||
<input class="hidden-file" id="import-markdown-file-input" type="file" @change="onImportMarkdown">
|
||||
<label class="menu-entry button flex flex--row flex--align-center" for="import-markdown-file-input">
|
||||
<div class="menu-entry__icon flex flex--column flex--center">
|
||||
<icon-upload></icon-upload>
|
||||
</div>
|
||||
<div class="flex flex--column">
|
||||
<div>Import Markdown</div>
|
||||
<span>Open a plain text file.</span>
|
||||
</div>
|
||||
</label>
|
||||
<input class="hidden-file" id="import-html-file-input" type="file" @change="onImportHtml">
|
||||
<label class="menu-entry button flex flex--row flex--align-center" for="import-html-file-input">
|
||||
<div class="menu-entry__icon flex flex--column flex--center">
|
||||
<icon-upload></icon-upload>
|
||||
</div>
|
||||
<div class="flex flex--column">
|
||||
<div>Import HTML</div>
|
||||
<span>Convert an HTML file to Markdown.</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TurndownService from 'turndown/lib/turndown.browser.umd';
|
||||
import htmlSanitizer from '../../libs/htmlSanitizer';
|
||||
import MenuEntry from './common/MenuEntry';
|
||||
import providerUtils from '../../services/providers/providerUtils';
|
||||
|
||||
const turndownService = new TurndownService({
|
||||
headingStyle: 'atx',
|
||||
hr: '----------',
|
||||
bulletListMarker: '-',
|
||||
codeBlockStyle: 'fenced',
|
||||
});
|
||||
|
||||
const readFile = file => new Promise((resolve) => {
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const content = e.target.result;
|
||||
if (content.match(/\uFFFD/)) {
|
||||
this.$store.dispatch('notification/error', 'File is not readable.');
|
||||
} else {
|
||||
resolve(content);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MenuEntry,
|
||||
},
|
||||
methods: {
|
||||
onImportMarkdown(evt) {
|
||||
const file = evt.target.files[0];
|
||||
readFile(file)
|
||||
.then(content => this.$store.dispatch('createFile', {
|
||||
...providerUtils.parseContent(content),
|
||||
name: file.name,
|
||||
})
|
||||
.then(item => this.$store.commit('file/setCurrentId', item.id)));
|
||||
},
|
||||
onImportHtml(evt) {
|
||||
const file = evt.target.files[0];
|
||||
readFile(file)
|
||||
.then(content => this.$store.dispatch('createFile', {
|
||||
...providerUtils.parseContent(
|
||||
turndownService.turndown(
|
||||
htmlSanitizer.sanitizeHtml(content)
|
||||
.replace(/ /g, ' '), // Replace non-breaking spaces with classic spaces
|
||||
)),
|
||||
name: file.name,
|
||||
}))
|
||||
.then(item => this.$store.commit('file/setCurrentId', item.id));
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -65,15 +65,10 @@
|
||||
<icon-content-save slot="icon"></icon-content-save>
|
||||
Export to disk
|
||||
</menu-entry>
|
||||
<input class="hidden-file" id="import-disk-file-input" type="file" @change="onImportFile">
|
||||
<label class="menu-entry button flex flex--row flex--align-center" for="import-disk-file-input">
|
||||
<div class="menu-entry__icon flex flex--column flex--center">
|
||||
<icon-content-save></icon-content-save>
|
||||
</div>
|
||||
<div class="flex flex--column">
|
||||
Import from disk
|
||||
</div>
|
||||
</label>
|
||||
<menu-entry @click.native="setPanel('import')">
|
||||
<icon-content-save slot="icon"></icon-content-save>
|
||||
Import from disk
|
||||
</menu-entry>
|
||||
<menu-entry @click.native="print">
|
||||
<icon-printer slot="icon"></icon-printer>
|
||||
Print
|
||||
@ -91,7 +86,6 @@ import MenuEntry from './common/MenuEntry';
|
||||
import UserImage from '../UserImage';
|
||||
import googleHelper from '../../services/providers/helpers/googleHelper';
|
||||
import syncSvc from '../../services/syncSvc';
|
||||
import providerUtils from '../../services/providers/providerUtils';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -116,25 +110,6 @@ export default {
|
||||
() => {}, // Cancel
|
||||
);
|
||||
},
|
||||
onImportFile(evt) {
|
||||
const file = evt.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const content = e.target.result;
|
||||
if (content.match(/\uFFFD/)) {
|
||||
this.$store.dispatch('notification/error', 'File is not readable.');
|
||||
} else {
|
||||
this.$store.dispatch('createFile', {
|
||||
...providerUtils.parseContent(content),
|
||||
name: file.name,
|
||||
})
|
||||
.then(item => this.$store.commit('file/setCurrentId', item.id));
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
},
|
||||
fileProperties() {
|
||||
return this.$store.dispatch('modal/open', 'fileProperties')
|
||||
.catch(() => {}); // Cancel
|
||||
|
Loading…
Reference in New Issue
Block a user