Stackedit/src/components/modals/FilePropertiesModal.vue
2022-06-02 07:45:13 +08:00

254 lines
9.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<modal-inner class="modal__inner-1--file-properties" aria-label="文件属性">
<div class="modal__content">
<div class="tabs flex flex--row">
<tab :active="tab === 'simple'" @click="setSimpleTab()">
简单属性
</tab>
<tab :active="tab === 'yaml'" @click="setYamlTab()">
YAML属性
</tab>
</div>
<div v-if="tab === 'simple'">
<div class="modal__title">扩展</div>
<div class="modal__sub-title">配置Markdown引擎。</div>
<form-entry label="Preset">
<select slot="field" class="textfield" v-model="preset" @keydown.enter="resolve()">
<option v-for="(preset, id) in presets" :key="id" :value="preset">
{{ preset }}
</option>
</select>
</form-entry>
<div class="modal__title">元数据</div>
<div class="modal__sub-title">将信息添加到您的发布WordPressBlogger ...</div>
<form-entry label="Title">
<input slot="field" class="textfield" type="text" v-model.trim="title" @keydown.enter="resolve()">
</form-entry>
<form-entry label="Author">
<input slot="field" class="textfield" type="text" v-model.trim="author" @keydown.enter="resolve()">
</form-entry>
<form-entry label="Tags" info="comma-separated">
<input slot="field" class="textfield" type="text" v-model.trim="tags" @keydown.enter="resolve()">
</form-entry>
<form-entry label="Categories" info="comma-separated">
<input slot="field" class="textfield" type="text" v-model.trim="categories" @keydown.enter="resolve()">
</form-entry>
<form-entry label="Excerpt">
<input slot="field" class="textfield" type="text" v-model.trim="excerpt" @keydown.enter="resolve()">
</form-entry>
<form-entry label="Featured image">
<input slot="field" class="textfield" type="text" v-model.trim="featuredImage" @keydown.enter="resolve()">
</form-entry>
<form-entry label="Status">
<input slot="field" class="textfield" type="text" v-model.trim="status" @keydown.enter="resolve()">
<div class="form-entry__info">
<b>示例</b>草稿
</div>
</form-entry>
<form-entry label="Date" info="YYYY-MM-DD">
<input slot="field" class="textfield" type="text" v-model.trim="date" @keydown.enter="resolve()">
</form-entry>
</div>
<div v-if="tab === 'yaml'">
<div class="form-entry" role="tabpanel" aria-label="YAML properties">
<label class="form-entry__label">YAML</label>
<div class="form-entry__field">
<code-editor lang="yaml" :value="yamlProperties" key="custom-properties" @changed="setYamlProperties"></code-editor>
</div>
</div>
<div class="modal__error modal__error--file-properties">{{error}}</div>
<div class="modal__info modal__info--multiline">
<p><strong>提示:</strong> 您可以手动切换扩展名:</p>
<pre class=" language-yaml"><code class="prism language-yaml"><span class="token key atrule">extensions</span><span class="token punctuation">:</span>
<span class="token key atrule">emoji</span><span class="token punctuation">:</span>
<span class="token comment"># 启用表情符号快捷方式如 :) :-(</span>
<span class="token key atrule">shortcuts</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
</code></pre>
<p>使用预设<code>zero</code>制作自己的配置:</p>
<pre class=" language-yaml"><code class="prism language-yaml"><span class="token key atrule">extensions</span><span class="token punctuation">:</span>
<span class="token key atrule">preset</span><span class="token punctuation">:</span> zero
<span class="token key atrule">markdown</span><span class="token punctuation">:</span>
<span class="token key atrule">table</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
<span class="token key atrule">katex</span><span class="token punctuation">:</span>
<span class="token key atrule">enabled</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
</code></pre>
<p>有关选项的完整列表,请参阅 <a href="https://gitee.com/mafgwo/stackedit/blob/master/src/data/presets.js" target="_blank">这里</a>.</p>
</div>
</div>
</div>
<div class="modal__button-bar">
<button class="button" @click="config.reject()">取消</button>
<button class="button button--resolve" @click="resolve()">确认</button>
</div>
</modal-inner>
</template>
<script>
import yaml from 'js-yaml';
import { mapGetters } from 'vuex';
import ModalInner from './common/ModalInner';
import Tab from './common/Tab';
import FormEntry from './common/FormEntry';
import CodeEditor from '../CodeEditor';
import utils from '../../services/utils';
import presets from '../../data/presets';
import store from '../../store';
import badgeSvc from '../../services/badgeSvc';
const metadataProperties = {
title: '',
author: '',
tags: '',
categories: '',
excerpt: '',
featuredImage: '',
status: '',
date: '',
};
export default {
components: {
ModalInner,
Tab,
FormEntry,
CodeEditor,
},
data: () => ({
contentId: null,
yamlProperties: null,
preset: '',
error: null,
...metadataProperties,
}),
computed: {
...mapGetters('modal', [
'config',
]),
presets: () => Object.keys(presets).sort(),
tab: {
get() {
return store.getters['data/localSettings'].filePropertiesTab;
},
set(value) {
store.dispatch('data/patchLocalSettings', {
filePropertiesTab: value,
});
},
},
},
created() {
const content = store.getters['content/current'];
this.contentId = content.id;
this.setYamlProperties(content.properties);
if (this.tab !== 'yaml') {
this.setSimpleTab();
}
},
methods: {
yamlToSimple() {
const properties = this.properties || {};
const extensions = properties.extensions || {};
this.preset = extensions.preset;
if (!this.presets.includes(this.preset)) {
this.preset = 'default';
}
Object.keys(metadataProperties).forEach((name) => {
this[name] = `${properties[name] || ''}`;
});
},
simpleToYaml() {
let hasChanged = false;
const properties = this.properties || {};
const extensions = properties.extensions || {};
if (this.preset !== extensions.preset) {
if (this.preset !== 'default') {
extensions.preset = this.preset;
hasChanged = true;
} else if (extensions.preset) {
delete extensions.preset;
hasChanged = true;
}
}
Object.keys(metadataProperties).forEach((name) => {
if (this[name] !== properties[name]) {
if (this[name]) {
properties[name] = this[name];
hasChanged = true;
} else if (properties[name]) {
delete properties[name];
hasChanged = true;
}
}
});
if (hasChanged) {
if (Object.keys(extensions).length) {
properties.extensions = extensions;
} else {
delete properties.extensions;
}
this.setYamlProperties(Object.keys(properties).length
? yaml.safeDump(properties)
: '\n');
}
},
setSimpleTab() {
this.tab = 'simple';
this.yamlToSimple();
},
setYamlTab() {
this.tab = 'yaml';
this.simpleToYaml();
},
setYamlProperties(value) {
this.yamlProperties = value;
try {
this.properties = yaml.safeLoad(value);
this.error = null;
} catch (e) {
this.error = e.message;
}
},
resolve() {
if (this.tab === 'simple') {
// Compute YAML properties
this.simpleToYaml();
}
if (this.error) {
this.setYamlTab();
} else {
const properties = this.properties || {};
if (Object.keys(metadataProperties).some(key => properties[key])) {
badgeSvc.addBadge('setMetadata');
}
const extensions = properties.extensions || {};
if (extensions.preset) {
badgeSvc.addBadge('changePreset');
}
if (Object.keys(extensions).filter(key => key !== 'preset').length) {
badgeSvc.addBadge('changeExtension');
}
store.commit('content/patchItem', {
id: this.contentId,
properties: utils.sanitizeText(this.yamlProperties),
});
this.config.resolve();
}
},
},
};
</script>
<style lang="scss">
@import '../../styles/variables.scss';
.modal__inner-1.modal__inner-1--file-properties {
max-width: 520px;
}
.modal__error--file-properties {
white-space: pre-wrap;
font-family: $font-family-monospace;
font-size: $font-size-monospace;
}
</style>