clay commit : tinymce编辑器集成完毕

This commit is contained in:
clay
2022-10-10 21:58:43 +08:00
parent 6ee37c3085
commit 4bb9d1b416
49 changed files with 10817 additions and 285 deletions

View File

@@ -128,6 +128,19 @@ export const constantRoutes = [
}
]
},
{
path: '/navigation',
component: Layout,
hidden: true,
children: [
{
path: 'edit/:refId/:navId',
component: (resolve) => require(['@/views/sist/navigation/articleEdit'], resolve),
name: 'navigationEdit',
meta: { title: '编辑详情' }
}
]
},
{
path: '/article',
component: Layout,

View File

@@ -64,12 +64,7 @@
<script>
import {approve, getArticle, rejected} from "@/api/sist/article";
import Editor from '@/views/utils/Editor'
import {parseTime} from "@/utils/hcy";
export default {
components: {
Editor
},
name: "approve",
data() {
return {

View File

@@ -139,7 +139,7 @@
</el-row>
<el-row>
<el-col :offset="1" :span="22">
<Editor v-model="formData.content" :height="800"/>
<TinymceEditor v-model="formData.content"></TinymceEditor>
</el-col>
</el-row>
<el-row>
@@ -155,7 +155,8 @@
</template>
<script>
// import ArticleFile from './ArticleFile'
import Editor from '@/views/utils/Editor'
// import Editor from '@/views/utils/Editor'
import TinymceEditor from '@/views/utils/tinymce/Tinymce'
import {updateArticle, getArticle, drafts, getArticleType, getArticleApprove} from "@/api/sist/article";
import {Message} from "element-ui";
import UploadFile from '@/views/utils/uploadFile.vue';
@@ -163,9 +164,10 @@ import { getArticleNav } from '../../../../api/sist/article'
import { getToken } from '../../../../utils/auth'
import { addFile, delFile } from '../../../../api/sist/file'
export default {
components: {
Editor,
TinymceEditor,
UploadFile,
// ArticleFile
},

View File

@@ -0,0 +1,88 @@
<template>
<div class="editor">
<el-form :model="formData" size="medium" label-width="100px">
<el-row>
<el-col :span="12">
<!-- <el-form-item label="详情标题" prop="title">-->
<el-form-item label="详情标题">
<el-input v-model="formData.title" placeholder="请输入详情标题" clearable :style="{width: '100%'}">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :offset="1" :span="22">
<Editor ref="editor" v-model="formData.content" :height="500"/>
<!-- <CodeEdit ref="codeEdit" v-model="formData.content" :height="500"/>-->
<!-- <CustomEditor v-model="formData.content" :height="500"/>-->
</el-col>
</el-row>
<el-row>
<el-col :span="24" class="save">
<el-form-item size="large">
<el-button type="primary" @click="save">保存</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
import { getDetails, updateDetails } from '../../../api/sist/navigation'
import Editor from '@/views/utils/tinymce/Tinymce'
export default {
name: 'articleEdit',
components: {
Editor
},
data() {
return {
formData: {
title: '',
content: ''
}
}
},
created() {
let refId = this.$route.params && this.$route.params.refId;
let navId = this.$route.params && this.$route.params.navId;
this.handleUpdateDetails(refId)
},
methods:{
handleUpdateDetails(id) {
this.formData = {
id: id,
title: '',
content: ''
}
getDetails(id).then(res => {
if (res.data){
this.formData = res.data
}
})
},
save() {
let that = this
updateDetails(this.formData).then(res => {
that.msgSuccess('修改成功')
that.close()
})
},
close() {
this.$store.dispatch("tagsView/delView", this.$route);
this.$router.push({path: "/sist/navigation/", query: {t: Date.now()}})
},
}
}
</script>
<style scoped lang="scss">
.save {
//text-align: center;
margin-top: 20px;
}
.editor{
margin-top: 20px;
}
</style>

View File

@@ -72,14 +72,14 @@
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdateDetails(scope.row.refId)"
@click="handleUpdateDetails(scope.row.refId,scope.row.id)"
>修改中文详情
</el-button>
<el-button v-show="scope.row.type == '1'"
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdateDetails(scope.row.enRefId)"
@click="handleUpdateDetails(scope.row.enRefId,scope.row.id)"
>修改英文详情
</el-button>
<el-button v-show="scope.row.pid != 0"
@@ -250,7 +250,8 @@ import {
} from '@/api/sist/navigation'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import Editor from '@/views/utils/Editor'
// import Editor from '@/views/utils/Editor'
import Editor from '@/views/utils/tinymce/Tinymce'
import CodeEdit from '@/views/utils/CodeEdit'
import UploadFile from '@/views/utils/uploadFile'
import { getArticleNav } from '../../../api/sist/article'
@@ -473,16 +474,17 @@ export default {
this.form.type = '0'
this.title = '添加下级导航'
},
handleUpdateDetails(id) {
this.detailsShow = true
this.formData = {
id: id,
title: '',
content: ''
}
getDetails(id).then(res => {
this.formData = res.data
})
handleUpdateDetails(refId,navId) {
this.$router.push('/navigation/edit/' + refId+'/'+navId)
// this.detailsShow = true
// this.formData = {
// id: id,
// title: '',
// content: ''
// }
// getDetails(id).then(res => {
// this.formData = res.data
// })
},
code(){
let html = this.$refs.editor.getHtml()

View File

@@ -1,240 +0,0 @@
<template>
<div>
<div class="editor" :style="styles" ref="editor"></div>
<!-- <div class="code">-->
<!-- <el-button @click="openCode">源码</el-button>-->
<!-- </div>-->
<el-dialog title="编辑详情" :visible="codeShow" width="1100px" :close-on-click-modal="false" @close="codeShow = false"
append-to-body>
<textarea
class="textarea"
rows="50"
cols="50"
v-model="code"></textarea>
<el-button @click="codeSuccess">完成</el-button>
</el-dialog>
</div>
</template>
<script>
import Editor from 'wangeditor'
import { htmlFormat } from './fromat'
import { getToken } from '../../utils/auth'
import axios from 'axios'
export default {
name: 'Editor',
props: {
/* 编辑器的内容 */
value: {
type: String,
default: ''
},
/* 高度 */
height: {
type: Number,
default: null
},
/* 最小高度 */
minHeight: {
type: Number,
default: null
},
meanArray: {
// 自定义菜单
type: Array,
default: null
}
},
model: {
prop: 'value',
event: 'change'
},
computed: {
styles() {
let style = {}
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`
}
if (this.height) {
style.height = `${this.height + 50}px`
}
return style
}
},
watch: {
value: function(value) {
if (value !== this.editor.txt.html()) {
this.editor.txt.html(this.value)
}
}
// value为编辑框输入的内容这里我监听了一下值当父组件调用得时候如果给value赋值了子组件将会显示父组件赋给的值
},
data() {
return {
code: null,
codeShow: false,
// 默认有这么多菜单meanArray有值以meanArray为准
defaultMeanus: [
'head',
'bold',
'fontSize',
'fontName',
'italic',
'underline',
'strikeThrough',
'indent',
'lineHeight',
'foreColor',
'backColor',
'link',
'list',
'justify',
'quote',
'emoticon',
'image',
'video',
'table',
'code',
'splitLine',
'undo',
'redo'
],
editor: ''
}
},
methods: {
pack(s){
s = s.replace(/\/\*(.|\n)*?\*\//g, "");
s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");
s = s.replace(/\,[\s\.\#\d]*\{/g, "{");
s = s.replace(/;\s*;/g, ";");
s = s.replace(/;\s*}/g, "}");
s = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);
return (s == null) ? "" : s[1];
},
openCode() {
this.code = null
this.code = htmlFormat(this.value)
// this.code = this.value.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/ /g, "&nbsp;")
// console.log(this.code,"this.code)")
// let text = this.editor.txt.text().replace(/&lt;/ig, "<").replace(/&gt;/ig, ">").replace(/&nbsp;/ig, " ")
// console.log(text,"text")
this.codeShow = true
},
codeSuccess(){
console.log(this.code)
// let packer = new Packer;
// let output = packer.pack(this.value, 0, 0);
// console.log(output, "output")
// let output= packageFormat(this.code)
// this.setHtml(output)
// this.editor.dangerouslyInsertHtml(this.code)
this.code = null
this.codeShow = false
},
init() {
const _this = this
this.editor = new Editor(this.$refs.editor)
this.editor.config.uploadImgAccept = ['doc', 'docx', 'png', 'img', 'gif', 'bmp', 'webp']
// this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
// this.editor.config.uploadImgServer = process.env.VUE_APP_BASE_API + "/web/images"
// this.editor.config.uploadFileName = "file"
// this.editor.config.uploadImgParams= {
//
// }
this.editor.config.customUploadImg = function (resultFiles, insertImgFn) {
// resultFiles 是 input 中选中的文件列表
// insertImgFn 是获取图片 url 后,插入到编辑器的方法
let forms = new FormData()
let configs = {
headers:{
'Content-Type':'multipart/form-data',
Authorization: getToken()
}
};
forms.append('file',resultFiles[0])
axios.post(
process.env.VUE_APP_BASE_API + "/sist/article/images",
forms ,configs).then(res=>{
console.log(res)
let img = "<p></p><img src='"+res.data.data.href+"' alt='"+res.data.data.url+"'></p>"
_this.setHtml(_this.getHtml() + img)
})
// 上传图片,返回结果,将图片插入到编辑器中
}
this.editor.config.height = this.height
this.editor.config.pasteFilterStyle = false
this.editor.config.zIndex = 10
// this.editor.config.uploadImgHooks = {
// customInsert: function (insertImg, result, editor2) {
// // uploadResult(result);
// console.log(result)
// insertImg(result.data.url);
// }
// }
this.setMenus() // 设置菜单
this.editor.config.onchange = (html) => {
_this.$emit('change', html) // 将内容同步到父组件中
}
this.editor.create() // 创建编辑器
},
setMenus() {
// 设置菜单
if (this.meanArray) {
this.editor.config.menus = this.meanArray
} else {
this.editor.config.menus = this.defaultMeanus
}
},
getHtml() {
// 得到文本内容
return this.editor.txt.html()
},
setHtml(txt) {
// 设置富文本里面的值
// this.editor.txt.html(txt)
this.editor.txt.text(txt)
}
},
mounted() {
const that = this
that.$nextTick(function() {
that.init()
})
}
}
</script>
<style scoped lang="scss">
.editor {
z-index: 1 !important;
white-space: pre-wrap !important;
line-height: normal !important;
}
.code {
margin-top: 3rem;
}
.textarea{
width: 1036px;
height: 750px;
}
</style>

View File

@@ -1,11 +1,33 @@
<template>
<div class="editor" :style="styles" ref="editor"></div>
<div>
<div class="editor" :style="styles" ref="editor"></div>
<!-- <div class="code">-->
<!-- <el-button @click="openCode">源码</el-button>-->
<!-- </div>-->
<el-dialog title="编辑详情" :visible="codeShow" width="1100px" :close-on-click-modal="false" @close="codeShow = false"
append-to-body>
<textarea
class="textarea"
rows="50"
cols="50"
v-model="code"></textarea>
<el-button @click="codeSuccess">完成</el-button>
</el-dialog>
</div>
</template>
<script>
import Editor from 'wangeditor'
import { htmlFormat } from './fromat'
import { getToken } from '../../utils/auth'
import axios from 'axios'
export default {
name: "Editor",
name: 'Editor',
props: {
/* 编辑器的内容 */
value: {
@@ -15,12 +37,12 @@ export default {
/* 高度 */
height: {
type: Number,
default: null,
default: null
},
/* 最小高度 */
minHeight: {
type: Number,
default: null,
default: null
},
meanArray: {
// 自定义菜单
@@ -35,27 +57,28 @@ export default {
computed: {
styles() {
let style = {};
let style = {}
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`;
style.minHeight = `${this.minHeight}px`
}
if (this.height) {
style.height = `${this.height}px`;
style.height = `${this.height + 50}px`
}
return style;
},
return style
}
},
watch: {
value: function (value) {
value: function(value) {
if (value !== this.editor.txt.html()) {
this.editor.txt.html(this.value)
}
}
// value为编辑框输入的内容这里我监听了一下值当父组件调用得时候如果给value赋值了子组件将会显示父组件赋给的值
},
data () {
data() {
return {
code: null,
codeShow: false,
// 默认有这么多菜单meanArray有值以meanArray为准
defaultMeanus: [
'head',
@@ -86,17 +109,90 @@ export default {
}
},
methods: {
init () {
pack(s){
s = s.replace(/\/\*(.|\n)*?\*\//g, "");
s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");
s = s.replace(/\,[\s\.\#\d]*\{/g, "{");
s = s.replace(/;\s*;/g, ";");
s = s.replace(/;\s*}/g, "}");
s = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);
return (s == null) ? "" : s[1];
},
openCode() {
this.code = null
this.code = htmlFormat(this.value)
// this.code = this.value.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/ /g, "&nbsp;")
// console.log(this.code,"this.code)")
// let text = this.editor.txt.text().replace(/&lt;/ig, "<").replace(/&gt;/ig, ">").replace(/&nbsp;/ig, " ")
// console.log(text,"text")
this.codeShow = true
},
codeSuccess(){
console.log(this.code)
// let packer = new Packer;
// let output = packer.pack(this.value, 0, 0);
// console.log(output, "output")
// let output= packageFormat(this.code)
// this.setHtml(output)
// this.editor.dangerouslyInsertHtml(this.code)
this.code = null
this.codeShow = false
},
init() {
const _this = this
this.editor = new Editor(this.$refs.editor)
this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
this.editor.config.uploadImgAccept = ['doc', 'docx', 'png', 'img', 'gif', 'bmp', 'webp']
// this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
// this.editor.config.uploadImgServer = process.env.VUE_APP_BASE_API + "/web/images"
// this.editor.config.uploadFileName = "file"
// this.editor.config.uploadImgParams= {
//
// }
this.editor.config.customUploadImg = function (resultFiles, insertImgFn) {
// resultFiles 是 input 中选中的文件列表
// insertImgFn 是获取图片 url 后,插入到编辑器的方法
let forms = new FormData()
let configs = {
headers:{
'Content-Type':'multipart/form-data',
Authorization: getToken()
}
};
forms.append('file',resultFiles[0])
axios.post(
process.env.VUE_APP_BASE_API + "/sist/article/images",
forms ,configs).then(res=>{
console.log(res)
let img = "<p></p><img src='"+res.data.data.href+"' alt='"+res.data.data.url+"'></p>"
_this.setHtml(_this.getHtml() + img)
})
// 上传图片,返回结果,将图片插入到编辑器中
}
this.editor.config.height = this.height
this.editor.config.pasteFilterStyle = false
this.editor.config.zIndex = 10
// this.editor.config.uploadImgHooks = {
// customInsert: function (insertImg, result, editor2) {
// // uploadResult(result);
// console.log(result)
// insertImg(result.data.url);
// }
// }
this.setMenus() // 设置菜单
this.editor.config.onchange = (html) => {
_this.$emit('change', html) // 将内容同步到父组件中
}
this.editor.create() // 创建编辑器
},
setMenus () {
setMenus() {
// 设置菜单
if (this.meanArray) {
this.editor.config.menus = this.meanArray
@@ -104,18 +200,20 @@ export default {
this.editor.config.menus = this.defaultMeanus
}
},
getHtml () {
getHtml() {
// 得到文本内容
return this.editor.txt.html()
},
setHtml (txt) {
setHtml(txt) {
// 设置富文本里面的值
this.editor.txt.html(txt)
// this.editor.txt.html(txt)
this.editor.txt.text(txt)
}
},
mounted () {
mounted() {
const that = this
that.$nextTick(function () {
that.$nextTick(function() {
that.init()
})
}
@@ -123,9 +221,20 @@ export default {
</script>
<style scoped lang="scss">
.editor{
z-index: 1!important;
white-space: pre-wrap!important;
.editor {
z-index: 1 !important;
white-space: pre-wrap !important;
line-height: normal !important;
}
.code {
margin-top: 3rem;
}
.textarea{
width: 1036px;
height: 750px;
}
</style>

View File

@@ -0,0 +1,223 @@
<template>
<div class="tinymce-editor">
<editor v-model="myValue"
:init="init"
>
</editor>
</div>
</template>
<script>
import tinymce from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver'
// 编辑器插件plugins
// 更多插件参考https://www.tiny.cloud/docs/plugins/
import 'tinymce/plugins/link' // 链接
import 'tinymce/plugins/code' // 代码
import 'tinymce/plugins/table' // 表单
import 'tinymce/plugins/lists'
import 'tinymce/plugins/contextmenu'
import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/paste' // 张贴
import 'tinymce/plugins/autosave' // 自动保存
import 'tinymce/plugins/imagetools' // 图片
// Any plugins you want to use has to be imported
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/charmap'
import 'tinymce/plugins/codesample'
import 'tinymce/plugins/emoticons'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/hr'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/media'
import 'tinymce/plugins/noneditable'
import 'tinymce/plugins/print'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/tabfocus'
import 'tinymce/plugins/template'
import 'tinymce/plugins/textpattern'
import 'tinymce/plugins/visualblocks'
import 'tinymce/plugins/anchor'
import 'tinymce/plugins/autoresize'
import 'tinymce/plugins/bbcode'
import 'tinymce/plugins/colorpicker'
import 'tinymce/plugins/directionality'
import 'tinymce/plugins/fullpage'
import 'tinymce/plugins/help'
import 'tinymce/plugins/image'
import 'tinymce/plugins/importcss'
import 'tinymce/plugins/legacyoutput'
import 'tinymce/plugins/nonbreaking'
import 'tinymce/plugins/pagebreak'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/save'
import 'tinymce/plugins/spellchecker'
import 'tinymce/plugins/textcolor'
import 'tinymce/plugins/toc'
import 'tinymce/plugins/visualchars'
// 自定义插件
import './plugin/letterspacing/plugin' // 字间距
import './plugin/indent/plugin' // 字间距
import './plugin/lineheight/plugin'
import { getToken } from '../../../utils/auth'
import axios from 'axios' // 行高
export default {
components: {
Editor
},
props: {
value: {
type: String,
default: ''
},
inline: {
type: Boolean
},
/* 高度 */
height: {
type: Number,
default: null
},
// 基本路径,默认为空根目录,如果你的项目发布后的地址为目录形式,
// 即abc.com/tinymcebaseUrl需要配置成tinymce不然发布后资源会找不到
baseUrl: {
type: String,
default: '/admin/tinymce'
},
disabled: {
type: Boolean,
default: false
},
plugins: {
type: Array,
default() {
return [
'link table wordcount autosave imagetools paste letterspacing indent lineheight',
'advlist autolink link image lists charmap print hr anchor pagebreak',
'searchreplace visualblocks visualchars code fullscreen media nonbreaking',
'table directionality emoticons textcolor paste textcolor colorpicker textpattern'
]
}
},
toolbar: {
type: String,
default: `undo redo | fontsizeselect bold italic underline strikethrough | forecolor backcolor | alignleft aligncenter alignright alignjustify |
| uploadimg image | table lineheight pastetext removeformat | customBtn letterspacing indent lineheight`
}
},
data() {
return {
init: {
language_url: `/admin/tinymce/langs/zh_CN.js`,
language: 'zh_CN',
skin_url: `/admin/tinymce/skins/ui/oxide`,
content_css: `/admin/tinymce/skins/content/default/content.css`,
base_url: this.baseUrl,
height: 800,
plugins: this.plugins,
toolbar: this.toolbar,
branding: false,
selector: 'textarea',
// menubar: false,
fontsize_formats: '11px 12px 14px 16px 18px 24px 36px 48px 50px 56px 60px 64px',
// 自定义字间距
letterspacing_val: '1px 2px 3px 4px 5px',
paste_data_images: true,
// setup: (editor) => {
// // 自定义新的工具栏按钮
// editor.ui.registry.addButton('customBtn', {
// tooltip: '新的工具栏按钮',
// text: '新的工具栏按钮',
// onAction: () => {
// window.alert('新的工具栏按钮')
// }
// })
// },
// 此处为图片上传处理函数这个直接用了base64的图片形式上传图片
// 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
// eslint-disable-next-line no-unused-vars
// images_upload_handler: (blobInfo, success, failure) => {
//
//
// const img = 'data:image/jpeg;base64,' + blobInfo.base64()
// success(img)
// },
images_upload_handler: (blobInfo, success, failure) => {
// const img = 'data:image/jpeg;base64,' + blobInfo.base64()
// success(img)
let formData = new FormData()
formData.append('file', blobInfo.blob())
console.log(formData, blobInfo.blob())
let configs = {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: getToken()
}
}
axios.post(
process.env.VUE_APP_BASE_API + '/sist/article/images',
formData, configs).then(res => {
console.log(res)
success(res.data.data.href)
})
}
},
myValue: this.value,
isShowFileDlg: false
}
},
mounted() {
tinymce.init({
images_upload_handler: (blobInfo, success, failure) => {
this.upload_handler(blobInfo, success, failure)
}
})
},
// created() {
// tinymce.init({})
// },
methods: {
upload_handler(blobInfo, success, failure) {
console.log('我被触发了')
console.log(blobInfo, 'blobInfo')
console.log(success, 'success')
console.log(failure, 'failure')
console.log(progress, 'progress')
const img = 'data:image/jpeg;base64,' + blobInfo.base64()
success(img)
let forms = new FormData()
let configs = {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: getToken()
}
}
forms.append('file', blobInfo.blob())
axios.post(
process.env.VUE_APP_BASE_API + '/sist/article/images',
forms, configs).then(res => {
console.log(res)
})
console.log(forms, 'forms')
}
},
watch: {
value(newValue) {
this.myValue = newValue
},
myValue(newValue) {
this.$emit('input', newValue)
}
}
}
</script>

View File

@@ -0,0 +1,47 @@
tinymce.PluginManager.add('indent2em', function(editor, url) {
var pluginName='首行缩进';
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
var indent2em_val = editor.getParam('indent2em_val', '2em');
var doAct = function () {
var dom = editor.dom;
var blocks = editor.selection.getSelectedBlocks();
var act = '';
global$1.each(blocks, function (block) {
if(act==''){
act = dom.getStyle(block,'text-indent')==indent2em_val ? 'remove' : 'add';
}
if( act=='add' ){
dom.setStyle(block, 'text-indent', indent2em_val);
}else{
var style=dom.getAttrib(block,'style');
style = style.replace(/text-indent:[\s]*2em;/ig,'');
dom.setAttrib(block,'style',style);
}
});
};
editor.ui.registry.addButton('indent2em', {
text: '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M170.666667 563.2v-102.4H887.466667v102.4zM170.666667 836.266667v-102.4H887.466667v102.4zM512 290.133333v-102.4H887.466667v102.4zM238.933333 341.333333V136.533333l204.8 102.4z" fill="#2c2c2c" p-id="5210"></path></svg>',
tooltip: pluginName,
onAction: function () {
doAct();
}
});
editor.ui.registry.addMenuItem('indent2em', {
text: pluginName,
onAction: function() {
doAct();
}
});
return {
getMetadata: function () {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/indent2em.php",
};
}
};
});

View File

@@ -0,0 +1,47 @@
tinymce.PluginManager.add('indent2em', function(editor, url) {
var pluginName='首行缩进';
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
var indent2em_val = editor.getParam('indent2em_val', '2em');
var doAct = function () {
var dom = editor.dom;
var blocks = editor.selection.getSelectedBlocks();
var act = '';
global$1.each(blocks, function (block) {
if(act==''){
act = dom.getStyle(block,'text-indent')==indent2em_val ? 'remove' : 'add';
}
if( act=='add' ){
dom.setStyle(block, 'text-indent', indent2em_val);
}else{
var style=dom.getAttrib(block,'style');
style = style.replace(/text-indent:[\s]*2em;/ig,'');
dom.setAttrib(block,'style',style);
}
});
};
editor.ui.registry.addButton('indent2em', {
text: '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M170.666667 563.2v-102.4H887.466667v102.4zM170.666667 836.266667v-102.4H887.466667v102.4zM512 290.133333v-102.4H887.466667v102.4zM238.933333 341.333333V136.533333l204.8 102.4z" fill="#2c2c2c" p-id="5210"></path></svg>',
tooltip: pluginName,
onAction: function () {
doAct();
}
});
editor.ui.registry.addMenuItem('indent2em', {
text: pluginName,
onAction: function() {
doAct();
}
});
return {
getMetadata: function () {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/indent2em.php",
};
}
};
});

View File

@@ -0,0 +1,54 @@
tinymce.PluginManager.add('letterspacing', function (editor, url) {
var pluginName = '字间距'
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools')
var letterspacing_val = editor.getParam('letterspacing_val', '1px 2px 3px 4px 5px')
editor.on('init', function () {
editor.formatter.register({
letterspacing: {inline: 'span', styles: {'letter-spacing': '%value'}}
})
})
var doAct = function (value) {
editor.formatter.apply('letterspacing', {value: value})
editor.fire('change', {})
}
editor.ui.registry.addMenuButton('letterspacing', {
text: '<svg t="1570979572631" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12244" width="20" height="20" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M33.450667 3.413333h102.4v956.8256H33.450667V3.413333z m887.330133 1.8432h102.4v957.713067h-102.4V5.188267z m-425.301333 200.704h108.9536l223.6416 584.977067h-102.4l-53.248-146.6368H427.485867l-53.248 146.6368h-102.4l223.6416-584.9088z m-39.3216 359.697067H643.754667L552.004267 309.248h-3.2768L456.157867 565.6576z" fill="#2c2c2c" p-id="12245"></path></svg>',
tooltip: pluginName,
fetch: function (callback) {
var dom = editor.dom
var blocks = editor.selection.getSelectedBlocks()
var lhv = 0
global$1.each(blocks, function (block) {
if (lhv == 0) {
lhv = dom.getStyle(block, 'letterspacing') ? dom.getStyle(block, 'letterspacing') : 0
}
})
var items = letterspacing_val.split(' ').map(function (item) {
var text = item
var value = item
return {
type: 'togglemenuitem',
text: text,
active: lhv == value ? true : false,
onAction: function () {
doAct(value)
}
}
})
callback(items)
}
})
return {
getMetadata: function () {
return {
name: pluginName,
url: 'http://tinymce.ax-z.cn/more-plugins/lineheight.php',
}
}
}
})

View File

@@ -0,0 +1,57 @@
tinymce.PluginManager.add('lineheight', function(editor, url) {
var pluginName='设置行高';
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
var lineheight_val = editor.getParam('lineheight_val', '1 1.5 1.6 1.75 1.8 2 3 4 5');
editor.on('init', function() {
editor.formatter.register({
lineheight: {
selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table',
styles: { 'line-height': '%value' }
}
});
});
var doAct = function (value) {
editor.formatter.apply('lineheight', { value: value });
editor.fire('change', {});
};
editor.ui.registry.addMenuButton('lineheight', {
text: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9.984 12.984v-1.969h12v1.969h-12zM9.984 18.984v-1.969h12v1.969h-12zM9.984 5.016h12v1.969h-12v-1.969zM6 6.984v10.031h2.484l-3.469 3.469-3.516-3.469h2.484v-10.031h-2.484l3.516-3.469 3.469 3.469h-2.484z"></path></svg>',
tooltip: pluginName,
fetch: function(callback) {
var dom = editor.dom;
var blocks = editor.selection.getSelectedBlocks();
var lhv = 0;
global$1.each(blocks, function(block) {
if(lhv==0){
lhv = dom.getStyle(block,'line-height') ? dom.getStyle(block,'line-height') : 0;
}
});
var items = lineheight_val.split(' ').map(function(item){
var text = item;
var value = item;
return {
type: 'togglemenuitem',
text: text,
active : lhv==value ? true :false,
onAction: function() {
doAct(value);
}
};
});
callback(items);
}
});
return {
getMetadata: function () {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/lineheight.php",
};
}
};
});

View File

@@ -0,0 +1,57 @@
tinymce.PluginManager.add('lineheight', function(editor, url) {
var pluginName='设置行高';
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
var lineheight_val = editor.getParam('lineheight_val', '1 1.5 1.6 1.75 1.8 2 3 4 5');
editor.on('init', function() {
editor.formatter.register({
lineheight: {
selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table',
styles: { 'line-height': '%value' }
}
});
});
var doAct = function (value) {
editor.formatter.apply('lineheight', { value: value });
editor.fire('change', {});
};
editor.ui.registry.addMenuButton('lineheight', {
text: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9.984 12.984v-1.969h12v1.969h-12zM9.984 18.984v-1.969h12v1.969h-12zM9.984 5.016h12v1.969h-12v-1.969zM6 6.984v10.031h2.484l-3.469 3.469-3.516-3.469h2.484v-10.031h-2.484l3.516-3.469 3.469 3.469h-2.484z"></path></svg>',
tooltip: pluginName,
fetch: function(callback) {
var dom = editor.dom;
var blocks = editor.selection.getSelectedBlocks();
var lhv = 0;
global$1.each(blocks, function(block) {
if(lhv==0){
lhv = dom.getStyle(block,'line-height') ? dom.getStyle(block,'line-height') : 0;
}
});
var items = lineheight_val.split(' ').map(function(item){
var text = item;
var value = item;
return {
type: 'togglemenuitem',
text: text,
active : lhv==value ? true :false,
onAction: function() {
doAct(value);
}
};
});
callback(items);
}
});
return {
getMetadata: function () {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/lineheight.php",
};
}
};
});