├── .gitignore
├── src
├── index.js
├── uid.js
└── richtext.js
├── .babelrc
├── examples
├── app.js
├── index.html
└── components
│ └── page1.js
├── lib
├── uid.js
├── index.js
└── richtext.js
├── package.json
├── webpack.dev.config.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | npm-debug.log
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import RichText from './richtext';
2 |
3 | export default RichText;
--------------------------------------------------------------------------------
/src/uid.js:
--------------------------------------------------------------------------------
1 | const now = +(new Date());
2 | let index = 0;
3 |
4 | export default function uid() {
5 | return `bee-${now}-${++index}`;
6 | }
7 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "env",
4 | "es2015",
5 | "react",
6 | "stage-2"
7 | ],
8 | "plugins": ["transform-runtime"]
9 | }
--------------------------------------------------------------------------------
/examples/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import Page1 from './components/page1.js'
4 |
5 |
6 | ReactDOM.render(
7 | ,
8 | document.getElementById('container')
9 | );
10 |
--------------------------------------------------------------------------------
/lib/uid.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = uid;
7 | var now = +new Date();
8 | var index = 0;
9 |
10 | function uid() {
11 | return "bee-" + now + "-" + ++index;
12 | }
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _richtext = require('./richtext');
8 |
9 | var _richtext2 = _interopRequireDefault(_richtext);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | exports.default = _richtext2.default;
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | richtextDemo
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-ueditor-wrap",
3 | "version": "1.0.8",
4 | "description": "react ueditor",
5 | "main": "lib/index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/uso51984/react-ueditor"
9 | },
10 | "license": "MIT",
11 | "keywords": [
12 | "ueditor",
13 | "react-ueditor",
14 | "rc-ueditor",
15 | "richtext"
16 | ],
17 | "config": {
18 | "name": "react-ueditor",
19 | "entry": {
20 | "react-ueditor": [
21 | "./src/index.js"
22 | ]
23 | },
24 | "server": {
25 | "port": 9200
26 | }
27 | },
28 | "dependencies": {},
29 | "devDependencies": {
30 | "bee-build-tools": "0.0.26",
31 | "react": "^16.8.6",
32 | "react-dom": "^16.8.6"
33 | },
34 | "scripts": {
35 | "dist": "bee-tools run dist",
36 | "dev": "webpack-dev-server --config ./webpack.dev.js",
37 | "compile": "bee-tools run compile --babel-runtime",
38 | "buildExample": "bee-tools run buildExample",
39 | "gh-pages": "bee-tools run gh-pages",
40 | "release": "bee-tools run release"
41 | },
42 | "author": "edmund_chen"
43 | }
44 |
--------------------------------------------------------------------------------
/examples/components/page1.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Ueditor from '../../src'
3 |
4 | const value = '受控设置value值
';
5 | export default class Page1 extends React.Component {
6 | state ={
7 | initValue: '',
8 | nowValue: ''
9 | }
10 |
11 | componentDidMount() {
12 | console.log('e23', this.ref)
13 | }
14 |
15 | onChange = (value) => {
16 | this.ueditorValue = value;
17 | this.setState({ nowValue: value });
18 | }
19 |
20 | onBlur = (value) => {
21 | this.ueditorValue = value;
22 | console.log('----')
23 | this.setState({ nowValue: value });
24 | }
25 |
26 | getEditorInstance(instance) {
27 | console.log('instance', instance);
28 | }
29 |
30 | render(){
31 | return(
32 |
33 |
41 |
42 |
43 |
{this.state.nowValue}
44 |
45 | )
46 | }
47 | };
48 |
--------------------------------------------------------------------------------
/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var path = require('path');
3 | var HtmlWebpackPlugin = require('html-webpack-plugin');
4 |
5 | var BUILD_PATH = path.resolve(__dirname, './dist');
6 | var TMP_PATH = path.resolve(__dirname,'./examples/index.html');
7 |
8 | module.exports = {
9 | entry: {
10 | 'app': [
11 | './examples/app.js',
12 | ],
13 | vendor: ['react', 'react-dom']
14 | },
15 | output: {
16 | path: BUILD_PATH,
17 | filename: '[name].js' //输出js
18 | },
19 | plugins: [
20 | new webpack.optimize.CommonsChunkPlugin({name:'vendor', filename: 'vendor.js'}),
21 | new HtmlWebpackPlugin({
22 | title: 'reactdemo',
23 | template: TMP_PATH,
24 | filename: 'index.html',
25 | chunks: ['app','vendor'],
26 | inject: 'body'
27 | }),
28 | new webpack.DefinePlugin({
29 | "process.env": {
30 | NODE_ENV: JSON.stringify("development") // development,production
31 | }
32 | })
33 | ],
34 |
35 | module: {
36 | loaders: [{
37 | test: /\.js$/,
38 | loaders: [ 'babel-loader?presets[]=es2015,presets[]=react,presets[]=stage-0'],
39 | exclude: /node_modules/
40 | },{
41 | test: /\.less$/,
42 | loaders: ['style', 'css?sourceMap', 'less?&sourceMap&includePaths[]=./user-center/style/index.less']
43 | },
44 | { test: /\.css$/, loader: "style-loader!css-loader" }
45 | ,
46 | {
47 | test: /\.(png|jpg|gif)$/,
48 | loader: 'file-loader?name=images/[name].[ext]',
49 | },
50 | {
51 | test: /\.(eot|ttf|svg|woff|woff2)$/,
52 | loader: 'file-loader?name=fonts/[name].[ext]',
53 | },
54 | ]
55 | }
56 | };
--------------------------------------------------------------------------------
/src/richtext.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Uid from './uid';
3 |
4 | const UEDITOR_LOADED_KEY = '__BEE_UEDITOR_LOADED_STATUS__';
5 |
6 | // ueditor 默认值
7 | const initConfig = {
8 | autoClearinitialContent: false,
9 | autoFloatEnabled: true, // 是否保持 toolbar 滚动时不动
10 | focus: false,
11 | wordCount: true,
12 | elementPathEnabled: false,
13 | pasteplain: false, // 是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴
14 | initialFrameWidth: 640, // 初始化编辑器宽度
15 | initialFrameHeight: 200,
16 | maximumWords: 10000,
17 | };
18 |
19 | export default class RichText extends React.Component {
20 | static defaultProps = {
21 | value: '',
22 | onChange: () => { },
23 | ueditorUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.all.js',
24 | ueditorConfigUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.config.js',
25 | ueditorHomeUrl: '',
26 | ueditorIframeUrl: '',
27 | editorConfig: {}, // ueditor 默认值
28 | className: '',
29 | prefix: 'bee',
30 | getEditorInstance(){}
31 | }
32 |
33 | constructor(props) {
34 | super(props);
35 |
36 | this.uuid = `bee-${Uid()}`
37 | }
38 |
39 | componentDidMount() {
40 | let timer = null;
41 |
42 | if (window.UE) {
43 | this.initRichText();
44 | } else {
45 | timer = setInterval(() => {
46 | const status = window[UEDITOR_LOADED_KEY];
47 | if (status === 2) {
48 | clearInterval(timer);
49 | this.initRichText();
50 | } else if (status !== 1){
51 | this.loadUEditorScript()
52 | }
53 | }, 50)
54 | }
55 | }
56 |
57 | componentWillUnmount() {
58 | if (!this.editor) return;
59 | this.editor.destroy();
60 | }
61 |
62 | componentWillReceiveProps({ value }) {
63 | if (value !== this.props.value && this.editor) {
64 | this.editor.setContent(value);
65 | }
66 | }
67 |
68 | loadUEditorScript() {
69 | if (window[UEDITOR_LOADED_KEY] !== undefined) {
70 | return;
71 | }
72 | window[UEDITOR_LOADED_KEY] = 1; // 加载中
73 | let {
74 | ueditorHomeUrl,
75 | ueditorIframeUrl,
76 | ueditorUrl,
77 | ueditorConfigUrl,
78 | } = this.props;
79 |
80 | window.UEDITOR_HOME_URL = ueditorHomeUrl;
81 | window.UEDITOR_IFRAME_URL = ueditorIframeUrl;
82 |
83 | this.createScriptDom(ueditorConfigUrl, () => {
84 | this.createScriptDom(ueditorUrl, () => {
85 | window[UEDITOR_LOADED_KEY] = 2; // 加载完成
86 | });
87 | });
88 | }
89 |
90 | createScriptDom(url, callback) {
91 | const scriptDom = document.createElement('script');
92 | scriptDom.type = 'text/javascript';
93 | scriptDom.async = true;
94 | scriptDom.src = url;
95 |
96 | scriptDom.onload = function () {
97 | callback();
98 | }
99 | document.body.appendChild(scriptDom);
100 | }
101 |
102 | initRichText = () => {
103 | const UE = window.UE;
104 | const target = document.getElementById(this.uuid);
105 |
106 | if (!UE || !target) {
107 | return false;
108 | }
109 |
110 | let { value, editorConfig } = this.props;
111 | let conf = { ...initConfig, ...editorConfig };
112 | let editor = new UE.ui.Editor(conf);
113 | this.editor = editor;
114 |
115 | editor.addListener('contentChange', () => {
116 | this.onChange();
117 | });
118 |
119 | editor.addListener('blur', () => {
120 | this.onBlur();
121 | });
122 |
123 | editor.render(target);
124 | editor.ready(() => {
125 | editor.setContent(value);
126 | })
127 | this.props.getEditorInstance(this.editor);
128 | }
129 |
130 | onChange = () => {
131 | const value = this.editor.getContent();
132 | this.props.onChange && this.props.onChange(value);
133 | }
134 |
135 | onBlur = () => {
136 | const value = this.editor.getContent();
137 | this.props.onBlur && this.props.onBlur(value);
138 | }
139 |
140 | render() {
141 | const { prefix, className } = this.props;
142 | return (
143 |
146 | )
147 | }
148 | }
--------------------------------------------------------------------------------
/lib/richtext.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require('babel-runtime/helpers/extends');
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
12 |
13 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
14 |
15 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
16 |
17 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
18 |
19 | var _createClass2 = require('babel-runtime/helpers/createClass');
20 |
21 | var _createClass3 = _interopRequireDefault(_createClass2);
22 |
23 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
24 |
25 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
26 |
27 | var _inherits2 = require('babel-runtime/helpers/inherits');
28 |
29 | var _inherits3 = _interopRequireDefault(_inherits2);
30 |
31 | var _react = require('react');
32 |
33 | var _react2 = _interopRequireDefault(_react);
34 |
35 | var _uid = require('./uid');
36 |
37 | var _uid2 = _interopRequireDefault(_uid);
38 |
39 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
40 |
41 | var UEDITOR_LOADED_KEY = '__BEE_UEDITOR_LOADED_STATUS__';
42 |
43 | // ueditor 默认值
44 | var initConfig = {
45 | autoClearinitialContent: false,
46 | autoFloatEnabled: true, // 是否保持 toolbar 滚动时不动
47 | focus: false,
48 | wordCount: true,
49 | elementPathEnabled: false,
50 | pasteplain: false, // 是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴
51 | initialFrameWidth: 640, // 初始化编辑器宽度
52 | initialFrameHeight: 200,
53 | maximumWords: 10000
54 | };
55 |
56 | var RichText = function (_React$Component) {
57 | (0, _inherits3.default)(RichText, _React$Component);
58 |
59 | function RichText(props) {
60 | (0, _classCallCheck3.default)(this, RichText);
61 |
62 | var _this = (0, _possibleConstructorReturn3.default)(this, (RichText.__proto__ || (0, _getPrototypeOf2.default)(RichText)).call(this, props));
63 |
64 | _this.initRichText = function () {
65 | var UE = window.UE;
66 | var target = document.getElementById(_this.uuid);
67 |
68 | if (!UE || !target) {
69 | return false;
70 | }
71 |
72 | var _this$props = _this.props,
73 | value = _this$props.value,
74 | editorConfig = _this$props.editorConfig;
75 |
76 | var conf = (0, _extends3.default)({}, initConfig, editorConfig);
77 | var editor = new UE.ui.Editor(conf);
78 | _this.editor = editor;
79 |
80 | editor.addListener('blur contentChange', function () {
81 | _this.onChange();
82 | });
83 | editor.render(target);
84 | editor.ready(function () {
85 | editor.setContent(value);
86 | });
87 | };
88 |
89 | _this.onChange = function () {
90 | var value = _this.editor.getContent();
91 | _this.props.onChange && _this.props.onChange(value);
92 | };
93 |
94 | _this.uuid = 'bee-' + (0, _uid2.default)();
95 | return _this;
96 | }
97 |
98 | (0, _createClass3.default)(RichText, [{
99 | key: 'componentDidMount',
100 | value: function componentDidMount() {
101 | var _this2 = this;
102 |
103 | var timer = null;
104 |
105 | if (window.UE) {
106 | this.initRichText();
107 | } else {
108 | timer = setInterval(function () {
109 | var status = window[UEDITOR_LOADED_KEY];
110 | if (status === 2) {
111 | clearInterval(timer);
112 | _this2.initRichText();
113 | } else if (status !== 1) {
114 | _this2.loadUEditorScript();
115 | }
116 | }, 50);
117 | }
118 | }
119 | }, {
120 | key: 'componentWillUnmount',
121 | value: function componentWillUnmount() {
122 | if (!this.editor) return;
123 | this.editor.destroy();
124 | }
125 | }, {
126 | key: 'componentWillReceiveProps',
127 | value: function componentWillReceiveProps(_ref) {
128 | var value = _ref.value;
129 |
130 | if (value !== this.props.value && this.editor) {
131 | this.editor.setContent(value);
132 | }
133 | }
134 | }, {
135 | key: 'loadUEditorScript',
136 | value: function loadUEditorScript() {
137 | var _this3 = this;
138 |
139 | if (window[UEDITOR_LOADED_KEY] !== undefined) {
140 | return;
141 | }
142 | window[UEDITOR_LOADED_KEY] = 1; // 加载中
143 | var _props = this.props,
144 | ueditorHomeUrl = _props.ueditorHomeUrl,
145 | ueditorIframeUrl = _props.ueditorIframeUrl,
146 | ueditorUrl = _props.ueditorUrl,
147 | ueditorConfigUrl = _props.ueditorConfigUrl;
148 |
149 |
150 | window.UEDITOR_HOME_URL = ueditorHomeUrl;
151 | window.UEDITOR_IFRAME_URL = ueditorIframeUrl;
152 |
153 | this.createScriptDom(ueditorConfigUrl, function () {
154 | _this3.createScriptDom(ueditorUrl, function () {
155 | window[UEDITOR_LOADED_KEY] = 2; // 加载完成
156 | });
157 | });
158 | }
159 | }, {
160 | key: 'createScriptDom',
161 | value: function createScriptDom(url, callback) {
162 | var scriptDom = document.createElement('script');
163 | scriptDom.type = 'text/javascript';
164 | scriptDom.async = true;
165 | scriptDom.src = url;
166 |
167 | scriptDom.onload = function () {
168 | callback();
169 | };
170 | document.body.appendChild(scriptDom);
171 | }
172 | }, {
173 | key: 'render',
174 | value: function render() {
175 | var _props2 = this.props,
176 | prefix = _props2.prefix,
177 | className = _props2.className;
178 |
179 | return _react2.default.createElement(
180 | 'div',
181 | { className: prefix + '-richtext ' + className },
182 | _react2.default.createElement('div', { id: this.uuid })
183 | );
184 | }
185 | }]);
186 | return RichText;
187 | }(_react2.default.Component);
188 |
189 | RichText.defaultProps = {
190 | value: '',
191 | onChange: function onChange() {},
192 | ueditorUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.all.js',
193 | ueditorConfigUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.config.js',
194 | ueditorHomeUrl: '',
195 | ueditorIframeUrl: '',
196 | editorConfig: {}, // ueditor 默认值
197 | className: '',
198 | prefix: 'bee'
199 | };
200 | exports.default = RichText;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### 安装
2 | ```
3 | npm i --save react-ueditor-wrap
4 | ```
5 | [demo](http://uso.oschina.io/react-ueditor-demo/)
6 | ### 使用
7 | ```
8 | import RcUeditor from 'react-ueditor-wrap';
9 |
10 | class Demo extends React.Component {
11 |
12 | hanldeChage = (value) => {
13 | console.log('RcUeditor', value);
14 | }
15 |
16 | render() {
17 |
18 | return (
19 |
20 |
21 |
22 | );
23 | }
24 | }
25 |
26 | export default Demo;
27 | ```
28 | ### api
29 |
30 | | 成员 | 说明 | 类型 | 默认值 |
31 | | --- | --- | --- | --- |
32 | | value | 设置编辑器的值 | string | - |
33 | | ueditorUrl | 设置ueditor(百度编辑器)js文件的地址 | string | 'https://uso.oschina.io/react-ueditor-demo/ueditor.all.js' |
34 | | ueditorConfigUrl | 设置百度编辑器默认config文件地址 | string | 'https://uso.oschina.io/react-ueditor-demo/ueditor.config.js' |
35 | | ueditorHomeUrl | 设置ueditorHomeUrl | string | '' |
36 | | ueditorIframeUrl | 设置ueditorIframeUrl | string | '' |
37 | | editorConfig | 百度编辑器的配置(如果不传则为默认配置) | Object | {} |
38 | | className | 添加自定义class | String | '' |
39 | | prefix | 修改默认class前缀 | String | 'bee' |
40 |
41 | > 注意: 实际生产环境使用请修改ueditorUrl以及ueditorConfigUrl到自己的服务器地址或者CDN。以及在对应的目录放入ueditor的依赖文件,这点可以参考ueditor官方给出的example. 自行下载观看https://ueditor.baidu.com/website/download.html
42 |
43 | ### editorConfig 例子
44 | ```
45 | // ueditor 默认值
46 | const editorConfig = {
47 | toolbars: [
48 | [
49 | 'bold',
50 | 'italic',
51 | 'underline',
52 | 'strikethrough',
53 | 'forecolor',
54 | 'backcolor',
55 | 'justifyleft',
56 | 'justifycenter',
57 | 'justifyright',
58 | '|',
59 | 'insertunorderedlist',
60 | 'insertorderedlist',
61 | 'blockquote',
62 | ],
63 | ],
64 | autoClearinitialContent: false,
65 | autoFloatEnabled: true,
66 | focus: false,
67 | initialFrameWidth: 740, // 初始化编辑器宽度
68 | initialFrameHeight: 300,
69 | maximumWords: 100000,
70 | };
71 | ```
72 |
73 |
74 | ## ueditor完整配置项
75 | > 以下是ueditor 代码默认的配置代码。 editorConfig配置实则是调用了`new UE.ui.Editor(conf);`
76 | 具体ueditor的使用请移步到https://ueditor.baidu.com/website/index.html
77 |
78 | ```
79 | /**
80 | * ueditor完整配置项
81 | * 可以在这里配置整个编辑器的特性
82 | */
83 | /**************************提示********************************
84 | * 所有被注释的配置项均为UEditor默认值。
85 | * 修改默认配置请首先确保已经完全明确该参数的真实用途。
86 | * 主要有两种修改方案,一种是取消此处注释,然后修改成对应参数;另一种是在实例化编辑器时传入对应参数。
87 | * 当升级编辑器时,可直接使用旧版配置文件替换新版配置文件,不用担心旧版配置文件中因缺少新功能所需的参数而导致脚本报错。
88 | **************************提示********************************/
89 |
90 | (function () {
91 |
92 | /**
93 | * 编辑器资源文件根路径。它所表示的含义是:以编辑器实例化页面为当前路径,指向编辑器资源文件(即dialog等文件夹)的路径。
94 | * 鉴于很多同学在使用编辑器的时候出现的种种路径问题,此处强烈建议大家使用"相对于网站根目录的相对路径"进行配置。
95 | * "相对于网站根目录的相对路径"也就是以斜杠开头的形如"/myProject/ueditor/"这样的路径。
96 | * 如果站点中有多个不在同一层级的页面需要实例化编辑器,且引用了同一UEditor的时候,此处的URL可能不适用于每个页面的编辑器。
97 | * 因此,UEditor提供了针对不同页面的编辑器可单独配置的根路径,具体来说,在需要实例化编辑器的页面最顶部写上如下代码即可。当然,需要令此处的URL等于对应的配置。
98 | * window.UEDITOR_HOME_URL = "/xxxx/xxxx/";
99 | */
100 | var URL = window.UEDITOR_HOME_URL || getUEBasePath();
101 |
102 | /**
103 | * 配置项主体。注意,此处所有涉及到路径的配置别遗漏URL变量。
104 | */
105 | window.UEDITOR_CONFIG = {
106 |
107 | //为编辑器实例添加一个路径,这个不能被注释
108 | UEDITOR_HOME_URL: URL
109 |
110 | // 服务器统一请求接口路径
111 | , serverUrl: URL + "php/controller.php"
112 |
113 | //工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义
114 | , toolbars: [[
115 | 'fullscreen', 'source', '|', 'undo', 'redo', '|',
116 | 'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|',
117 | 'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
118 | 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
119 | 'directionalityltr', 'directionalityrtl', 'indent', '|',
120 | 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',
121 | 'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',
122 | 'simpleupload', 'insertimage', 'emotion', 'scrawl', 'insertvideo', 'music', 'attachment', 'map', 'gmap', 'insertframe', 'insertcode', 'webapp', 'pagebreak', 'template', 'background', '|',
123 | 'horizontal', 'date', 'time', 'spechars', 'snapscreen', 'wordimage', '|',
124 | 'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|',
125 | 'print', 'preview', 'searchreplace', 'drafts', 'help'
126 | ]]
127 | //当鼠标放在工具栏上时显示的tooltip提示,留空支持自动多语言配置,否则以配置值为准
128 | //,labelMap:{
129 | // 'anchor':'', 'undo':''
130 | //}
131 |
132 | //语言配置项,默认是zh-cn。有需要的话也可以使用如下这样的方式来自动多语言切换,当然,前提条件是lang文件夹下存在对应的语言文件:
133 | //lang值也可以通过自动获取 (navigator.language||navigator.browserLanguage ||navigator.userLanguage).toLowerCase()
134 | //,lang:"zh-cn"
135 | //,langPath:URL +"lang/"
136 |
137 | //主题配置项,默认是default。有需要的话也可以使用如下这样的方式来自动多主题切换,当然,前提条件是themes文件夹下存在对应的主题文件:
138 | //现有如下皮肤:default
139 | //,theme:'default'
140 | //,themePath:URL +"themes/"
141 |
142 | //,zIndex : 900 //编辑器层级的基数,默认是900
143 |
144 | //针对getAllHtml方法,会在对应的head标签中增加该编码设置。
145 | //,charset:"utf-8"
146 |
147 | //若实例化编辑器的页面手动修改的domain,此处需要设置为true
148 | //,customDomain:false
149 |
150 | //常用配置项目
151 | //,isShow : true //默认显示编辑器
152 |
153 | //,textarea:'editorValue' // 提交表单时,服务器获取编辑器提交内容的所用的参数,多实例时可以给容器name属性,会将name给定的值最为每个实例的键值,不用每次实例化的时候都设置这个值
154 |
155 | //,initialContent:'欢迎使用ueditor!' //初始化编辑器的内容,也可以通过textarea/script给值,看官网例子
156 |
157 | //,autoClearinitialContent:true //是否自动清除编辑器初始内容,注意:如果focus属性设置为true,这个也为真,那么编辑器一上来就会触发导致初始化的内容看不到了
158 |
159 | //,focus:false //初始化时,是否让编辑器获得焦点true或false
160 |
161 | //如果自定义,最好给p标签如下的行高,要不输入中文时,会有跳动感
162 | //,initialStyle:'p{line-height:1em}'//编辑器层级的基数,可以用来改变字体等
163 |
164 | //,iframeCssUrl: URL + '/themes/iframe.css' //给编辑区域的iframe引入一个css文件
165 |
166 | //indentValue
167 | //首行缩进距离,默认是2em
168 | //,indentValue:'2em'
169 |
170 | //,initialFrameWidth:1000 //初始化编辑器宽度,默认1000
171 | //,initialFrameHeight:320 //初始化编辑器高度,默认320
172 |
173 | //,readonly : false //编辑器初始化结束后,编辑区域是否是只读的,默认是false
174 |
175 | //,autoClearEmptyNode : true //getContent时,是否删除空的inlineElement节点(包括嵌套的情况)
176 |
177 | //启用自动保存
178 | //,enableAutoSave: true
179 | //自动保存间隔时间, 单位ms
180 | //,saveInterval: 500
181 |
182 | //,fullscreen : false //是否开启初始化时即全屏,默认关闭
183 |
184 | //,imagePopup:true //图片操作的浮层开关,默认打开
185 |
186 | //,autoSyncData:true //自动同步编辑器要提交的数据
187 | //,emotionLocalization:false //是否开启表情本地化,默认关闭。若要开启请确保emotion文件夹下包含官网提供的images表情文件夹
188 |
189 | //粘贴只保留标签,去除标签所有属性
190 | //,retainOnlyLabelPasted: false
191 |
192 | //,pasteplain:false //是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴
193 | //纯文本粘贴模式下的过滤规则
194 | //'filterTxtRules' : function(){
195 | // function transP(node){
196 | // node.tagName = 'p';
197 | // node.setStyle();
198 | // }
199 | // return {
200 | // //直接删除及其字节点内容
201 | // '-' : 'script style object iframe embed input select',
202 | // 'p': {$:{}},
203 | // 'br':{$:{}},
204 | // 'div':{'$':{}},
205 | // 'li':{'$':{}},
206 | // 'caption':transP,
207 | // 'th':transP,
208 | // 'tr':transP,
209 | // 'h1':transP,'h2':transP,'h3':transP,'h4':transP,'h5':transP,'h6':transP,
210 | // 'td':function(node){
211 | // //没有内容的td直接删掉
212 | // var txt = !!node.innerText();
213 | // if(txt){
214 | // node.parentNode.insertAfter(UE.uNode.createText(' '),node);
215 | // }
216 | // node.parentNode.removeChild(node,node.innerText())
217 | // }
218 | // }
219 | //}()
220 |
221 | //,allHtmlEnabled:false //提交到后台的数据是否包含整个html字符串
222 |
223 | //insertorderedlist
224 | //有序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准
225 | //,'insertorderedlist':{
226 | // //自定的样式
227 | // 'num':'1,2,3...',
228 | // 'num1':'1),2),3)...',
229 | // 'num2':'(1),(2),(3)...',
230 | // 'cn':'一,二,三....',
231 | // 'cn1':'一),二),三)....',
232 | // 'cn2':'(一),(二),(三)....',
233 | // //系统自带
234 | // 'decimal' : '' , //'1,2,3...'
235 | // 'lower-alpha' : '' , // 'a,b,c...'
236 | // 'lower-roman' : '' , //'i,ii,iii...'
237 | // 'upper-alpha' : '' , lang //'A,B,C'
238 | // 'upper-roman' : '' //'I,II,III...'
239 | //}
240 |
241 | //insertunorderedlist
242 | //无序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准
243 | //,insertunorderedlist : { //自定的样式
244 | // 'dash' :'— 破折号', //-破折号
245 | // 'dot':' 。 小圆圈', //系统自带
246 | // 'circle' : '', // '○ 小圆圈'
247 | // 'disc' : '', // '● 小圆点'
248 | // 'square' : '' //'■ 小方块'
249 | //}
250 | //,listDefaultPaddingLeft : '30'//默认的左边缩进的基数倍
251 | //,listiconpath : 'http://bs.baidu.com/listicon/'//自定义标号的路径
252 | //,maxListLevel : 3 //限制可以tab的级数, 设置-1为不限制
253 |
254 | //,autoTransWordToList:false //禁止word中粘贴进来的列表自动变成列表标签
255 |
256 | //fontfamily
257 | //字体设置 label留空支持多语言自动切换,若配置,则以配置值为准
258 | //,'fontfamily':[
259 | // { label:'',name:'songti',val:'宋体,SimSun'},
260 | // { label:'',name:'kaiti',val:'楷体,楷体_GB2312, SimKai'},
261 | // { label:'',name:'yahei',val:'微软雅黑,Microsoft YaHei'},
262 | // { label:'',name:'heiti',val:'黑体, SimHei'},
263 | // { label:'',name:'lishu',val:'隶书, SimLi'},
264 | // { label:'',name:'andaleMono',val:'andale mono'},
265 | // { label:'',name:'arial',val:'arial, helvetica,sans-serif'},
266 | // { label:'',name:'arialBlack',val:'arial black,avant garde'},
267 | // { label:'',name:'comicSansMs',val:'comic sans ms'},
268 | // { label:'',name:'impact',val:'impact,chicago'},
269 | // { label:'',name:'timesNewRoman',val:'times new roman'}
270 | //]
271 |
272 | //fontsize
273 | //字号
274 | //,'fontsize':[10, 11, 12, 14, 16, 18, 20, 24, 36]
275 |
276 | //paragraph
277 | //段落格式 值留空时支持多语言自动识别,若配置,则以配置值为准
278 | //,'paragraph':{'p':'', 'h1':'', 'h2':'', 'h3':'', 'h4':'', 'h5':'', 'h6':''}
279 |
280 | //rowspacingtop
281 | //段间距 值和显示的名字相同
282 | //,'rowspacingtop':['5', '10', '15', '20', '25']
283 |
284 | //rowspacingBottom
285 | //段间距 值和显示的名字相同
286 | //,'rowspacingbottom':['5', '10', '15', '20', '25']
287 |
288 | //lineheight
289 | //行内间距 值和显示的名字相同
290 | //,'lineheight':['1', '1.5','1.75','2', '3', '4', '5']
291 |
292 | //customstyle
293 | //自定义样式,不支持国际化,此处配置值即可最后显示值
294 | //block的元素是依据设置段落的逻辑设置的,inline的元素依据BIU的逻辑设置
295 | //尽量使用一些常用的标签
296 | //参数说明
297 | //tag 使用的标签名字
298 | //label 显示的名字也是用来标识不同类型的标识符,注意这个值每个要不同,
299 | //style 添加的样式
300 | //每一个对象就是一个自定义的样式
301 | //,'customstyle':[
302 | // {tag:'h1', name:'tc', label:'', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'},
303 | // {tag:'h1', name:'tl',label:'', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;margin:0 0 10px 0;'},
304 | // {tag:'span',name:'im', label:'', style:'font-style:italic;font-weight:bold'},
305 | // {tag:'span',name:'hi', label:'', style:'font-style:italic;font-weight:bold;color:rgb(51, 153, 204)'}
306 | //]
307 |
308 | //打开右键菜单功能
309 | //,enableContextMenu: true
310 | //右键菜单的内容,可以参考plugins/contextmenu.js里边的默认菜单的例子,label留空支持国际化,否则以此配置为准
311 | //,contextMenu:[
312 | // {
313 | // label:'', //显示的名称
314 | // cmdName:'selectall',//执行的command命令,当点击这个右键菜单时
315 | // //exec可选,有了exec就会在点击时执行这个function,优先级高于cmdName
316 | // exec:function () {
317 | // //this是当前编辑器的实例
318 | // //this.ui._dialogs['inserttableDialog'].open();
319 | // }
320 | // }
321 | //]
322 |
323 | //快捷菜单
324 | //,shortcutMenu:["fontfamily", "fontsize", "bold", "italic", "underline", "forecolor", "backcolor", "insertorderedlist", "insertunorderedlist"]
325 |
326 | //elementPathEnabled
327 | //是否启用元素路径,默认是显示
328 | //,elementPathEnabled : true
329 |
330 | //wordCount
331 | //,wordCount:true //是否开启字数统计
332 | //,maximumWords:10000 //允许的最大字符数
333 | //字数统计提示,{#count}代表当前字数,{#leave}代表还可以输入多少字符数,留空支持多语言自动切换,否则按此配置显示
334 | //,wordCountMsg:'' //当前已输入 {#count} 个字符,您还可以输入{#leave} 个字符
335 | //超出字数限制提示 留空支持多语言自动切换,否则按此配置显示
336 | //,wordOverFlowMsg:'' //你输入的字符个数已经超出最大允许值,服务器可能会拒绝保存!
337 |
338 | //tab
339 | //点击tab键时移动的距离,tabSize倍数,tabNode什么字符做为单位
340 | //,tabSize:4
341 | //,tabNode:' '
342 |
343 | //removeFormat
344 | //清除格式时可以删除的标签和属性
345 | //removeForamtTags标签
346 | //,removeFormatTags:'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var'
347 | //removeFormatAttributes属性
348 | //,removeFormatAttributes:'class,style,lang,width,height,align,hspace,valign'
349 |
350 | //undo
351 | //可以最多回退的次数,默认20
352 | //,maxUndoCount:20
353 | //当输入的字符数超过该值时,保存一次现场
354 | //,maxInputCount:1
355 |
356 | //autoHeightEnabled
357 | // 是否自动长高,默认true
358 | //,autoHeightEnabled:true
359 |
360 | //scaleEnabled
361 | //是否可以拉伸长高,默认true(当开启时,自动长高失效)
362 | //,scaleEnabled:false
363 | //,minFrameWidth:800 //编辑器拖动时最小宽度,默认800
364 | //,minFrameHeight:220 //编辑器拖动时最小高度,默认220
365 |
366 | //autoFloatEnabled
367 | //是否保持toolbar的位置不动,默认true
368 | //,autoFloatEnabled:true
369 | //浮动时工具栏距离浏览器顶部的高度,用于某些具有固定头部的页面
370 | //,topOffset:30
371 | //编辑器底部距离工具栏高度(如果参数大于等于编辑器高度,则设置无效)
372 | //,toolbarTopOffset:400
373 |
374 | //设置远程图片是否抓取到本地保存
375 | //,catchRemoteImageEnable: true //设置是否抓取远程图片
376 |
377 | //pageBreakTag
378 | //分页标识符,默认是_ueditor_page_break_tag_
379 | //,pageBreakTag:'_ueditor_page_break_tag_'
380 |
381 | //autotypeset
382 | //自动排版参数
383 | //,autotypeset: {
384 | // mergeEmptyline: true, //合并空行
385 | // removeClass: true, //去掉冗余的class
386 | // removeEmptyline: false, //去掉空行
387 | // textAlign:"left", //段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版
388 | // imageBlockLine: 'center', //图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版
389 | // pasteFilter: false, //根据规则过滤没事粘贴进来的内容
390 | // clearFontSize: false, //去掉所有的内嵌字号,使用编辑器默认的字号
391 | // clearFontFamily: false, //去掉所有的内嵌字体,使用编辑器默认的字体
392 | // removeEmptyNode: false, // 去掉空节点
393 | // //可以去掉的标签
394 | // removeTagNames: {标签名字:1},
395 | // indent: false, // 行首缩进
396 | // indentValue : '2em', //行首缩进的大小
397 | // bdc2sb: false,
398 | // tobdc: false
399 | //}
400 |
401 | //tableDragable
402 | //表格是否可以拖拽
403 | //,tableDragable: true
404 |
405 |
406 |
407 | //sourceEditor
408 | //源码的查看方式,codemirror 是代码高亮,textarea是文本框,默认是codemirror
409 | //注意默认codemirror只能在ie8+和非ie中使用
410 | //,sourceEditor:"codemirror"
411 | //如果sourceEditor是codemirror,还用配置一下两个参数
412 | //codeMirrorJsUrl js加载的路径,默认是 URL + "third-party/codemirror/codemirror.js"
413 | //,codeMirrorJsUrl:URL + "third-party/codemirror/codemirror.js"
414 | //codeMirrorCssUrl css加载的路径,默认是 URL + "third-party/codemirror/codemirror.css"
415 | //,codeMirrorCssUrl:URL + "third-party/codemirror/codemirror.css"
416 | //编辑器初始化完成后是否进入源码模式,默认为否。
417 | //,sourceEditorFirst:false
418 |
419 | //iframeUrlMap
420 | //dialog内容的路径 ~会被替换成URL,垓属性一旦打开,将覆盖所有的dialog的默认路径
421 | //,iframeUrlMap:{
422 | // 'anchor':'~/dialogs/anchor/anchor.html',
423 | //}
424 |
425 | //allowLinkProtocol 允许的链接地址,有这些前缀的链接地址不会自动添加http
426 | //, allowLinkProtocols: ['http:', 'https:', '#', '/', 'ftp:', 'mailto:', 'tel:', 'git:', 'svn:']
427 |
428 | //webAppKey 百度应用的APIkey,每个站长必须首先去百度官网注册一个key后方能正常使用app功能,注册介绍,http://app.baidu.com/static/cms/getapikey.html
429 | //, webAppKey: ""
430 |
431 | //默认过滤规则相关配置项目
432 | //,disabledTableInTable:true //禁止表格嵌套
433 | //,allowDivTransToP:true //允许进入编辑器的div标签自动变成p标签
434 | //,rgb2Hex:true //默认产出的数据中的color自动从rgb格式变成16进制格式
435 |
436 | // xss 过滤是否开启,inserthtml等操作
437 | ,xssFilterRules: true
438 | //input xss过滤
439 | ,inputXssFilter: true
440 | //output xss过滤
441 | ,outputXssFilter: true
442 | // xss过滤白名单 名单来源: https://raw.githubusercontent.com/leizongmin/js-xss/master/lib/default.js
443 | ,whitList: {
444 | a: ['target', 'href', 'title', 'class', 'style'],
445 | abbr: ['title', 'class', 'style'],
446 | address: ['class', 'style'],
447 | area: ['shape', 'coords', 'href', 'alt'],
448 | article: [],
449 | aside: [],
450 | audio: ['autoplay', 'controls', 'loop', 'preload', 'src', 'class', 'style'],
451 | b: ['class', 'style'],
452 | bdi: ['dir'],
453 | bdo: ['dir'],
454 | big: [],
455 | blockquote: ['cite', 'class', 'style'],
456 | br: [],
457 | caption: ['class', 'style'],
458 | center: [],
459 | cite: [],
460 | code: ['class', 'style'],
461 | col: ['align', 'valign', 'span', 'width', 'class', 'style'],
462 | colgroup: ['align', 'valign', 'span', 'width', 'class', 'style'],
463 | dd: ['class', 'style'],
464 | del: ['datetime'],
465 | details: ['open'],
466 | div: ['class', 'style'],
467 | dl: ['class', 'style'],
468 | dt: ['class', 'style'],
469 | em: ['class', 'style'],
470 | font: ['color', 'size', 'face'],
471 | footer: [],
472 | h1: ['class', 'style'],
473 | h2: ['class', 'style'],
474 | h3: ['class', 'style'],
475 | h4: ['class', 'style'],
476 | h5: ['class', 'style'],
477 | h6: ['class', 'style'],
478 | header: [],
479 | hr: [],
480 | i: ['class', 'style'],
481 | img: ['src', 'alt', 'title', 'width', 'height', 'id', '_src', 'loadingclass', 'class', 'data-latex'],
482 | ins: ['datetime'],
483 | li: ['class', 'style'],
484 | mark: [],
485 | nav: [],
486 | ol: ['class', 'style'],
487 | p: ['class', 'style'],
488 | pre: ['class', 'style'],
489 | s: [],
490 | section:[],
491 | small: [],
492 | span: ['class', 'style'],
493 | sub: ['class', 'style'],
494 | sup: ['class', 'style'],
495 | strong: ['class', 'style'],
496 | table: ['width', 'border', 'align', 'valign', 'class', 'style'],
497 | tbody: ['align', 'valign', 'class', 'style'],
498 | td: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
499 | tfoot: ['align', 'valign', 'class', 'style'],
500 | th: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
501 | thead: ['align', 'valign', 'class', 'style'],
502 | tr: ['rowspan', 'align', 'valign', 'class', 'style'],
503 | tt: [],
504 | u: [],
505 | ul: ['class', 'style'],
506 | video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width', 'class', 'style']
507 | }
508 | };
509 |
510 | function getUEBasePath(docUrl, confUrl) {
511 |
512 | return getBasePath(docUrl || self.document.URL || self.location.href, confUrl || getConfigFilePath());
513 |
514 | }
515 |
516 | function getConfigFilePath() {
517 |
518 | var configPath = document.getElementsByTagName('script');
519 |
520 | return configPath[ configPath.length - 1 ].src;
521 |
522 | }
523 |
524 | function getBasePath(docUrl, confUrl) {
525 |
526 | var basePath = confUrl;
527 |
528 |
529 | if (/^(\/|\\\\)/.test(confUrl)) {
530 |
531 | basePath = /^.+?\w(\/|\\\\)/.exec(docUrl)[0] + confUrl.replace(/^(\/|\\\\)/, '');
532 |
533 | } else if (!/^[a-z]+:/i.test(confUrl)) {
534 |
535 | docUrl = docUrl.split("#")[0].split("?")[0].replace(/[^\\\/]+$/, '');
536 |
537 | basePath = docUrl + "" + confUrl;
538 |
539 | }
540 |
541 | return optimizationPath(basePath);
542 |
543 | }
544 |
545 | function optimizationPath(path) {
546 |
547 | var protocol = /^[a-z]+:\/\//.exec(path)[ 0 ],
548 | tmp = null,
549 | res = [];
550 |
551 | path = path.replace(protocol, "").split("?")[0].split("#")[0];
552 |
553 | path = path.replace(/\\/g, '/').split(/\//);
554 |
555 | path[ path.length - 1 ] = "";
556 |
557 | while (path.length) {
558 |
559 | if (( tmp = path.shift() ) === "..") {
560 | res.pop();
561 | } else if (tmp !== ".") {
562 | res.push(tmp);
563 | }
564 |
565 | }
566 |
567 | return protocol + res.join("/");
568 |
569 | }
570 |
571 | window.UE = {
572 | getUEBasePath: getUEBasePath
573 | };
574 |
575 | })();
576 |
577 | ## 联系
578 |
579 | Email: usocjb@163.com
580 | weixin: chenjianbin519846538
581 |
582 | ```
583 |
--------------------------------------------------------------------------------