diff --git a/build/examples/build.js b/build/examples/build.js index 26cd6506..c7fe42d6 100644 --- a/build/examples/build.js +++ b/build/examples/build.js @@ -5,20 +5,20 @@ import config from './webpack.config' const spinner = ora('Building …') export default new Promise((resolve, reject) => { - spinner.start() + spinner.start() - webpack(config, (error, stats) => { - if (error) { - return reject(error) - } + webpack(config, (error, stats) => { + if (error) { + return reject(error) + } - if (stats.hasErrors()) { - process.stdout.write(stats.toString() + "\n"); - return reject(new Error('Build failed with errors.')) - } + if (stats.hasErrors()) { + process.stdout.write(stats.toString() + "\n"); + return reject(new Error('Build failed with errors.')) + } - return resolve('Build complete.') - }) + return resolve('Build complete.') + }) }) .then(success => spinner.succeed(success)) .catch(error => spinner.fail(error)) diff --git a/build/examples/server.js b/build/examples/server.js index d971bdcd..447f9a6f 100644 --- a/build/examples/server.js +++ b/build/examples/server.js @@ -16,11 +16,11 @@ middlewares.push(historyApiFallbackMiddleware()) // add webpack stuff middlewares.push(webpackDevMiddleware(bundler, { - publicPath: config.output.publicPath, - stats: { - colors: true, - chunks: false, - }, + publicPath: config.output.publicPath, + stats: { + colors: true, + chunks: false, + }, })) // add hot reloading @@ -30,25 +30,25 @@ middlewares.push(webpackHotMiddleware(bundler)) const url = 'http://localhost' const bs = browserSync.create() const server = bs.init({ - server: { - baseDir: `${srcPath}/`, - middleware: middlewares, - }, - files: [], - logLevel: 'silent', - open: false, - notify: false, - injectChanges: false, - ghostMode: { - clicks: false, - forms: false, - scroll: false, - }, + server: { + baseDir: `${srcPath}/`, + middleware: middlewares, + }, + files: [], + logLevel: 'silent', + open: false, + notify: false, + injectChanges: false, + ghostMode: { + clicks: false, + forms: false, + scroll: false, + }, }) console.log(`${url}:${server.options.get('port')}`) // sass import bs.watch(path.join(sassImportPath, '**/!(index|index_sub).scss'), { ignoreInitial: true }, () => { - sassImport(sassImportPath) + sassImport(sassImportPath) }) diff --git a/build/examples/utilities.js b/build/examples/utilities.js index f6792766..8f0ca34e 100644 --- a/build/examples/utilities.js +++ b/build/examples/utilities.js @@ -6,11 +6,11 @@ import minimist from 'minimist' let argv = minimist(process.argv.slice(2)) export function removeEmpty(array) { - return array.filter(entry => !!entry) + return array.filter(entry => !!entry) } export function ifElse(condition) { - return (then, otherwise) => (condition ? then : otherwise) + return (then, otherwise) => (condition ? then : otherwise) } export const env = argv.env || 'development' @@ -23,25 +23,25 @@ export const ifProd = ifElse(isProd) export const ifTest = ifElse(isTest) export function sassImport(basePath) { - const indexFileName = 'index.scss' - glob.sync(`${basePath}/**/${indexFileName}`).forEach(sourceFile => { - fs.writeFileSync(sourceFile, '// This is a dynamically generated file \n\n') - glob.sync(`${path.dirname(sourceFile)}/*.scss`).forEach(file => { - if (path.basename(file) !== indexFileName) { - fs.appendFileSync(sourceFile, `@import "${path.basename(file)}";\n`) - } - }) - }) + const indexFileName = 'index.scss' + glob.sync(`${basePath}/**/${indexFileName}`).forEach(sourceFile => { + fs.writeFileSync(sourceFile, '// This is a dynamically generated file \n\n') + glob.sync(`${path.dirname(sourceFile)}/*.scss`).forEach(file => { + if (path.basename(file) !== indexFileName) { + fs.appendFileSync(sourceFile, `@import "${path.basename(file)}";\n`) + } + }) + }) - const indexSubFileName = 'index_sub.scss' - glob.sync(`${basePath}/**/${indexSubFileName}`).forEach(sourceFile => { - fs.writeFileSync(sourceFile, '// This is a dynamically generated file \n\n') - glob.sync(`${path.dirname(sourceFile)}/**/*.scss`).forEach(file => { - if (path.basename(file) !== indexSubFileName) { - let importPath = (path.dirname(sourceFile) === path.dirname(file)) ? path.basename(file) : file - importPath = importPath.replace(`${path.dirname(sourceFile)}/`, '') - fs.appendFileSync(sourceFile, `@import "${importPath}";\n`) - } - }) - }) + const indexSubFileName = 'index_sub.scss' + glob.sync(`${basePath}/**/${indexSubFileName}`).forEach(sourceFile => { + fs.writeFileSync(sourceFile, '// This is a dynamically generated file \n\n') + glob.sync(`${path.dirname(sourceFile)}/**/*.scss`).forEach(file => { + if (path.basename(file) !== indexSubFileName) { + let importPath = (path.dirname(sourceFile) === path.dirname(file)) ? path.basename(file) : file + importPath = importPath.replace(`${path.dirname(sourceFile)}/`, '') + fs.appendFileSync(sourceFile, `@import "${importPath}";\n`) + } + }) + }) } diff --git a/build/examples/webpack.config.js b/build/examples/webpack.config.js index 84316ea5..0d4e5fac 100644 --- a/build/examples/webpack.config.js +++ b/build/examples/webpack.config.js @@ -13,214 +13,214 @@ import { rootPath, srcPath, buildPath } from './paths' export default { - mode: ifDev('development', 'production'), + mode: ifDev('development', 'production'), - entry: { - app: removeEmpty([ - ifDev('webpack-hot-middleware/client?reload=true'), - `${srcPath}/assets/sass/main.scss`, - `${srcPath}/main.js`, - ]), - }, + entry: { + app: removeEmpty([ + ifDev('webpack-hot-middleware/client?reload=true'), + `${srcPath}/assets/sass/main.scss`, + `${srcPath}/main.js`, + ]), + }, - output: { - path: `${buildPath}/`, - filename: `assets/js/[name]${ifProd('.[hash]', '')}.js`, - chunkFilename: `assets/js/[name]${ifProd('.[chunkhash]', '')}.js`, - publicPath: '/', - }, + output: { + path: `${buildPath}/`, + filename: `assets/js/[name]${ifProd('.[hash]', '')}.js`, + chunkFilename: `assets/js/[name]${ifProd('.[chunkhash]', '')}.js`, + publicPath: '/', + }, - resolve: { - extensions: ['.js', '.scss', '.vue'], - alias: { - vue$: 'vue/dist/vue.esm.js', - modules: path.resolve(rootPath, '../node_modules'), - images: `${srcPath}/assets/images`, - fonts: `${srcPath}/assets/fonts`, - variables: `${srcPath}/assets/sass/variables`, - tiptap: path.resolve(rootPath, '../packages/tiptap/src'), - 'tiptap-commands': path.resolve(rootPath, '../packages/tiptap-commands/src'), - 'tiptap-utils': path.resolve(rootPath, '../packages/tiptap-utils/src'), - 'tiptap-models': path.resolve(rootPath, '../packages/tiptap-models/src'), - 'tiptap-extensions': path.resolve(rootPath, '../packages/tiptap-extensions/src'), - }, - modules: [ - srcPath, - path.resolve(rootPath, '../node_modules'), - ], - }, + resolve: { + extensions: ['.js', '.scss', '.vue'], + alias: { + vue$: 'vue/dist/vue.esm.js', + modules: path.resolve(rootPath, '../node_modules'), + images: `${srcPath}/assets/images`, + fonts: `${srcPath}/assets/fonts`, + variables: `${srcPath}/assets/sass/variables`, + tiptap: path.resolve(rootPath, '../packages/tiptap/src'), + 'tiptap-commands': path.resolve(rootPath, '../packages/tiptap-commands/src'), + 'tiptap-utils': path.resolve(rootPath, '../packages/tiptap-utils/src'), + 'tiptap-models': path.resolve(rootPath, '../packages/tiptap-models/src'), + 'tiptap-extensions': path.resolve(rootPath, '../packages/tiptap-extensions/src'), + }, + modules: [ + srcPath, + path.resolve(rootPath, '../node_modules'), + ], + }, - devtool: ifDev('eval-source-map', 'source-map'), + devtool: ifDev('eval-source-map', 'source-map'), - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader', - }, - { - test: /\.js$/, - exclude: [/node_modules/], - use: { - loader: ifDev('babel-loader?cacheDirectory=true', 'babel-loader'), - options: { - presets: [ - '@babel/preset-env', - ], - plugins: [ - '@babel/plugin-syntax-dynamic-import', - ], - }, - }, - }, - { - test: /\.css$/, - use: removeEmpty([ - ifDev('vue-style-loader', MiniCssExtractPlugin.loader), - 'css-loader', - 'postcss-loader', - ]), - }, - { - test: /\.scss$/, - use: removeEmpty([ - ifDev('vue-style-loader', MiniCssExtractPlugin.loader), - 'css-loader', - 'postcss-loader', - 'sass-loader', - ]), - }, - { - test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/, - use: { - loader: 'file-loader', - options: { - name: `assets/images/[name]${ifProd('.[hash]', '')}.[ext]`, - }, - }, - }, - { - test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, - use: { - loader: 'file-loader', - options: { - name: `assets/fonts/[name]${ifProd('.[hash]', '')}.[ext]`, - }, - }, - }, - ], - }, + module: { + rules: [ + { + test: /\.vue$/, + loader: 'vue-loader', + }, + { + test: /\.js$/, + exclude: [/node_modules/], + use: { + loader: ifDev('babel-loader?cacheDirectory=true', 'babel-loader'), + options: { + presets: [ + '@babel/preset-env', + ], + plugins: [ + '@babel/plugin-syntax-dynamic-import', + ], + }, + }, + }, + { + test: /\.css$/, + use: removeEmpty([ + ifDev('vue-style-loader', MiniCssExtractPlugin.loader), + 'css-loader', + 'postcss-loader', + ]), + }, + { + test: /\.scss$/, + use: removeEmpty([ + ifDev('vue-style-loader', MiniCssExtractPlugin.loader), + 'css-loader', + 'postcss-loader', + 'sass-loader', + ]), + }, + { + test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/, + use: { + loader: 'file-loader', + options: { + name: `assets/images/[name]${ifProd('.[hash]', '')}.[ext]`, + }, + }, + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + use: { + loader: 'file-loader', + options: { + name: `assets/fonts/[name]${ifProd('.[hash]', '')}.[ext]`, + }, + }, + }, + ], + }, - // splitting out the vendor - optimization: { - namedModules: true, - splitChunks: { - name: 'vendor', - minChunks: 2, - }, - noEmitOnErrors: true, - // concatenateModules: true, - }, + // splitting out the vendor + optimization: { + namedModules: true, + splitChunks: { + name: 'vendor', + minChunks: 2, + }, + noEmitOnErrors: true, + // concatenateModules: true, + }, - plugins: removeEmpty([ + plugins: removeEmpty([ - // create manifest file for server-side asset manipulation - new ManifestPlugin({ - fileName: 'assets/manifest.json', - writeToFileEmit: true, - }), + // create manifest file for server-side asset manipulation + new ManifestPlugin({ + fileName: 'assets/manifest.json', + writeToFileEmit: true, + }), - // define env - // new webpack.DefinePlugin({ - // 'process.env': {}, - // }), + // define env + // new webpack.DefinePlugin({ + // 'process.env': {}, + // }), - // copy static files - new CopyWebpackPlugin([ - { - context: `${srcPath}/assets/static`, - from: { glob: '**/*', dot: false }, - to: `${buildPath}/assets`, - }, - { - context: `${srcPath}/assets/static`, - from: { glob: '**/*', dot: false }, - to: `${buildPath}/assets/[path][name].[hash].[ext]`, - }, - ]), + // copy static files + new CopyWebpackPlugin([ + { + context: `${srcPath}/assets/static`, + from: { glob: '**/*', dot: false }, + to: `${buildPath}/assets`, + }, + { + context: `${srcPath}/assets/static`, + from: { glob: '**/*', dot: false }, + to: `${buildPath}/assets/[path][name].[hash].[ext]`, + }, + ]), - // enable hot reloading - ifDev(new webpack.HotModuleReplacementPlugin()), + // enable hot reloading + ifDev(new webpack.HotModuleReplacementPlugin()), - // html - new HtmlWebpackPlugin({ - filename: 'index.html', - template: `${srcPath}/index.html`, - inject: true, - minify: ifProd({ - removeComments: true, - collapseWhitespace: true, - removeAttributeQuotes: true, - }), - buildVersion: new Date().valueOf(), - chunksSortMode: 'none', - }), + // html + new HtmlWebpackPlugin({ + filename: 'index.html', + template: `${srcPath}/index.html`, + inject: true, + minify: ifProd({ + removeComments: true, + collapseWhitespace: true, + removeAttributeQuotes: true, + }), + buildVersion: new Date().valueOf(), + chunksSortMode: 'none', + }), - new VueLoaderPlugin(), + new VueLoaderPlugin(), - // create css files - ifProd(new MiniCssExtractPlugin({ - filename: `assets/css/[name]${ifProd('.[hash]', '')}.css`, - chunkFilename: `assets/css/[name]${ifProd('.[hash]', '')}.css`, - })), + // create css files + ifProd(new MiniCssExtractPlugin({ + filename: `assets/css/[name]${ifProd('.[hash]', '')}.css`, + chunkFilename: `assets/css/[name]${ifProd('.[hash]', '')}.css`, + })), - // minify css files - ifProd(new OptimizeCssAssetsPlugin({ - cssProcessorOptions: { - reduceIdents: false, - autoprefixer: false, - zindex: false, - discardComments: { - removeAll: true, - }, - }, - })), + // minify css files + ifProd(new OptimizeCssAssetsPlugin({ + cssProcessorOptions: { + reduceIdents: false, + autoprefixer: false, + zindex: false, + discardComments: { + removeAll: true, + }, + }, + })), - // svg icons - new SvgStore({ - prefix: 'icon--', - svgoOptions: { - plugins: [ - { cleanupIDs: false }, - { collapseGroups: false }, - { removeTitle: true }, - ], - }, - }), + // svg icons + new SvgStore({ + prefix: 'icon--', + svgoOptions: { + plugins: [ + { cleanupIDs: false }, + { collapseGroups: false }, + { removeTitle: true }, + ], + }, + }), - // image optimization - new ImageminWebpackPlugin({ - optipng: ifDev(null, { - optimizationLevel: 3, - }), - jpegtran: ifDev(null, { - progressive: true, - quality: 80, - }), - svgo: ifDev(null, { - plugins: [ - { cleanupIDs: false }, - { removeViewBox: false }, - { removeUselessStrokeAndFill: false }, - { removeEmptyAttrs: false }, - ], - }), - }), + // image optimization + new ImageminWebpackPlugin({ + optipng: ifDev(null, { + optimizationLevel: 3, + }), + jpegtran: ifDev(null, { + progressive: true, + quality: 80, + }), + svgo: ifDev(null, { + plugins: [ + { cleanupIDs: false }, + { removeViewBox: false }, + { removeUselessStrokeAndFill: false }, + { removeEmptyAttrs: false }, + ], + }), + }), - ]), + ]), - node: { - fs: 'empty', - }, + node: { + fs: 'empty', + }, } diff --git a/build/packages/config.js b/build/packages/config.js index 25150c17..a05d2ef0 100644 --- a/build/packages/config.js +++ b/build/packages/config.js @@ -9,7 +9,7 @@ import packagejson from '../../package.json' const { version } = packagejson const banner = ` - /*! + /*! * tiptap v${version} * (c) ${new Date().getFullYear()} Scrumpy UG (limited liability) * @license MIT @@ -23,19 +23,19 @@ function genConfig(opts) { input: { input: opts.input, plugins: [ - flow(), + flow(), node(), cjs(), - vue({ - css: true, - compileTemplate: true, - }), + vue({ + css: true, + compileTemplate: true, + }), replace({ __VERSION__: version, }), buble({ - objectAssign: 'Object.assign', - }), + objectAssign: 'Object.assign', + }), ], external(id) { return !/^[\.\/]/.test(id) }, }, @@ -44,7 +44,7 @@ function genConfig(opts) { format: opts.format, banner, name: 'tiptap', - }, + }, } if (opts.env) { diff --git a/examples/Components/Ad/index.vue b/examples/Components/Ad/index.vue index e48f8e1a..5184c551 100644 --- a/examples/Components/Ad/index.vue +++ b/examples/Components/Ad/index.vue @@ -1,7 +1,7 @@ diff --git a/examples/Components/Ad/style.scss b/examples/Components/Ad/style.scss index 9b938444..81556ef4 100644 --- a/examples/Components/Ad/style.scss +++ b/examples/Components/Ad/style.scss @@ -1,42 +1,42 @@ @import "~variables"; .ad { - display: block; - padding: 1rem; - transition: 0.2s transform; - margin: 3rem auto 0 auto; - width: 15rem; + display: block; + padding: 1rem; + transition: 0.2s transform; + margin: 3rem auto 0 auto; + width: 15rem; - @media (min-width: 1020px) { - position: fixed; - left: 0; - bottom: 0; - margin-top: 0; - } + @media (min-width: 1020px) { + position: fixed; + left: 0; + bottom: 0; + margin-top: 0; + } - &__image { - display: block; - width: 100%; - height: auto; - border-radius: 5px; - overflow: hidden; - transition: 0.2s box-shadow; - box-shadow: - 0 2px 4px 0 rgba(black, 0.05), - 0 2px 10px 0 rgba(black, 0.07) - ; - } + &__image { + display: block; + width: 100%; + height: auto; + border-radius: 5px; + overflow: hidden; + transition: 0.2s box-shadow; + box-shadow: + 0 2px 4px 0 rgba(black, 0.05), + 0 2px 10px 0 rgba(black, 0.07) + ; + } - &:hover { - transform: translateY(-5px); - } + &:hover { + transform: translateY(-5px); + } - &:hover &__image { - box-shadow: - 0 2px 1px 0 rgba(black, 0.07), - 0 5px 20px 0 rgba(black, 0.06), - 0 8px 40px 0 rgba(black, 0.04) - ; - } + &:hover &__image { + box-shadow: + 0 2px 1px 0 rgba(black, 0.07), + 0 5px 20px 0 rgba(black, 0.06), + 0 8px 40px 0 rgba(black, 0.04) + ; + } -} \ No newline at end of file +} diff --git a/examples/Components/App/style.scss b/examples/Components/App/style.scss index b81dc98a..c700022a 100644 --- a/examples/Components/App/style.scss +++ b/examples/Components/App/style.scss @@ -2,8 +2,8 @@ .page { - &__content { - padding: 4rem 1rem; + &__content { + padding: 4rem 1rem; } &__footer { @@ -212,4 +212,4 @@ li[data-done="true"] .todo-checkbox { li[data-done="false"] { text-decoration: none; -} \ No newline at end of file +} diff --git a/examples/Components/Hero/index.vue b/examples/Components/Hero/index.vue index d6c15a04..ea5c23f9 100644 --- a/examples/Components/Hero/index.vue +++ b/examples/Components/Hero/index.vue @@ -1,17 +1,17 @@ diff --git a/examples/Components/Hero/style.scss b/examples/Components/Hero/style.scss index 8b44796e..c77fec24 100644 --- a/examples/Components/Hero/style.scss +++ b/examples/Components/Hero/style.scss @@ -2,23 +2,23 @@ .hero { - background-color: $color-black; - color: $color-white; - text-align: center; - padding: 3rem 1rem; + background-color: $color-black; + color: $color-white; + text-align: center; + padding: 3rem 1rem; - &__inner { - margin: 0 auto; - max-width: 30rem; - } + &__inner { + margin: 0 auto; + max-width: 30rem; + } - &__logo { - width: 4rem; - height: 4rem; + &__logo { + width: 4rem; + height: 4rem; - path { - fill: $color-white; - } - } + path { + fill: $color-white; + } + } -} \ No newline at end of file +} diff --git a/examples/Components/Icon/index.vue b/examples/Components/Icon/index.vue index eac940ca..29f23ad0 100644 --- a/examples/Components/Icon/index.vue +++ b/examples/Components/Icon/index.vue @@ -1,57 +1,57 @@ diff --git a/examples/Components/Navigation/index.vue b/examples/Components/Navigation/index.vue index 39979957..628657ea 100644 --- a/examples/Components/Navigation/index.vue +++ b/examples/Components/Navigation/index.vue @@ -1,30 +1,30 @@ - \ No newline at end of file + diff --git a/examples/Components/Navigation/style.scss b/examples/Components/Navigation/style.scss index bbb49e38..ba3c6127 100644 --- a/examples/Components/Navigation/style.scss +++ b/examples/Components/Navigation/style.scss @@ -2,54 +2,54 @@ .navigation { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.75rem; - background-color: $color-black; - color: $color-white; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.75rem; + background-color: $color-black; + color: $color-white; - &__logo { - font-size: 1.1rem; - font-weight: bold; - margin: 0; - } + &__logo { + font-size: 1.1rem; + font-weight: bold; + margin: 0; + } - &__icon { - width: 1.5rem; - height: 1.5rem; - } + &__icon { + width: 1.5rem; + height: 1.5rem; + } - &__beta { - display: inline-block; - vertical-align: middle; - background-color: $color-white; - color: $color-black; - font-size: 0.6rem; - font-weight: bold; - text-transform: uppercase; - letter-spacing: 0.05rem; - padding: 0.1rem 0.2rem; - border-radius: 5px; - } + &__beta { + display: inline-block; + vertical-align: middle; + background-color: $color-white; + color: $color-black; + font-size: 0.6rem; + font-weight: bold; + text-transform: uppercase; + letter-spacing: 0.05rem; + padding: 0.1rem 0.2rem; + border-radius: 5px; + } - &__link { - display: inline-block; - color: rgba($color-white, 0.5); - text-decoration: none; - font-weight: bold; - font-size: 0.9rem; - padding: 0.1rem 0.5rem; - border-radius: 3px; + &__link { + display: inline-block; + color: rgba($color-white, 0.5); + text-decoration: none; + font-weight: bold; + font-size: 0.9rem; + padding: 0.1rem 0.5rem; + border-radius: 3px; - &:hover { - color: $color-white; + &:hover { + color: $color-white; background-color: rgba($color-white, 0.1); } - } + } - &__github-link { - margin-left: 0.5rem; - } + &__github-link { + margin-left: 0.5rem; + } -} \ No newline at end of file +} diff --git a/examples/Components/Routes/Basic/index.vue b/examples/Components/Routes/Basic/index.vue index 6f0d9fb0..efa91d35 100644 --- a/examples/Components/Routes/Basic/index.vue +++ b/examples/Components/Routes/Basic/index.vue @@ -1,209 +1,209 @@ \ No newline at end of file + diff --git a/examples/Components/Routes/CodeHighlighting/index.vue b/examples/Components/Routes/CodeHighlighting/index.vue index 0782347a..7f46c23b 100644 --- a/examples/Components/Routes/CodeHighlighting/index.vue +++ b/examples/Components/Routes/CodeHighlighting/index.vue @@ -1,136 +1,136 @@ diff --git a/examples/Components/Routes/Embeds/Iframe.js b/examples/Components/Routes/Embeds/Iframe.js index fef35aca..63141242 100644 --- a/examples/Components/Routes/Embeds/Iframe.js +++ b/examples/Components/Routes/Embeds/Iframe.js @@ -2,57 +2,57 @@ import { Node } from 'tiptap' export default class Iframe extends Node { - get name() { - return 'iframe' - } + get name() { + return 'iframe' + } - get schema() { - return { - attrs: { - src: { - default: null, - }, - }, - group: 'block', - selectable: false, - parseDOM: [{ - tag: 'iframe', - getAttrs: dom => ({ - src: dom.getAttribute('src'), - }), - }], - toDOM: node => ['iframe', { - src: node.attrs.src, - frameborder: 0, - allowfullscreen: 'true', - }], - } - } + get schema() { + return { + attrs: { + src: { + default: null, + }, + }, + group: 'block', + selectable: false, + parseDOM: [{ + tag: 'iframe', + getAttrs: dom => ({ + src: dom.getAttribute('src'), + }), + }], + toDOM: node => ['iframe', { + src: node.attrs.src, + frameborder: 0, + allowfullscreen: 'true', + }], + } + } - get view() { - return { - props: ['node', 'updateAttrs', 'editable'], - data() { - return { - url: this.node.attrs.src, - } - }, - methods: { - onChange(event) { - this.url = event.target.value + get view() { + return { + props: ['node', 'updateAttrs', 'editable'], + data() { + return { + url: this.node.attrs.src, + } + }, + methods: { + onChange(event) { + this.url = event.target.value - this.updateAttrs({ - src: this.url, - }) - }, - }, - template: ` -
- - -
- `, - } - } + this.updateAttrs({ + src: this.url, + }) + }, + }, + template: ` +
+ + +
+ `, + } + } } diff --git a/examples/Components/Routes/Embeds/index.vue b/examples/Components/Routes/Embeds/index.vue index 8d927c54..907dbc9f 100644 --- a/examples/Components/Routes/Embeds/index.vue +++ b/examples/Components/Routes/Embeds/index.vue @@ -1,51 +1,51 @@ @@ -53,20 +53,20 @@ export default { @import "~variables"; .iframe { - &__embed { - width: 100%; - height: 15rem; - border: 0; - } + &__embed { + width: 100%; + height: 15rem; + border: 0; + } - &__input { - display: block; - width: 100%; - font: inherit; - border: 0; - border-radius: 5px; - background-color: rgba($color-black, 0.1); - padding: 0.3rem 0.5rem; - } + &__input { + display: block; + width: 100%; + font: inherit; + border: 0; + border-radius: 5px; + background-color: rgba($color-black, 0.1); + padding: 0.3rem 0.5rem; + } } diff --git a/examples/Components/Routes/Export/index.vue b/examples/Components/Routes/Export/index.vue index f14238f0..a2d3348f 100644 --- a/examples/Components/Routes/Export/index.vue +++ b/examples/Components/Routes/Export/index.vue @@ -1,203 +1,203 @@ @@ -205,27 +205,27 @@ export default { @import "~variables"; .actions { - max-width: 30rem; - margin: 0 auto 2rem auto; + max-width: 30rem; + margin: 0 auto 2rem auto; } .export { - max-width: 30rem; - margin: 0 auto 2rem auto; + max-width: 30rem; + margin: 0 auto 2rem auto; - pre { - padding: 1rem; - border-radius: 5px; - font-size: 0.8rem; - font-weight: bold; - background: rgba($color-black, 0.05); - color: rgba($color-black, 0.8); - } + pre { + padding: 1rem; + border-radius: 5px; + font-size: 0.8rem; + font-weight: bold; + background: rgba($color-black, 0.05); + color: rgba($color-black, 0.8); + } - code { - display: block; - white-space: pre-wrap; - } + code { + display: block; + white-space: pre-wrap; + } } diff --git a/examples/Components/Routes/FloatingMenu/index.vue b/examples/Components/Routes/FloatingMenu/index.vue index d0513dac..5a761042 100644 --- a/examples/Components/Routes/FloatingMenu/index.vue +++ b/examples/Components/Routes/FloatingMenu/index.vue @@ -1,132 +1,132 @@ @@ -135,20 +135,20 @@ export default { .editor { - position: relative; + position: relative; - &__floating-menu { - position: absolute; - margin-top: -0.25rem; - visibility: hidden; - opacity: 0; - transition: opacity 0.2s, visibility 0.2s; + &__floating-menu { + position: absolute; + margin-top: -0.25rem; + visibility: hidden; + opacity: 0; + transition: opacity 0.2s, visibility 0.2s; - &.is-active { - opacity: 1; - visibility: visible; - } - } + &.is-active { + opacity: 1; + visibility: visible; + } + } } - \ No newline at end of file + diff --git a/examples/Components/Routes/HidingMenuBar/index.vue b/examples/Components/Routes/HidingMenuBar/index.vue index 3e3d259d..b463b4f0 100644 --- a/examples/Components/Routes/HidingMenuBar/index.vue +++ b/examples/Components/Routes/HidingMenuBar/index.vue @@ -1,185 +1,185 @@ \ No newline at end of file + diff --git a/examples/Components/Routes/Images/index.vue b/examples/Components/Routes/Images/index.vue index 79356dfa..500c5091 100644 --- a/examples/Components/Routes/Images/index.vue +++ b/examples/Components/Routes/Images/index.vue @@ -1,68 +1,68 @@ \ No newline at end of file + diff --git a/examples/Components/Routes/Links/index.vue b/examples/Components/Routes/Links/index.vue index 607c833f..5284eab4 100644 --- a/examples/Components/Routes/Links/index.vue +++ b/examples/Components/Routes/Links/index.vue @@ -1,113 +1,113 @@ \ No newline at end of file + diff --git a/examples/Components/Routes/MarkdownShortcuts/index.vue b/examples/Components/Routes/MarkdownShortcuts/index.vue index 09d1f4fc..325f3c0e 100644 --- a/examples/Components/Routes/MarkdownShortcuts/index.vue +++ b/examples/Components/Routes/MarkdownShortcuts/index.vue @@ -1,69 +1,69 @@ \ No newline at end of file + diff --git a/examples/Components/Routes/MenuBubble/index.vue b/examples/Components/Routes/MenuBubble/index.vue index e0469ba8..a8a992a2 100644 --- a/examples/Components/Routes/MenuBubble/index.vue +++ b/examples/Components/Routes/MenuBubble/index.vue @@ -1,106 +1,106 @@ \ No newline at end of file + diff --git a/examples/Components/Routes/Placeholder/index.vue b/examples/Components/Routes/Placeholder/index.vue index f192115c..59ed3880 100644 --- a/examples/Components/Routes/Placeholder/index.vue +++ b/examples/Components/Routes/Placeholder/index.vue @@ -1,47 +1,47 @@ diff --git a/examples/Components/Routes/ReadOnly/index.vue b/examples/Components/Routes/ReadOnly/index.vue index 6994057d..607c9be4 100644 --- a/examples/Components/Routes/ReadOnly/index.vue +++ b/examples/Components/Routes/ReadOnly/index.vue @@ -1,49 +1,49 @@ \ No newline at end of file + diff --git a/examples/Components/Routes/Suggestions/index.vue b/examples/Components/Routes/Suggestions/index.vue index d5e4101c..214f58d8 100644 --- a/examples/Components/Routes/Suggestions/index.vue +++ b/examples/Components/Routes/Suggestions/index.vue @@ -1,28 +1,28 @@ @@ -242,74 +242,74 @@ export default { font-weight: bold; border-radius: 5px; padding: 0.2rem 0.5rem; - white-space: nowrap; + white-space: nowrap; } .mention-suggestion { - color: rgba($color-black, 0.6); + color: rgba($color-black, 0.6); } .suggestion-list { - padding: 0.2rem; - border: 2px solid rgba($color-black, 0.1); - font-size: 0.8rem; - font-weight: bold; + padding: 0.2rem; + border: 2px solid rgba($color-black, 0.1); + font-size: 0.8rem; + font-weight: bold; - &__no-results { - padding: 0.2rem 0.5rem; - } + &__no-results { + padding: 0.2rem 0.5rem; + } - &__item { - border-radius: 5px; - padding: 0.2rem 0.5rem; - margin-bottom: 0.2rem; - cursor: pointer; + &__item { + border-radius: 5px; + padding: 0.2rem 0.5rem; + margin-bottom: 0.2rem; + cursor: pointer; - &:last-child { - margin-bottom: 0; - } + &:last-child { + margin-bottom: 0; + } - &.is-selected, - &:hover { - background-color: rgba($color-white, 0.2); - } + &.is-selected, + &:hover { + background-color: rgba($color-white, 0.2); + } - &.is-empty { - opacity: 0.5; - } - } + &.is-empty { + opacity: 0.5; + } + } } .tippy-tooltip.dark-theme { - background-color: $color-black; - padding: 0; - font-size: 1rem; - text-align: inherit; - color: $color-white; - border-radius: 5px; + background-color: $color-black; + padding: 0; + font-size: 1rem; + text-align: inherit; + color: $color-white; + border-radius: 5px; - .tippy-backdrop { - display: none; - } + .tippy-backdrop { + display: none; + } - .tippy-roundarrow { - fill: $color-black; - } + .tippy-roundarrow { + fill: $color-black; + } - .tippy-popper[x-placement^=top] & .tippy-arrow { - border-top-color: $color-black; - } + .tippy-popper[x-placement^=top] & .tippy-arrow { + border-top-color: $color-black; + } - .tippy-popper[x-placement^=bottom] & .tippy-arrow { - border-bottom-color: $color-black; - } + .tippy-popper[x-placement^=bottom] & .tippy-arrow { + border-bottom-color: $color-black; + } - .tippy-popper[x-placement^=left] & .tippy-arrow { - border-left-color: $color-black; - } + .tippy-popper[x-placement^=left] & .tippy-arrow { + border-left-color: $color-black; + } - .tippy-popper[x-placement^=right] & .tippy-arrow { - border-right-color: $color-black; - } + .tippy-popper[x-placement^=right] & .tippy-arrow { + border-right-color: $color-black; + } } diff --git a/examples/Components/Routes/TextAlign/Paragraph.js b/examples/Components/Routes/TextAlign/Paragraph.js index 926fa1fd..6185cca1 100644 --- a/examples/Components/Routes/TextAlign/Paragraph.js +++ b/examples/Components/Routes/TextAlign/Paragraph.js @@ -3,32 +3,32 @@ import { Node } from 'tiptap' export default class Paragraph extends Node { - get name() { - return 'paragraph' - } + get name() { + return 'paragraph' + } - get schema() { - return { - attrs: { - textAlign: { - default: 'left', - }, - }, - content: 'inline*', - group: 'block', - draggable: false, - parseDOM: [{ - tag: 'p', - getAttrs: node => ({ - textAlign: node.style.textAlign, - }), - }], - toDOM: node => ['p', { style: `text-align: ${node.attrs.textAlign}` }, 0], - } - } + get schema() { + return { + attrs: { + textAlign: { + default: 'left', + }, + }, + content: 'inline*', + group: 'block', + draggable: false, + parseDOM: [{ + tag: 'p', + getAttrs: node => ({ + textAlign: node.style.textAlign, + }), + }], + toDOM: node => ['p', { style: `text-align: ${node.attrs.textAlign}` }, 0], + } + } - commands({ type }) { - return attrs => setBlockType(type, attrs) - } + commands({ type }) { + return attrs => setBlockType(type, attrs) + } } diff --git a/examples/Components/Routes/TextAlign/index.vue b/examples/Components/Routes/TextAlign/index.vue index f9f64d49..81d12f75 100644 --- a/examples/Components/Routes/TextAlign/index.vue +++ b/examples/Components/Routes/TextAlign/index.vue @@ -1,93 +1,93 @@ diff --git a/examples/Components/Routes/TodoList/index.vue b/examples/Components/Routes/TodoList/index.vue index 297c18e1..149977d8 100644 --- a/examples/Components/Routes/TodoList/index.vue +++ b/examples/Components/Routes/TodoList/index.vue @@ -1,108 +1,108 @@ @@ -148,4 +148,4 @@ li[data-done="true"] .todo-checkbox { li[data-done="false"] { text-decoration: none; } - \ No newline at end of file + diff --git a/examples/Components/Subnavigation/index.vue b/examples/Components/Subnavigation/index.vue index ba93707e..3cc9cf5b 100644 --- a/examples/Components/Subnavigation/index.vue +++ b/examples/Components/Subnavigation/index.vue @@ -1,51 +1,51 @@ - \ No newline at end of file + diff --git a/examples/Components/Subnavigation/style.scss b/examples/Components/Subnavigation/style.scss index 32387211..403da309 100644 --- a/examples/Components/Subnavigation/style.scss +++ b/examples/Components/Subnavigation/style.scss @@ -2,35 +2,35 @@ .subnavigation { - padding: 0.5rem; - background-color: rgba($color-black, 0.9); - color: $color-white; - text-align: center; + padding: 0.5rem; + background-color: rgba($color-black, 0.9); + color: $color-white; + text-align: center; - @media (min-width: 600px) { - position: sticky; - top: 0; - z-index: 1000; - } + @media (min-width: 600px) { + position: sticky; + top: 0; + z-index: 1000; + } - &__link { - display: inline-block; - color: rgba($color-white, 0.5); - text-decoration: none; - font-weight: bold; - font-size: 0.9rem; - padding: 0.1rem 0.5rem; - border-radius: 3px; + &__link { + display: inline-block; + color: rgba($color-white, 0.5); + text-decoration: none; + font-weight: bold; + font-size: 0.9rem; + padding: 0.1rem 0.5rem; + border-radius: 3px; - &:hover { - color: $color-white; + &:hover { + color: $color-white; background-color: rgba($color-white, 0.1); } &.is-exact-active { - color: $color-white; + color: $color-white; background-color: rgba($color-white, 0.2); } - } + } -} \ No newline at end of file +} diff --git a/examples/assets/images/icons/align-center.svg b/examples/assets/images/icons/align-center.svg index 707ceb54..4f980d65 100644 --- a/examples/assets/images/icons/align-center.svg +++ b/examples/assets/images/icons/align-center.svg @@ -1 +1 @@ -paragraph-center-align-alternate \ No newline at end of file +paragraph-center-align-alternate diff --git a/examples/assets/images/icons/align-left.svg b/examples/assets/images/icons/align-left.svg index 5a679484..40665539 100644 --- a/examples/assets/images/icons/align-left.svg +++ b/examples/assets/images/icons/align-left.svg @@ -1 +1 @@ -paragraph-left-align-alternate \ No newline at end of file +paragraph-left-align-alternate diff --git a/examples/assets/images/icons/align-right.svg b/examples/assets/images/icons/align-right.svg index 8e70ec39..820e6fec 100644 --- a/examples/assets/images/icons/align-right.svg +++ b/examples/assets/images/icons/align-right.svg @@ -1 +1 @@ -paragraph-right-align-alternate \ No newline at end of file +paragraph-right-align-alternate diff --git a/examples/assets/images/icons/bold.svg b/examples/assets/images/icons/bold.svg index a981d296..985854b3 100644 --- a/examples/assets/images/icons/bold.svg +++ b/examples/assets/images/icons/bold.svg @@ -1 +1 @@ -text-bold \ No newline at end of file +text-bold diff --git a/examples/assets/images/icons/checklist.svg b/examples/assets/images/icons/checklist.svg index d4298911..20e8dc03 100644 --- a/examples/assets/images/icons/checklist.svg +++ b/examples/assets/images/icons/checklist.svg @@ -1 +1 @@ -checklist-alternate \ No newline at end of file +checklist-alternate diff --git a/examples/assets/images/icons/code.svg b/examples/assets/images/icons/code.svg index 3570e175..18b960bf 100644 --- a/examples/assets/images/icons/code.svg +++ b/examples/assets/images/icons/code.svg @@ -1 +1 @@ -angle-brackets \ No newline at end of file +angle-brackets diff --git a/examples/assets/images/icons/image.svg b/examples/assets/images/icons/image.svg index 8e1a8f4f..388c745f 100644 --- a/examples/assets/images/icons/image.svg +++ b/examples/assets/images/icons/image.svg @@ -1 +1 @@ -paginate-filter-picture-alternate \ No newline at end of file +paginate-filter-picture-alternate diff --git a/examples/assets/images/icons/italic.svg b/examples/assets/images/icons/italic.svg index a0773927..1916b10a 100644 --- a/examples/assets/images/icons/italic.svg +++ b/examples/assets/images/icons/italic.svg @@ -1 +1 @@ -text-italic \ No newline at end of file +text-italic diff --git a/examples/assets/images/icons/link.svg b/examples/assets/images/icons/link.svg index e02c680f..223282be 100644 --- a/examples/assets/images/icons/link.svg +++ b/examples/assets/images/icons/link.svg @@ -1 +1 @@ -hyperlink-2 \ No newline at end of file +hyperlink-2 diff --git a/examples/assets/images/icons/ol.svg b/examples/assets/images/icons/ol.svg index 90e8cb36..1e524f7f 100644 --- a/examples/assets/images/icons/ol.svg +++ b/examples/assets/images/icons/ol.svg @@ -1 +1 @@ -list-numbers \ No newline at end of file +list-numbers diff --git a/examples/assets/images/icons/paragraph.svg b/examples/assets/images/icons/paragraph.svg index b58ab10e..4c23b826 100644 --- a/examples/assets/images/icons/paragraph.svg +++ b/examples/assets/images/icons/paragraph.svg @@ -1 +1 @@ -paragraph \ No newline at end of file +paragraph diff --git a/examples/assets/images/icons/quote.svg b/examples/assets/images/icons/quote.svg index ca4b1533..64c4d3fb 100644 --- a/examples/assets/images/icons/quote.svg +++ b/examples/assets/images/icons/quote.svg @@ -1 +1 @@ -close-quote \ No newline at end of file +close-quote diff --git a/examples/assets/images/icons/redo.svg b/examples/assets/images/icons/redo.svg index 93fd762c..fbfc27a5 100644 --- a/examples/assets/images/icons/redo.svg +++ b/examples/assets/images/icons/redo.svg @@ -1 +1 @@ -redo \ No newline at end of file +redo diff --git a/examples/assets/images/icons/remove.svg b/examples/assets/images/icons/remove.svg index dad025f3..53397958 100644 --- a/examples/assets/images/icons/remove.svg +++ b/examples/assets/images/icons/remove.svg @@ -1 +1 @@ -delete-2-alternate \ No newline at end of file +delete-2-alternate diff --git a/examples/assets/images/icons/strike.svg b/examples/assets/images/icons/strike.svg index 4e67b52d..5bf1e886 100644 --- a/examples/assets/images/icons/strike.svg +++ b/examples/assets/images/icons/strike.svg @@ -1 +1 @@ -text-strike-through \ No newline at end of file +text-strike-through diff --git a/examples/assets/images/icons/ul.svg b/examples/assets/images/icons/ul.svg index af7a060a..ab754800 100644 --- a/examples/assets/images/icons/ul.svg +++ b/examples/assets/images/icons/ul.svg @@ -1 +1 @@ -list-bullets \ No newline at end of file +list-bullets diff --git a/examples/assets/images/icons/underline.svg b/examples/assets/images/icons/underline.svg index ac70c47a..26f85651 100644 --- a/examples/assets/images/icons/underline.svg +++ b/examples/assets/images/icons/underline.svg @@ -1 +1 @@ -text-underline \ No newline at end of file +text-underline diff --git a/examples/assets/images/icons/undo.svg b/examples/assets/images/icons/undo.svg index c834b4b1..833ab39d 100644 --- a/examples/assets/images/icons/undo.svg +++ b/examples/assets/images/icons/undo.svg @@ -1 +1 @@ -undo \ No newline at end of file +undo diff --git a/examples/assets/sass/editor.scss b/examples/assets/sass/editor.scss index a92b6336..2c7947e1 100644 --- a/examples/assets/sass/editor.scss +++ b/examples/assets/sass/editor.scss @@ -53,4 +53,4 @@ } } -} \ No newline at end of file +} diff --git a/examples/assets/sass/main.scss b/examples/assets/sass/main.scss index bdba5825..89a88025 100644 --- a/examples/assets/sass/main.scss +++ b/examples/assets/sass/main.scss @@ -1,39 +1,39 @@ @import "~variables"; * { - margin: 0; - padding: 0; - box-sizing: border-box; - text-size-adjust: 100%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - -webkit-touch-callout: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-rendering: optimizeLegibility; + margin: 0; + padding: 0; + box-sizing: border-box; + text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-touch-callout: none; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; - &:focus { - outline: none; - } + &:focus { + outline: none; + } } *::before, *::after { - box-sizing: border-box; + box-sizing: border-box; } html { - font-family: -apple-system, BlinkMacSystemFont, San Francisco, Roboto, Segoe UI, Helvetica Neue, sans-serif; - font-size: 18px; - color: $color-black; - line-height: 1.5; + font-family: -apple-system, BlinkMacSystemFont, San Francisco, Roboto, Segoe UI, Helvetica Neue, sans-serif; + font-size: 18px; + color: $color-black; + line-height: 1.5; } body { - margin: 0; + margin: 0; } a { - color: inherit; + color: inherit; } h1, @@ -44,11 +44,11 @@ ul, ol, pre, blockquote { - margin: 1rem 0; + margin: 1rem 0; &:first-child { margin-top: 0; - } + } &:last-child { margin-bottom: 0; @@ -58,22 +58,22 @@ blockquote { h1, h2, h3 { - line-height: 1.3; + line-height: 1.3; } .button { - font-weight: bold; - display: inline-flex; - background: transparent; - border: 0; - color: $color-black; - padding: 0.2rem 0.5rem; - margin-right: 0.2rem; - border-radius: 3px; - cursor: pointer; - background-color: rgba($color-black, 0.1); + font-weight: bold; + display: inline-flex; + background: transparent; + border: 0; + color: $color-black; + padding: 0.2rem 0.5rem; + margin-right: 0.2rem; + border-radius: 3px; + cursor: pointer; + background-color: rgba($color-black, 0.1); } @import "./editor"; @import "./menubar"; -@import "./menububble"; \ No newline at end of file +@import "./menububble"; diff --git a/examples/assets/sass/menubar.scss b/examples/assets/sass/menubar.scss index e7dea82b..3846f046 100644 --- a/examples/assets/sass/menubar.scss +++ b/examples/assets/sass/menubar.scss @@ -34,4 +34,4 @@ background-color: rgba($color-black, 0.1); } } -} \ No newline at end of file +} diff --git a/examples/assets/sass/menububble.scss b/examples/assets/sass/menububble.scss index 818c5d5e..e408465f 100644 --- a/examples/assets/sass/menububble.scss +++ b/examples/assets/sass/menububble.scss @@ -45,4 +45,4 @@ background: transparent; color: $color-white; } -} \ No newline at end of file +} diff --git a/examples/assets/sass/variables.scss b/examples/assets/sass/variables.scss index 7ca1d2c6..7d6283ac 100644 --- a/examples/assets/sass/variables.scss +++ b/examples/assets/sass/variables.scss @@ -1,2 +1,2 @@ $color-black: #000000; -$color-white: #ffffff; \ No newline at end of file +$color-white: #ffffff; diff --git a/examples/helpers/svg-sprite-loader.js b/examples/helpers/svg-sprite-loader.js index 63922383..db9be476 100644 --- a/examples/helpers/svg-sprite-loader.js +++ b/examples/helpers/svg-sprite-loader.js @@ -1,80 +1,80 @@ ;(function(window, document) { - 'use strict'; + 'use strict'; - var isSvg = document.createElementNS && document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ).createSVGRect; - var localStorage = 'localStorage' in window && window['localStorage'] !== null ? window.localStorage : false; + var isSvg = document.createElementNS && document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ).createSVGRect; + var localStorage = 'localStorage' in window && window['localStorage'] !== null ? window.localStorage : false; - function svgSpriteInjector(source, opts) { - var file; - opts = opts || {}; + function svgSpriteInjector(source, opts) { + var file; + opts = opts || {}; - if (source instanceof Node) { - file = source.getAttribute('data-svg-sprite'); - opts.revision = source.getAttribute('data-svg-sprite-revision') || opts.revision; - } else if (typeof source === 'string') { - file = source; - } + if (source instanceof Node) { + file = source.getAttribute('data-svg-sprite'); + opts.revision = source.getAttribute('data-svg-sprite-revision') || opts.revision; + } else if (typeof source === 'string') { + file = source; + } - if (isSvg) { - if (file) { - injector(file, opts); - } else { - console.error('svg-sprite-injector: undefined sprite filename!'); - } - } else { - console.error('svg-sprite-injector require ie9 or greater!'); - } - }; + if (isSvg) { + if (file) { + injector(file, opts); + } else { + console.error('svg-sprite-injector: undefined sprite filename!'); + } + } else { + console.error('svg-sprite-injector require ie9 or greater!'); + } + }; - function injector(filepath, opts) { - var name = 'injectedSVGSprite' + filepath, - revision = opts.revision, - request; + function injector(filepath, opts) { + var name = 'injectedSVGSprite' + filepath, + revision = opts.revision, + request; - // localStorage cache - if (revision !== undefined && localStorage && localStorage[name + 'Rev'] == revision) { - return injectOnLoad(localStorage[name]); - } + // localStorage cache + if (revision !== undefined && localStorage && localStorage[name + 'Rev'] == revision) { + return injectOnLoad(localStorage[name]); + } - // Async load - request = new XMLHttpRequest(); - request.open('GET', filepath, true); - request.onreadystatechange = function (e) { - var data; + // Async load + request = new XMLHttpRequest(); + request.open('GET', filepath, true); + request.onreadystatechange = function (e) { + var data; - if (request.readyState === 4 && request.status >= 200 && request.status < 400) { - injectOnLoad(data = request.responseText); - if (revision !== undefined && localStorage) { - localStorage[name] = data; - localStorage[name + 'Rev'] = revision; - } - } - }; - request.send(); - } + if (request.readyState === 4 && request.status >= 200 && request.status < 400) { + injectOnLoad(data = request.responseText); + if (revision !== undefined && localStorage) { + localStorage[name] = data; + localStorage[name + 'Rev'] = revision; + } + } + }; + request.send(); + } - function injectOnLoad(data) { - if (data) { - if (document.body) { - injectData(data); - } else { - document.addEventListener('DOMContentLoaded', injectData.bind(null, data)); - } - } - } + function injectOnLoad(data) { + if (data) { + if (document.body) { + injectData(data); + } else { + document.addEventListener('DOMContentLoaded', injectData.bind(null, data)); + } + } + } - function injectData(data) { - var body = document.body; - body.insertAdjacentHTML('afterbegin', data); - if (body.firstChild.tagName === 'svg') { - body.firstChild.style.display = 'none'; - } - } + function injectData(data) { + var body = document.body; + body.insertAdjacentHTML('afterbegin', data); + if (body.firstChild.tagName === 'svg') { + body.firstChild.style.display = 'none'; + } + } - if (typeof exports === 'object') { - module.exports = svgSpriteInjector; - } else { - window.svgSpriteInjector = svgSpriteInjector; - } + if (typeof exports === 'object') { + module.exports = svgSpriteInjector; + } else { + window.svgSpriteInjector = svgSpriteInjector; + } -} (window, document)); \ No newline at end of file +} (window, document)); diff --git a/examples/index.html b/examples/index.html index ce90f5c5..c3cb9ed8 100644 --- a/examples/index.html +++ b/examples/index.html @@ -1,16 +1,16 @@ - - - - tiptap - - - - - - - -
- - \ No newline at end of file + + + + tiptap + + + + + + + +
+ + diff --git a/netlify.toml b/netlify.toml index ff1c0508..b87b8d3d 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,4 +1,4 @@ [[redirects]] from = "/*" to = "/index.html" - status = 200 \ No newline at end of file + status = 200 diff --git a/packages/tiptap-commands/README.md b/packages/tiptap-commands/README.md index 5171645a..a93b2840 100644 --- a/packages/tiptap-commands/README.md +++ b/packages/tiptap-commands/README.md @@ -4,4 +4,4 @@ This is a collection of commands for [tiptap](https://www.npmjs.com/package/tipt [![](https://img.shields.io/npm/v/tiptap-commands.svg?label=version)](https://www.npmjs.com/package/tiptap-commands) [![](https://img.shields.io/npm/dm/tiptap-commands.svg)](https://npmcharts.com/compare/tiptap-commands?minimal=true) [![](https://img.shields.io/npm/l/tiptap-commands.svg)](https://www.npmjs.com/package/tiptap-commands) -[![](http://img.badgesize.io/https://unpkg.com/tiptap-commands/dist/commands.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap-commands) \ No newline at end of file +[![](http://img.badgesize.io/https://unpkg.com/tiptap-commands/dist/commands.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap-commands) diff --git a/packages/tiptap-commands/src/commands/insertText.js b/packages/tiptap-commands/src/commands/insertText.js index ee7d4ae7..dd8a62a2 100644 --- a/packages/tiptap-commands/src/commands/insertText.js +++ b/packages/tiptap-commands/src/commands/insertText.js @@ -1,10 +1,10 @@ export default function (text = '') { - return (state, dispatch) => { - const { $from } = state.selection - const { pos } = $from.pos + return (state, dispatch) => { + const { $from } = state.selection + const { pos } = $from.pos - dispatch(state.tr.insertText(text, pos)) + dispatch(state.tr.insertText(text, pos)) - return true - } + return true + } } diff --git a/packages/tiptap-commands/src/commands/markInputRule.js b/packages/tiptap-commands/src/commands/markInputRule.js index 379e987d..066760e6 100644 --- a/packages/tiptap-commands/src/commands/markInputRule.js +++ b/packages/tiptap-commands/src/commands/markInputRule.js @@ -1,26 +1,26 @@ import { InputRule } from 'prosemirror-inputrules' export default function (regexp, markType, getAttrs) { - return new InputRule(regexp, (state, match, start, end) => { - const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs + return new InputRule(regexp, (state, match, start, end) => { + const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs const { tr } = state let markEnd = end - if (match[1]) { - const startSpaces = match[0].search(/\S/) - const textStart = start + match[0].indexOf(match[1]) - const textEnd = textStart + match[1].length - if (textEnd < end) { - tr.delete(textEnd, end) - } - if (textStart > start) { - tr.delete(start + startSpaces, textStart) - } - markEnd = start + startSpaces + match[1].length - } + if (match[1]) { + const startSpaces = match[0].search(/\S/) + const textStart = start + match[0].indexOf(match[1]) + const textEnd = textStart + match[1].length + if (textEnd < end) { + tr.delete(textEnd, end) + } + if (textStart > start) { + tr.delete(start + startSpaces, textStart) + } + markEnd = start + startSpaces + match[1].length + } - tr.addMark(start, markEnd, markType.create(attrs)) - tr.removeStoredMark(markType) // Do not continue with mark. - return tr - }) + tr.addMark(start, markEnd, markType.create(attrs)) + tr.removeStoredMark(markType) // Do not continue with mark. + return tr + }) } diff --git a/packages/tiptap-commands/src/commands/removeMark.js b/packages/tiptap-commands/src/commands/removeMark.js index 180d46f2..6483d274 100644 --- a/packages/tiptap-commands/src/commands/removeMark.js +++ b/packages/tiptap-commands/src/commands/removeMark.js @@ -1,6 +1,6 @@ export default function (type) { return (state, dispatch) => { - const { from, to } = state.selection - return dispatch(state.tr.removeMark(from, to, type)) - } + const { from, to } = state.selection + return dispatch(state.tr.removeMark(from, to, type)) + } } diff --git a/packages/tiptap-commands/src/commands/replaceText.js b/packages/tiptap-commands/src/commands/replaceText.js index 5555ae65..ecc6b86a 100644 --- a/packages/tiptap-commands/src/commands/replaceText.js +++ b/packages/tiptap-commands/src/commands/replaceText.js @@ -1,16 +1,16 @@ export default function (range, type, attrs = {}) { - return (state, dispatch) => { - const { $from } = state.selection - const index = $from.index() + return (state, dispatch) => { + const { $from } = state.selection + const index = $from.index() - if (!$from.parent.canReplaceWith(index, index, type)) { - return false - } + if (!$from.parent.canReplaceWith(index, index, type)) { + return false + } - if (dispatch) { - dispatch(state.tr.replaceWith(range.from, range.to, type.create(attrs))) - } + if (dispatch) { + dispatch(state.tr.replaceWith(range.from, range.to, type.create(attrs))) + } - return true - } + return true + } } diff --git a/packages/tiptap-commands/src/commands/setInlineBlockType.js b/packages/tiptap-commands/src/commands/setInlineBlockType.js index 4030f2be..b784c083 100644 --- a/packages/tiptap-commands/src/commands/setInlineBlockType.js +++ b/packages/tiptap-commands/src/commands/setInlineBlockType.js @@ -1,16 +1,16 @@ export default function (type, attrs = {}) { - return (state, dispatch) => { - const { $from } = state.selection - const index = $from.index() + return (state, dispatch) => { + const { $from } = state.selection + const index = $from.index() - if (!$from.parent.canReplaceWith(index, index, type)) { - return false - } + if (!$from.parent.canReplaceWith(index, index, type)) { + return false + } - if (dispatch) { - dispatch(state.tr.replaceSelectionWith(type.create(attrs))) - } + if (dispatch) { + dispatch(state.tr.replaceSelectionWith(type.create(attrs))) + } - return true - } + return true + } } diff --git a/packages/tiptap-commands/src/commands/splitToDefaultListItem.js b/packages/tiptap-commands/src/commands/splitToDefaultListItem.js index 9d209eab..7f413a9c 100644 --- a/packages/tiptap-commands/src/commands/splitToDefaultListItem.js +++ b/packages/tiptap-commands/src/commands/splitToDefaultListItem.js @@ -16,13 +16,13 @@ index = $pos.index(d) if (node.type.spec.isolating) return false let rest = node.content.cutByIndex(index, node.childCount) const after = (typesAfter && typesAfter[i]) || node - if (after != node) rest = rest.replaceChild(0, after.type.create(after.attrs)) + if (after != node) rest = rest.replaceChild(0, after.type.create(after.attrs)) - /* Change starts from here */ - // if (!node.canReplace(index + 1, node.childCount) || !after.type.validContent(rest)) + /* Change starts from here */ + // if (!node.canReplace(index + 1, node.childCount) || !after.type.validContent(rest)) // return false if (!node.canReplace(index + 1, node.childCount)) return false - /* Change ends here */ + /* Change ends here */ } const index = $pos.indexAfter(base) const baseType = typesAfter && typesAfter[0] @@ -43,7 +43,7 @@ export default function splitListItem(itemType) { // list item should be split. Otherwise, bail out and let next // command handle lifting. if ($from.depth == 2 || $from.node(-3).type != itemType - || $from.index(-2) != $from.node(-2).childCount - 1) return false + || $from.index(-2) != $from.node(-2).childCount - 1) return false if (dispatch) { let wrap = Fragment.empty; const @@ -52,23 +52,23 @@ keepItem = $from.index(-1) > 0 // from the outer list item to the parent node of the cursor for (let d = $from.depth - (keepItem ? 1 : 2); d >= $from.depth - 3; d--) wrap = Fragment.from($from.node(d).copy(wrap)) // Add a second list item with an empty default start node - wrap = wrap.append(Fragment.from(itemType.createAndFill())) + wrap = wrap.append(Fragment.from(itemType.createAndFill())) const tr = state.tr.replace($from.before(keepItem ? null : -1), $from.after(-3), new Slice(wrap, keepItem ? 3 : 2, 2)) tr.setSelection(state.selection.constructor.near(tr.doc.resolve($from.pos + (keepItem ? 3 : 2)))) dispatch(tr.scrollIntoView()) } return true } - const nextType = $to.pos == $from.end() ? grandParent.contentMatchAt($from.indexAfter(-1)).defaultType : null - const tr = state.tr.delete($from.pos, $to.pos) + const nextType = $to.pos == $from.end() ? grandParent.contentMatchAt($from.indexAfter(-1)).defaultType : null + const tr = state.tr.delete($from.pos, $to.pos) - /* Change starts from here */ - // let types = nextType && [null, {type: nextType}] + /* Change starts from here */ + // let types = nextType && [null, {type: nextType}] let types = nextType && [{ type: itemType }, { type: nextType }] if (!types) types = [{ type: itemType }, null] - /* Change ends here */ + /* Change ends here */ - if (!canSplit(tr.doc, $from.pos, 2, types)) return false + if (!canSplit(tr.doc, $from.pos, 2, types)) return false if (dispatch) dispatch(tr.split($from.pos, 2, [{ type: state.schema.nodes.todo_item, attrs: { done: false } }]).scrollIntoView()) return true } diff --git a/packages/tiptap-commands/src/commands/toggleBlockType.js b/packages/tiptap-commands/src/commands/toggleBlockType.js index 971a4f4b..6cdd2dc0 100644 --- a/packages/tiptap-commands/src/commands/toggleBlockType.js +++ b/packages/tiptap-commands/src/commands/toggleBlockType.js @@ -2,13 +2,13 @@ import { setBlockType } from 'prosemirror-commands' import { nodeIsActive } from 'tiptap-utils' export default function (type, toggletype, attrs = {}) { - return (state, dispatch, view) => { - const isActive = nodeIsActive(state, type, attrs) + return (state, dispatch, view) => { + const isActive = nodeIsActive(state, type, attrs) - if (isActive) { - return setBlockType(toggletype)(state, dispatch, view) - } + if (isActive) { + return setBlockType(toggletype)(state, dispatch, view) + } - return setBlockType(type, attrs)(state, dispatch, view) - } + return setBlockType(type, attrs)(state, dispatch, view) + } } diff --git a/packages/tiptap-commands/src/commands/toggleWrap.js b/packages/tiptap-commands/src/commands/toggleWrap.js index e8d0c942..bb71f5f3 100644 --- a/packages/tiptap-commands/src/commands/toggleWrap.js +++ b/packages/tiptap-commands/src/commands/toggleWrap.js @@ -2,13 +2,13 @@ import { wrapIn, lift } from 'prosemirror-commands' import { nodeIsActive } from 'tiptap-utils' export default function (type) { - return (state, dispatch, view) => { - const isActive = nodeIsActive(state, type) + return (state, dispatch, view) => { + const isActive = nodeIsActive(state, type) - if (isActive) { - return lift(state, dispatch) - } + if (isActive) { + return lift(state, dispatch) + } - return wrapIn(type)(state, dispatch, view) - } + return wrapIn(type)(state, dispatch, view) + } } diff --git a/packages/tiptap-commands/src/commands/updateMark.js b/packages/tiptap-commands/src/commands/updateMark.js index 77902aa1..eb6c4a16 100644 --- a/packages/tiptap-commands/src/commands/updateMark.js +++ b/packages/tiptap-commands/src/commands/updateMark.js @@ -1,6 +1,6 @@ export default function (type, attrs) { return (state, dispatch) => { - const { from, to } = state.selection - return dispatch(state.tr.addMark(from, to, type.create(attrs))) - } + const { from, to } = state.selection + return dispatch(state.tr.addMark(from, to, type.create(attrs))) + } } diff --git a/packages/tiptap-commands/src/index.js b/packages/tiptap-commands/src/index.js index 0701c096..fb319aee 100644 --- a/packages/tiptap-commands/src/index.js +++ b/packages/tiptap-commands/src/index.js @@ -1,41 +1,41 @@ import { - chainCommands, - deleteSelection, - joinBackward, - selectNodeBackward, - joinForward, - selectNodeForward, - joinUp, - joinDown, - lift, - newlineInCode, - exitCode, - createParagraphNear, - liftEmptyBlock, - splitBlock, - splitBlockKeepMarks, - selectParentNode, - selectAll, - wrapIn, - setBlockType, - toggleMark, - autoJoin, - baseKeymap, - pcBaseKeymap, - macBaseKeymap, + chainCommands, + deleteSelection, + joinBackward, + selectNodeBackward, + joinForward, + selectNodeForward, + joinUp, + joinDown, + lift, + newlineInCode, + exitCode, + createParagraphNear, + liftEmptyBlock, + splitBlock, + splitBlockKeepMarks, + selectParentNode, + selectAll, + wrapIn, + setBlockType, + toggleMark, + autoJoin, + baseKeymap, + pcBaseKeymap, + macBaseKeymap, } from 'prosemirror-commands' import { - addListNodes, - wrapInList, - splitListItem, - liftListItem, - sinkListItem, + addListNodes, + wrapInList, + splitListItem, + liftListItem, + sinkListItem, } from 'prosemirror-schema-list' import { - wrappingInputRule, - textblockTypeInputRule, + wrappingInputRule, + textblockTypeInputRule, } from 'prosemirror-inputrules' import insertText from './commands/insertText' @@ -50,52 +50,52 @@ import toggleWrap from './commands/toggleWrap' import updateMark from './commands/updateMark' export { - // prosemirror-commands - chainCommands, - deleteSelection, - joinBackward, - selectNodeBackward, - joinForward, - selectNodeForward, - joinUp, - joinDown, - lift, - newlineInCode, - exitCode, - createParagraphNear, - liftEmptyBlock, - splitBlock, - splitBlockKeepMarks, - selectParentNode, - selectAll, - wrapIn, - setBlockType, - toggleMark, - autoJoin, - baseKeymap, - pcBaseKeymap, - macBaseKeymap, + // prosemirror-commands + chainCommands, + deleteSelection, + joinBackward, + selectNodeBackward, + joinForward, + selectNodeForward, + joinUp, + joinDown, + lift, + newlineInCode, + exitCode, + createParagraphNear, + liftEmptyBlock, + splitBlock, + splitBlockKeepMarks, + selectParentNode, + selectAll, + wrapIn, + setBlockType, + toggleMark, + autoJoin, + baseKeymap, + pcBaseKeymap, + macBaseKeymap, - // prosemirror-schema-list - addListNodes, - wrapInList, - splitListItem, - liftListItem, - sinkListItem, + // prosemirror-schema-list + addListNodes, + wrapInList, + splitListItem, + liftListItem, + sinkListItem, - // prosemirror-inputrules - wrappingInputRule, - textblockTypeInputRule, + // prosemirror-inputrules + wrappingInputRule, + textblockTypeInputRule, - // custom - insertText, - markInputRule, - removeMark, - replaceText, - setInlineBlockType, - splitToDefaultListItem, - toggleBlockType, - toggleList, - toggleWrap, - updateMark, + // custom + insertText, + markInputRule, + removeMark, + replaceText, + setInlineBlockType, + splitToDefaultListItem, + toggleBlockType, + toggleList, + toggleWrap, + updateMark, } diff --git a/packages/tiptap-extensions/README.md b/packages/tiptap-extensions/README.md index 1e81951b..ed1e766c 100644 --- a/packages/tiptap-extensions/README.md +++ b/packages/tiptap-extensions/README.md @@ -4,4 +4,4 @@ This is a collection of extensions for [tiptap](https://www.npmjs.com/package/ti [![](https://img.shields.io/npm/v/tiptap-extensions.svg?label=version)](https://www.npmjs.com/package/tiptap-extensions) [![](https://img.shields.io/npm/dm/tiptap-extensions.svg)](https://npmcharts.com/compare/tiptap-extensions?minimal=true) [![](https://img.shields.io/npm/l/tiptap-extensions.svg)](https://www.npmjs.com/package/tiptap-extensions) -[![](http://img.badgesize.io/https://unpkg.com/tiptap-extensions/dist/extensions.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap-extensions) \ No newline at end of file +[![](http://img.badgesize.io/https://unpkg.com/tiptap-extensions/dist/extensions.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap-extensions) diff --git a/packages/tiptap-extensions/src/extensions/History.js b/packages/tiptap-extensions/src/extensions/History.js index 19a88d8a..4257da78 100644 --- a/packages/tiptap-extensions/src/extensions/History.js +++ b/packages/tiptap-extensions/src/extensions/History.js @@ -3,35 +3,35 @@ import { history, undo, redo } from 'prosemirror-history' export default class History extends Extension { - get name() { - return 'history' - } + get name() { + return 'history' + } - keys() { - const isMac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false - const keymap = { - 'Mod-z': undo, - 'Shift-Mod-z': redo, - } + keys() { + const isMac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false + const keymap = { + 'Mod-z': undo, + 'Shift-Mod-z': redo, + } - if (!isMac) { - keymap['Mod-y'] = redo - } + if (!isMac) { + keymap['Mod-y'] = redo + } - return keymap - } + return keymap + } - get plugins() { - return [ - history(), - ] - } + get plugins() { + return [ + history(), + ] + } - commands() { - return { - undo: () => undo, - redo: () => redo, - } - } + commands() { + return { + undo: () => undo, + redo: () => redo, + } + } } diff --git a/packages/tiptap-extensions/src/extensions/Placeholder.js b/packages/tiptap-extensions/src/extensions/Placeholder.js index ccef669c..39f107ed 100644 --- a/packages/tiptap-extensions/src/extensions/Placeholder.js +++ b/packages/tiptap-extensions/src/extensions/Placeholder.js @@ -3,40 +3,40 @@ import { Decoration, DecorationSet } from 'prosemirror-view' export default class Placeholder extends Extension { - get name() { - return 'placeholder' - } + get name() { + return 'placeholder' + } - get defaultOptions() { - return { - emptyNodeClass: 'is-empty', - } - } + get defaultOptions() { + return { + emptyNodeClass: 'is-empty', + } + } - get plugins() { - return [ - new Plugin({ - props: { - decorations: ({ doc }) => { - const decorations = [] - const completelyEmpty = doc.textContent === '' && doc.childCount <= 1 && doc.content.size <= 2 + get plugins() { + return [ + new Plugin({ + props: { + decorations: ({ doc }) => { + const decorations = [] + const completelyEmpty = doc.textContent === '' && doc.childCount <= 1 && doc.content.size <= 2 - doc.descendants((node, pos) => { - if (!completelyEmpty) { - return - } + doc.descendants((node, pos) => { + if (!completelyEmpty) { + return + } - const decoration = Decoration.node(pos, pos + node.nodeSize, { - class: this.options.emptyNodeClass, - }) - decorations.push(decoration) - }) + const decoration = Decoration.node(pos, pos + node.nodeSize, { + class: this.options.emptyNodeClass, + }) + decorations.push(decoration) + }) - return DecorationSet.create(doc, decorations) - }, - }, - }), - ] - } + return DecorationSet.create(doc, decorations) + }, + }, + }), + ] + } } diff --git a/packages/tiptap-extensions/src/marks/Bold.js b/packages/tiptap-extensions/src/marks/Bold.js index 50afd017..275426db 100644 --- a/packages/tiptap-extensions/src/marks/Bold.js +++ b/packages/tiptap-extensions/src/marks/Bold.js @@ -3,43 +3,43 @@ import { toggleMark, markInputRule } from 'tiptap-commands' export default class Bold extends Mark { - get name() { - return 'bold' - } + get name() { + return 'bold' + } - get schema() { - return { - parseDOM: [ - { - tag: 'strong', - }, - { - tag: 'b', - getAttrs: node => node.style.fontWeight !== 'normal' && null, - }, - { - style: 'font-weight', - getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null, - }, - ], - toDOM: () => ['strong', 0], - } - } + get schema() { + return { + parseDOM: [ + { + tag: 'strong', + }, + { + tag: 'b', + getAttrs: node => node.style.fontWeight !== 'normal' && null, + }, + { + style: 'font-weight', + getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null, + }, + ], + toDOM: () => ['strong', 0], + } + } - keys({ type }) { - return { - 'Mod-b': toggleMark(type), - } - } + keys({ type }) { + return { + 'Mod-b': toggleMark(type), + } + } - commands({ type }) { - return () => toggleMark(type) - } + commands({ type }) { + return () => toggleMark(type) + } - inputRules({ type }) { - return [ - markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type), - ] - } + inputRules({ type }) { + return [ + markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/marks/Code.js b/packages/tiptap-extensions/src/marks/Code.js index a4a513b0..7d7dfa98 100644 --- a/packages/tiptap-extensions/src/marks/Code.js +++ b/packages/tiptap-extensions/src/marks/Code.js @@ -3,33 +3,33 @@ import { toggleMark, markInputRule } from 'tiptap-commands' export default class Code extends Mark { - get name() { - return 'code' - } + get name() { + return 'code' + } - get schema() { - return { - parseDOM: [ - { tag: 'code' }, - ], - toDOM: () => ['code', 0], - } - } + get schema() { + return { + parseDOM: [ + { tag: 'code' }, + ], + toDOM: () => ['code', 0], + } + } - keys({ type }) { - return { - 'Mod-`': toggleMark(type), - } - } + keys({ type }) { + return { + 'Mod-`': toggleMark(type), + } + } - commands({ type }) { - return () => toggleMark(type) - } + commands({ type }) { + return () => toggleMark(type) + } - inputRules({ type }) { - return [ - markInputRule(/(?:`)([^`]+)(?:`)$/, type), - ] - } + inputRules({ type }) { + return [ + markInputRule(/(?:`)([^`]+)(?:`)$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/marks/Italic.js b/packages/tiptap-extensions/src/marks/Italic.js index 6294a191..a69a731c 100644 --- a/packages/tiptap-extensions/src/marks/Italic.js +++ b/packages/tiptap-extensions/src/marks/Italic.js @@ -3,35 +3,35 @@ import { toggleMark, markInputRule } from 'tiptap-commands' export default class Italic extends Mark { - get name() { - return 'italic' - } + get name() { + return 'italic' + } - get schema() { - return { - parseDOM: [ - { tag: 'i' }, - { tag: 'em' }, - { style: 'font-style=italic' }, - ], - toDOM: () => ['em', 0], - } - } + get schema() { + return { + parseDOM: [ + { tag: 'i' }, + { tag: 'em' }, + { style: 'font-style=italic' }, + ], + toDOM: () => ['em', 0], + } + } - keys({ type }) { - return { - 'Mod-i': toggleMark(type), - } - } + keys({ type }) { + return { + 'Mod-i': toggleMark(type), + } + } - commands({ type }) { - return () => toggleMark(type) - } + commands({ type }) { + return () => toggleMark(type) + } - inputRules({ type }) { - return [ - markInputRule(/(?:^|[^*_])(?:\*|_)([^*_]+)(?:\*|_)$/, type), - ] - } + inputRules({ type }) { + return [ + markInputRule(/(?:^|[^*_])(?:\*|_)([^*_]+)(?:\*|_)$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/marks/Link.js b/packages/tiptap-extensions/src/marks/Link.js index ceacd6ec..49ab891b 100644 --- a/packages/tiptap-extensions/src/marks/Link.js +++ b/packages/tiptap-extensions/src/marks/Link.js @@ -3,41 +3,41 @@ import { updateMark, removeMark } from 'tiptap-commands' export default class Link extends Mark { - get name() { - return 'link' - } + get name() { + return 'link' + } - get schema() { - return { - attrs: { - href: { - default: null, - }, - }, - inclusive: false, - parseDOM: [ - { - tag: 'a[href]', - getAttrs: dom => ({ - href: dom.getAttribute('href'), - }), - }, - ], - toDOM: node => ['a', { - ...node.attrs, - rel: 'noopener noreferrer nofollow', - }, 0], - } - } + get schema() { + return { + attrs: { + href: { + default: null, + }, + }, + inclusive: false, + parseDOM: [ + { + tag: 'a[href]', + getAttrs: dom => ({ + href: dom.getAttribute('href'), + }), + }, + ], + toDOM: node => ['a', { + ...node.attrs, + rel: 'noopener noreferrer nofollow', + }, 0], + } + } - commands({ type }) { - return attrs => { - if (attrs.href) { - return updateMark(type, attrs) - } + commands({ type }) { + return attrs => { + if (attrs.href) { + return updateMark(type, attrs) + } - return removeMark(type) - } - } + return removeMark(type) + } + } } diff --git a/packages/tiptap-extensions/src/marks/Strike.js b/packages/tiptap-extensions/src/marks/Strike.js index 784efa58..79fd0f46 100644 --- a/packages/tiptap-extensions/src/marks/Strike.js +++ b/packages/tiptap-extensions/src/marks/Strike.js @@ -3,45 +3,45 @@ import { toggleMark, markInputRule } from 'tiptap-commands' export default class Strike extends Mark { - get name() { - return 'strike' - } + get name() { + return 'strike' + } - get schema() { - return { - parseDOM: [ - { - tag: 's', - }, - { - tag: 'del', - }, - { - tag: 'strike', - }, - { - style: 'text-decoration', - getAttrs: value => value === 'line-through', - }, - ], - toDOM: () => ['s', 0], - } - } + get schema() { + return { + parseDOM: [ + { + tag: 's', + }, + { + tag: 'del', + }, + { + tag: 'strike', + }, + { + style: 'text-decoration', + getAttrs: value => value === 'line-through', + }, + ], + toDOM: () => ['s', 0], + } + } - keys({ type }) { - return { - 'Mod-d': toggleMark(type), - } - } + keys({ type }) { + return { + 'Mod-d': toggleMark(type), + } + } - commands({ type }) { - return () => toggleMark(type) - } + commands({ type }) { + return () => toggleMark(type) + } - inputRules({ type }) { - return [ - markInputRule(/~([^~]+)~$/, type), - ] - } + inputRules({ type }) { + return [ + markInputRule(/~([^~]+)~$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/marks/Underline.js b/packages/tiptap-extensions/src/marks/Underline.js index aacfadf8..b49539a9 100644 --- a/packages/tiptap-extensions/src/marks/Underline.js +++ b/packages/tiptap-extensions/src/marks/Underline.js @@ -3,33 +3,33 @@ import { toggleMark } from 'tiptap-commands' export default class Underline extends Mark { - get name() { - return 'underline' - } + get name() { + return 'underline' + } - get schema() { - return { - parseDOM: [ - { - tag: 'u', - }, - { - style: 'text-decoration', - getAttrs: value => value === 'underline', - }, - ], - toDOM: () => ['u', 0], - } - } + get schema() { + return { + parseDOM: [ + { + tag: 'u', + }, + { + style: 'text-decoration', + getAttrs: value => value === 'underline', + }, + ], + toDOM: () => ['u', 0], + } + } - keys({ type }) { - return { - 'Mod-u': toggleMark(type), - } - } + keys({ type }) { + return { + 'Mod-u': toggleMark(type), + } + } - commands({ type }) { - return () => toggleMark(type) - } + commands({ type }) { + return () => toggleMark(type) + } } diff --git a/packages/tiptap-extensions/src/nodes/Blockquote.js b/packages/tiptap-extensions/src/nodes/Blockquote.js index 868155b6..93a5eb72 100644 --- a/packages/tiptap-extensions/src/nodes/Blockquote.js +++ b/packages/tiptap-extensions/src/nodes/Blockquote.js @@ -3,37 +3,37 @@ import { wrappingInputRule, toggleWrap } from 'tiptap-commands' export default class Blockquote extends Node { - get name() { - return 'blockquote' - } + get name() { + return 'blockquote' + } - get schema() { - return { - content: 'block*', - group: 'block', - defining: true, - draggable: false, - parseDOM: [ - { tag: 'blockquote' }, - ], - toDOM: () => ['blockquote', 0], - } - } + get schema() { + return { + content: 'block*', + group: 'block', + defining: true, + draggable: false, + parseDOM: [ + { tag: 'blockquote' }, + ], + toDOM: () => ['blockquote', 0], + } + } - commands({ type, schema }) { - return () => toggleWrap(type, schema.nodes.paragraph) - } + commands({ type, schema }) { + return () => toggleWrap(type, schema.nodes.paragraph) + } - keys({ type }) { - return { - 'Ctrl->': toggleWrap(type), - } - } + keys({ type }) { + return { + 'Ctrl->': toggleWrap(type), + } + } - inputRules({ type }) { - return [ - wrappingInputRule(/^\s*>\s$/, type), - ] - } + inputRules({ type }) { + return [ + wrappingInputRule(/^\s*>\s$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/nodes/BulletList.js b/packages/tiptap-extensions/src/nodes/BulletList.js index 6ff0bfa5..732998ac 100644 --- a/packages/tiptap-extensions/src/nodes/BulletList.js +++ b/packages/tiptap-extensions/src/nodes/BulletList.js @@ -3,35 +3,35 @@ import { wrappingInputRule, toggleList } from 'tiptap-commands' export default class Bullet extends Node { - get name() { - return 'bullet_list' - } + get name() { + return 'bullet_list' + } - get schema() { - return { - content: 'list_item+', - group: 'block', - parseDOM: [ - { tag: 'ul' }, - ], - toDOM: () => ['ul', 0], - } - } + get schema() { + return { + content: 'list_item+', + group: 'block', + parseDOM: [ + { tag: 'ul' }, + ], + toDOM: () => ['ul', 0], + } + } - commands({ type, schema }) { - return () => toggleList(type, schema.nodes.list_item) - } + commands({ type, schema }) { + return () => toggleList(type, schema.nodes.list_item) + } - keys({ type, schema }) { - return { - 'Shift-Ctrl-8': toggleList(type, schema.nodes.list_item), - } - } + keys({ type, schema }) { + return { + 'Shift-Ctrl-8': toggleList(type, schema.nodes.list_item), + } + } - inputRules({ type }) { - return [ - wrappingInputRule(/^\s*([-+*])\s$/, type), - ] - } + inputRules({ type }) { + return [ + wrappingInputRule(/^\s*([-+*])\s$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/nodes/CodeBlock.js b/packages/tiptap-extensions/src/nodes/CodeBlock.js index ca7260e7..c764540e 100644 --- a/packages/tiptap-extensions/src/nodes/CodeBlock.js +++ b/packages/tiptap-extensions/src/nodes/CodeBlock.js @@ -3,39 +3,39 @@ import { toggleBlockType, setBlockType, textblockTypeInputRule } from 'tiptap-co export default class CodeBlock extends Node { - get name() { - return 'code_block' - } + get name() { + return 'code_block' + } - get schema() { - return { - content: 'text*', - marks: '', - group: 'block', - code: true, - defining: true, - draggable: false, - parseDOM: [ - { tag: 'pre', preserveWhitespace: 'full' }, - ], - toDOM: () => ['pre', ['code', 0]], - } - } + get schema() { + return { + content: 'text*', + marks: '', + group: 'block', + code: true, + defining: true, + draggable: false, + parseDOM: [ + { tag: 'pre', preserveWhitespace: 'full' }, + ], + toDOM: () => ['pre', ['code', 0]], + } + } - commands({ type, schema }) { - return () => toggleBlockType(type, schema.nodes.paragraph) - } + commands({ type, schema }) { + return () => toggleBlockType(type, schema.nodes.paragraph) + } - keys({ type }) { - return { - 'Shift-Ctrl-\\': setBlockType(type), - } - } + keys({ type }) { + return { + 'Shift-Ctrl-\\': setBlockType(type), + } + } - inputRules({ type }) { - return [ - textblockTypeInputRule(/^```$/, type), - ] - } + inputRules({ type }) { + return [ + textblockTypeInputRule(/^```$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/nodes/CodeBlockHighlight.js b/packages/tiptap-extensions/src/nodes/CodeBlockHighlight.js index 68b40eec..76c690a0 100644 --- a/packages/tiptap-extensions/src/nodes/CodeBlockHighlight.js +++ b/packages/tiptap-extensions/src/nodes/CodeBlockHighlight.js @@ -5,139 +5,139 @@ import { findBlockNodes } from 'prosemirror-utils' import low from 'lowlight/lib/core' function getDecorations(doc) { - const decorations = [] + const decorations = [] - const blocks = findBlockNodes(doc) - .filter(item => item.node.type.name === 'code_block') + const blocks = findBlockNodes(doc) + .filter(item => item.node.type.name === 'code_block') - const flatten = list => list.reduce( - (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [], - ) + const flatten = list => list.reduce( + (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), [], + ) - function parseNodes(nodes, className = []) { - return nodes.map(node => { + function parseNodes(nodes, className = []) { + return nodes.map(node => { - const classes = [ - ...className, - ...node.properties ? node.properties.className : [], - ] + const classes = [ + ...className, + ...node.properties ? node.properties.className : [], + ] - if (node.children) { - return parseNodes(node.children, classes) - } + if (node.children) { + return parseNodes(node.children, classes) + } - return { - text: node.value, - classes, - } - }) - } + return { + text: node.value, + classes, + } + }) + } - blocks.forEach(block => { - let startPos = block.pos + 1 - const nodes = low.highlightAuto(block.node.textContent).value + blocks.forEach(block => { + let startPos = block.pos + 1 + const nodes = low.highlightAuto(block.node.textContent).value - flatten(parseNodes(nodes)) - .map(node => { - const from = startPos - const to = from + node.text.length + flatten(parseNodes(nodes)) + .map(node => { + const from = startPos + const to = from + node.text.length - startPos = to + startPos = to - return { - ...node, - from, - to, - } - }) - .forEach(node => { - const decoration = Decoration.inline(node.from, node.to, { - class: node.classes.join(' '), - }) - decorations.push(decoration) - }) - }) + return { + ...node, + from, + to, + } + }) + .forEach(node => { + const decoration = Decoration.inline(node.from, node.to, { + class: node.classes.join(' '), + }) + decorations.push(decoration) + }) + }) - return DecorationSet.create(doc, decorations) + return DecorationSet.create(doc, decorations) } export default class CodeBlockHighlight extends Node { - constructor(options = {}) { - super(options) - try { - Object.entries(this.options.languages).forEach(([name, mapping]) => { - low.registerLanguage(name, mapping) - }) - } catch (err) { - throw new Error('Invalid syntax highlight definitions: define at least one highlight.js language mapping') - } - } + constructor(options = {}) { + super(options) + try { + Object.entries(this.options.languages).forEach(([name, mapping]) => { + low.registerLanguage(name, mapping) + }) + } catch (err) { + throw new Error('Invalid syntax highlight definitions: define at least one highlight.js language mapping') + } + } - get defaultOptions() { - return { - languages: {}, - } - } + get defaultOptions() { + return { + languages: {}, + } + } - get name() { - return 'code_block' - } + get name() { + return 'code_block' + } - get schema() { - return { - content: 'text*', - marks: '', - group: 'block', - code: true, - defining: true, - draggable: false, - parseDOM: [ - { tag: 'pre', preserveWhitespace: 'full' }, - ], - toDOM: () => ['pre', ['code', 0]], - } - } + get schema() { + return { + content: 'text*', + marks: '', + group: 'block', + code: true, + defining: true, + draggable: false, + parseDOM: [ + { tag: 'pre', preserveWhitespace: 'full' }, + ], + toDOM: () => ['pre', ['code', 0]], + } + } - commands({ type, schema }) { - return () => toggleBlockType(type, schema.nodes.paragraph) - } + commands({ type, schema }) { + return () => toggleBlockType(type, schema.nodes.paragraph) + } - keys({ type }) { - return { - 'Shift-Ctrl-\\': setBlockType(type), - } - } + keys({ type }) { + return { + 'Shift-Ctrl-\\': setBlockType(type), + } + } - inputRules({ type }) { - return [ - textblockTypeInputRule(/^```$/, type), - ] - } + inputRules({ type }) { + return [ + textblockTypeInputRule(/^```$/, type), + ] + } - get plugins() { - return [ - new Plugin({ - state: { - init(_, { doc }) { - return getDecorations(doc) - }, - apply(tr, set) { - // TODO: find way to cache decorations - // see: https://discuss.prosemirror.net/t/how-to-update-multiple-inline-decorations-on-node-change/1493 - if (tr.docChanged) { - return getDecorations(tr.doc) - } - return set.map(tr.mapping, tr.doc) - }, - }, - props: { - decorations(state) { - return this.getState(state) - }, - }, - }), - ] - } + get plugins() { + return [ + new Plugin({ + state: { + init(_, { doc }) { + return getDecorations(doc) + }, + apply(tr, set) { + // TODO: find way to cache decorations + // see: https://discuss.prosemirror.net/t/how-to-update-multiple-inline-decorations-on-node-change/1493 + if (tr.docChanged) { + return getDecorations(tr.doc) + } + return set.map(tr.mapping, tr.doc) + }, + }, + props: { + decorations(state) { + return this.getState(state) + }, + }, + }), + ] + } } diff --git a/packages/tiptap-extensions/src/nodes/HardBreak.js b/packages/tiptap-extensions/src/nodes/HardBreak.js index 6bdff2fa..61d35974 100644 --- a/packages/tiptap-extensions/src/nodes/HardBreak.js +++ b/packages/tiptap-extensions/src/nodes/HardBreak.js @@ -3,31 +3,31 @@ import { chainCommands, exitCode } from 'tiptap-commands' export default class HardBreak extends Node { - get name() { - return 'hard_break' - } + get name() { + return 'hard_break' + } - get schema() { - return { - inline: true, - group: 'inline', - selectable: false, - parseDOM: [ - { tag: 'br' }, - ], - toDOM: () => ['br'], - } - } + get schema() { + return { + inline: true, + group: 'inline', + selectable: false, + parseDOM: [ + { tag: 'br' }, + ], + toDOM: () => ['br'], + } + } - keys({ type }) { - const command = chainCommands(exitCode, (state, dispatch) => { - dispatch(state.tr.replaceSelectionWith(type.create()).scrollIntoView()) - return true - }) - return { - 'Mod-Enter': command, - 'Shift-Enter': command, - } - } + keys({ type }) { + const command = chainCommands(exitCode, (state, dispatch) => { + dispatch(state.tr.replaceSelectionWith(type.create()).scrollIntoView()) + return true + }) + return { + 'Mod-Enter': command, + 'Shift-Enter': command, + } + } } diff --git a/packages/tiptap-extensions/src/nodes/Heading.js b/packages/tiptap-extensions/src/nodes/Heading.js index 914d1d9a..3197048e 100644 --- a/packages/tiptap-extensions/src/nodes/Heading.js +++ b/packages/tiptap-extensions/src/nodes/Heading.js @@ -3,55 +3,55 @@ import { setBlockType, textblockTypeInputRule, toggleBlockType } from 'tiptap-co export default class Heading extends Node { - get name() { - return 'heading' - } + get name() { + return 'heading' + } - get defaultOptions() { - return { - levels: [1, 2, 3, 4, 5, 6], - } - } + get defaultOptions() { + return { + levels: [1, 2, 3, 4, 5, 6], + } + } - get schema() { - return { - attrs: { - level: { - default: 1, - }, - }, - content: 'inline*', - group: 'block', - defining: true, - draggable: false, - parseDOM: this.options.levels - .map(level => ({ - tag: `h${level}`, - attrs: { level }, - })), - toDOM: node => [`h${node.attrs.level}`, 0], - } - } + get schema() { + return { + attrs: { + level: { + default: 1, + }, + }, + content: 'inline*', + group: 'block', + defining: true, + draggable: false, + parseDOM: this.options.levels + .map(level => ({ + tag: `h${level}`, + attrs: { level }, + })), + toDOM: node => [`h${node.attrs.level}`, 0], + } + } - commands({ type, schema }) { - return attrs => toggleBlockType(type, schema.nodes.paragraph, attrs) - } + commands({ type, schema }) { + return attrs => toggleBlockType(type, schema.nodes.paragraph, attrs) + } - keys({ type }) { - return this.options.levels.reduce((items, level) => ({ - ...items, - ...{ - [`Shift-Ctrl-${level}`]: setBlockType(type, { level }), - }, - }), {}) - } + keys({ type }) { + return this.options.levels.reduce((items, level) => ({ + ...items, + ...{ + [`Shift-Ctrl-${level}`]: setBlockType(type, { level }), + }, + }), {}) + } - inputRules({ type }) { - return this.options.levels.map(level => textblockTypeInputRule( - new RegExp(`^(#{1,${level}})\\s$`), - type, - match => ({ level }), - )) - } + inputRules({ type }) { + return this.options.levels.map(level => textblockTypeInputRule( + new RegExp(`^(#{1,${level}})\\s$`), + type, + match => ({ level }), + )) + } } diff --git a/packages/tiptap-extensions/src/nodes/Image.js b/packages/tiptap-extensions/src/nodes/Image.js index b8017ebd..7a23ecd9 100644 --- a/packages/tiptap-extensions/src/nodes/Image.js +++ b/packages/tiptap-extensions/src/nodes/Image.js @@ -2,92 +2,92 @@ import { Node, Plugin } from 'tiptap' export default class Image extends Node { - get name() { - return 'image' - } + get name() { + return 'image' + } - get schema() { - return { - inline: true, - attrs: { - src: {}, - alt: { - default: null, - }, - title: { - default: null, - }, - }, - group: 'inline', - draggable: true, - parseDOM: [ - { - tag: 'img[src]', - getAttrs: dom => ({ - src: dom.getAttribute('src'), - title: dom.getAttribute('title'), - alt: dom.getAttribute('alt'), - }), - }, - ], - toDOM: node => ['img', node.attrs], - } - } + get schema() { + return { + inline: true, + attrs: { + src: {}, + alt: { + default: null, + }, + title: { + default: null, + }, + }, + group: 'inline', + draggable: true, + parseDOM: [ + { + tag: 'img[src]', + getAttrs: dom => ({ + src: dom.getAttribute('src'), + title: dom.getAttribute('title'), + alt: dom.getAttribute('alt'), + }), + }, + ], + toDOM: node => ['img', node.attrs], + } + } - commands({ type }) { - return attrs => (state, dispatch) => { - const { selection } = state - const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos - const node = type.create(attrs) - const transaction = state.tr.insert(position, node) - dispatch(transaction) - } - } + commands({ type }) { + return attrs => (state, dispatch) => { + const { selection } = state + const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos + const node = type.create(attrs) + const transaction = state.tr.insert(position, node) + dispatch(transaction) + } + } - get plugins() { - return [ - new Plugin({ - props: { - handleDOMEvents: { - drop(view, event) { - const hasFiles = event.dataTransfer - && event.dataTransfer.files - && event.dataTransfer.files.length + get plugins() { + return [ + new Plugin({ + props: { + handleDOMEvents: { + drop(view, event) { + const hasFiles = event.dataTransfer + && event.dataTransfer.files + && event.dataTransfer.files.length - if (!hasFiles) { - return - } + if (!hasFiles) { + return + } - const images = Array - .from(event.dataTransfer.files) - .filter(file => (/image/i).test(file.type)) + const images = Array + .from(event.dataTransfer.files) + .filter(file => (/image/i).test(file.type)) - if (images.length === 0) { - return - } + if (images.length === 0) { + return + } - event.preventDefault() + event.preventDefault() - const { schema } = view.state - const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY }) + const { schema } = view.state + const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY }) - images.forEach(image => { - const reader = new FileReader() + images.forEach(image => { + const reader = new FileReader() - reader.onload = readerEvent => { - const node = schema.nodes.image.create({ - src: readerEvent.target.result, - }) - const transaction = view.state.tr.insert(coordinates.pos, node) - view.dispatch(transaction) - } - reader.readAsDataURL(image) - }) - }, - }, - }, - }), - ] - } + reader.onload = readerEvent => { + const node = schema.nodes.image.create({ + src: readerEvent.target.result, + }) + const transaction = view.state.tr.insert(coordinates.pos, node) + view.dispatch(transaction) + } + reader.readAsDataURL(image) + }) + }, + }, + }, + }), + ] + } } diff --git a/packages/tiptap-extensions/src/nodes/ListItem.js b/packages/tiptap-extensions/src/nodes/ListItem.js index bcbfb01b..a5c18984 100644 --- a/packages/tiptap-extensions/src/nodes/ListItem.js +++ b/packages/tiptap-extensions/src/nodes/ListItem.js @@ -3,28 +3,28 @@ import { splitListItem, liftListItem, sinkListItem } from 'tiptap-commands' export default class ListItem extends Node { - get name() { - return 'list_item' - } + get name() { + return 'list_item' + } - get schema() { - return { - content: 'paragraph block*', - defining: true, - draggable: false, - parseDOM: [ - { tag: 'li' }, - ], - toDOM: () => ['li', 0], - } - } + get schema() { + return { + content: 'paragraph block*', + defining: true, + draggable: false, + parseDOM: [ + { tag: 'li' }, + ], + toDOM: () => ['li', 0], + } + } - keys({ type }) { - return { - Enter: splitListItem(type), - Tab: sinkListItem(type), - 'Shift-Tab': liftListItem(type), - } - } + keys({ type }) { + return { + Enter: splitListItem(type), + Tab: sinkListItem(type), + 'Shift-Tab': liftListItem(type), + } + } } diff --git a/packages/tiptap-extensions/src/nodes/Mention.js b/packages/tiptap-extensions/src/nodes/Mention.js index 7c8d6a74..e458a0f5 100644 --- a/packages/tiptap-extensions/src/nodes/Mention.js +++ b/packages/tiptap-extensions/src/nodes/Mention.js @@ -4,68 +4,68 @@ import SuggestionsPlugin from '../plugins/Suggestions' export default class Mention extends Node { - get name() { - return 'mention' - } + get name() { + return 'mention' + } - get defaultOptions() { - return { - matcher: { - char: '@', - allowSpaces: false, - startOfLine: false, - }, - mentionClass: 'mention', - suggestionClass: 'mention-suggestion', - } - } + get defaultOptions() { + return { + matcher: { + char: '@', + allowSpaces: false, + startOfLine: false, + }, + mentionClass: 'mention', + suggestionClass: 'mention-suggestion', + } + } - get schema() { - return { - attrs: { - id: {}, - label: {}, - }, - group: 'inline', - inline: true, - selectable: false, - atom: true, - toDOM: node => [ - 'span', - { - class: this.options.mentionClass, - 'data-mention-id': node.attrs.id, - }, - `${this.options.matcher.char}${node.attrs.label}`, - ], - parseDOM: [ - { - tag: 'span[data-mention-id]', - getAttrs: dom => { - const id = dom.getAttribute('data-mention-id') - const label = dom.innerText.split(this.options.matcher.char).join('') - return { id, label } - }, - }, - ], - } - } + get schema() { + return { + attrs: { + id: {}, + label: {}, + }, + group: 'inline', + inline: true, + selectable: false, + atom: true, + toDOM: node => [ + 'span', + { + class: this.options.mentionClass, + 'data-mention-id': node.attrs.id, + }, + `${this.options.matcher.char}${node.attrs.label}`, + ], + parseDOM: [ + { + tag: 'span[data-mention-id]', + getAttrs: dom => { + const id = dom.getAttribute('data-mention-id') + const label = dom.innerText.split(this.options.matcher.char).join('') + return { id, label } + }, + }, + ], + } + } - get plugins() { - return [ - SuggestionsPlugin({ - command: ({ range, attrs, schema }) => replaceText(range, schema.nodes.mention, attrs), - appendText: ' ', - matcher: this.options.matcher, - items: this.options.items, - onEnter: this.options.onEnter, - onChange: this.options.onChange, - onExit: this.options.onExit, - onKeyDown: this.options.onKeyDown, - onFilter: this.options.onFilter, - suggestionClass: this.options.suggestionClass, - }), - ] - } + get plugins() { + return [ + SuggestionsPlugin({ + command: ({ range, attrs, schema }) => replaceText(range, schema.nodes.mention, attrs), + appendText: ' ', + matcher: this.options.matcher, + items: this.options.items, + onEnter: this.options.onEnter, + onChange: this.options.onChange, + onExit: this.options.onExit, + onKeyDown: this.options.onKeyDown, + onFilter: this.options.onFilter, + suggestionClass: this.options.suggestionClass, + }), + ] + } } diff --git a/packages/tiptap-extensions/src/nodes/OrderedList.js b/packages/tiptap-extensions/src/nodes/OrderedList.js index deada26b..dbeee045 100644 --- a/packages/tiptap-extensions/src/nodes/OrderedList.js +++ b/packages/tiptap-extensions/src/nodes/OrderedList.js @@ -3,50 +3,50 @@ import { wrappingInputRule, toggleList } from 'tiptap-commands' export default class OrderedList extends Node { - get name() { - return 'ordered_list' - } + get name() { + return 'ordered_list' + } - get schema() { - return { - attrs: { - order: { - default: 1, - }, - }, - content: 'list_item+', - group: 'block', - parseDOM: [ - { - tag: 'ol', - getAttrs: dom => ({ - order: dom.hasAttribute('start') ? +dom.getAttribute('start') : 1, - }), - }, - ], - toDOM: node => (node.attrs.order === 1 ? ['ol', 0] : ['ol', { start: node.attrs.order }, 0]), - } - } + get schema() { + return { + attrs: { + order: { + default: 1, + }, + }, + content: 'list_item+', + group: 'block', + parseDOM: [ + { + tag: 'ol', + getAttrs: dom => ({ + order: dom.hasAttribute('start') ? +dom.getAttribute('start') : 1, + }), + }, + ], + toDOM: node => (node.attrs.order === 1 ? ['ol', 0] : ['ol', { start: node.attrs.order }, 0]), + } + } - commands({ type, schema }) { - return () => toggleList(type, schema.nodes.list_item) - } + commands({ type, schema }) { + return () => toggleList(type, schema.nodes.list_item) + } - keys({ type, schema }) { - return { - 'Shift-Ctrl-9': toggleList(type, schema.nodes.list_item), - } - } + keys({ type, schema }) { + return { + 'Shift-Ctrl-9': toggleList(type, schema.nodes.list_item), + } + } - inputRules({ type }) { - return [ - wrappingInputRule( - /^(\d+)\.\s$/, - type, - match => ({ order: +match[1] }), - (match, node) => node.childCount + node.attrs.order === +match[1], - ), - ] - } + inputRules({ type }) { + return [ + wrappingInputRule( + /^(\d+)\.\s$/, + type, + match => ({ order: +match[1] }), + (match, node) => node.childCount + node.attrs.order === +match[1], + ), + ] + } } diff --git a/packages/tiptap-extensions/src/nodes/TodoItem.js b/packages/tiptap-extensions/src/nodes/TodoItem.js index 8cff4d4c..9ec77820 100644 --- a/packages/tiptap-extensions/src/nodes/TodoItem.js +++ b/packages/tiptap-extensions/src/nodes/TodoItem.js @@ -3,64 +3,64 @@ import { splitToDefaultListItem, liftListItem } from 'tiptap-commands' export default class TodoItem extends Node { - get name() { - return 'todo_item' - } + get name() { + return 'todo_item' + } - get view() { - return { - props: ['node', 'updateAttrs', 'editable'], - methods: { - onChange() { - this.updateAttrs({ - done: !this.node.attrs.done, - }) - }, - }, - template: ` -
  • - -
    -
  • - `, - } - } + get view() { + return { + props: ['node', 'updateAttrs', 'editable'], + methods: { + onChange() { + this.updateAttrs({ + done: !this.node.attrs.done, + }) + }, + }, + template: ` +
  • + +
    +
  • + `, + } + } - get schema() { - return { - attrs: { - done: { - default: false, - }, - }, - draggable: false, - content: 'paragraph', - toDOM(node) { - const { done } = node.attrs + get schema() { + return { + attrs: { + done: { + default: false, + }, + }, + draggable: false, + content: 'paragraph', + toDOM(node) { + const { done } = node.attrs - return ['li', { - 'data-type': 'todo_item', - 'data-done': done.toString(), - }, - ['span', { class: 'todo-checkbox', contenteditable: 'false' }], - ['div', { class: 'todo-content' }, 0], - ] - }, - parseDOM: [{ - priority: 51, - tag: '[data-type="todo_item"]', - getAttrs: dom => ({ - done: dom.getAttribute('data-done') === 'true', - }), - }], - } - } + return ['li', { + 'data-type': 'todo_item', + 'data-done': done.toString(), + }, + ['span', { class: 'todo-checkbox', contenteditable: 'false' }], + ['div', { class: 'todo-content' }, 0], + ] + }, + parseDOM: [{ + priority: 51, + tag: '[data-type="todo_item"]', + getAttrs: dom => ({ + done: dom.getAttribute('data-done') === 'true', + }), + }], + } + } - keys({ type }) { - return { - Enter: splitToDefaultListItem(type), - 'Shift-Tab': liftListItem(type), - } - } + keys({ type }) { + return { + Enter: splitToDefaultListItem(type), + 'Shift-Tab': liftListItem(type), + } + } } diff --git a/packages/tiptap-extensions/src/nodes/TodoList.js b/packages/tiptap-extensions/src/nodes/TodoList.js index f844f591..fd749b86 100644 --- a/packages/tiptap-extensions/src/nodes/TodoList.js +++ b/packages/tiptap-extensions/src/nodes/TodoList.js @@ -3,30 +3,30 @@ import { wrapInList, wrappingInputRule } from 'tiptap-commands' export default class TodoList extends Node { - get name() { - return 'todo_list' - } + get name() { + return 'todo_list' + } - get schema() { - return { - group: 'block', - content: 'todo_item+', - toDOM: () => ['ul', { 'data-type': 'todo_list' }, 0], - parseDOM: [{ - priority: 51, - tag: '[data-type="todo_list"]', - }], - } - } + get schema() { + return { + group: 'block', + content: 'todo_item+', + toDOM: () => ['ul', { 'data-type': 'todo_list' }, 0], + parseDOM: [{ + priority: 51, + tag: '[data-type="todo_list"]', + }], + } + } - commands({ type }) { - return () => wrapInList(type) - } + commands({ type }) { + return () => wrapInList(type) + } - inputRules({ type }) { - return [ - wrappingInputRule(/^\s*(\[ \])\s$/, type), - ] - } + inputRules({ type }) { + return [ + wrappingInputRule(/^\s*(\[ \])\s$/, type), + ] + } } diff --git a/packages/tiptap-extensions/src/plugins/Suggestions.js b/packages/tiptap-extensions/src/plugins/Suggestions.js index b6a48e65..7ab6af28 100644 --- a/packages/tiptap-extensions/src/plugins/Suggestions.js +++ b/packages/tiptap-extensions/src/plugins/Suggestions.js @@ -4,239 +4,239 @@ import { insertText } from 'tiptap-commands' // Create a matcher that matches when a specific character is typed. Useful for @mentions and #tags. function triggerCharacter({ - char = '@', - allowSpaces = false, - startOfLine = false, + char = '@', + allowSpaces = false, + startOfLine = false, }) { - return $position => { - // Matching expressions used for later - const suffix = new RegExp(`\\s${char}$`) - const prefix = startOfLine ? '^' : '' - const regexp = allowSpaces - ? new RegExp(`${prefix}${char}.*?(?=\\s${char}|$)`, 'gm') - : new RegExp(`${prefix}(?:^)?${char}[^\\s${char}]*`, 'gm') + return $position => { + // Matching expressions used for later + const suffix = new RegExp(`\\s${char}$`) + const prefix = startOfLine ? '^' : '' + const regexp = allowSpaces + ? new RegExp(`${prefix}${char}.*?(?=\\s${char}|$)`, 'gm') + : new RegExp(`${prefix}(?:^)?${char}[^\\s${char}]*`, 'gm') - // Lookup the boundaries of the current node - const textFrom = $position.before() - const textTo = $position.end() - const text = $position.doc.textBetween(textFrom, textTo, '\0', '\0') + // Lookup the boundaries of the current node + const textFrom = $position.before() + const textTo = $position.end() + const text = $position.doc.textBetween(textFrom, textTo, '\0', '\0') - let match = regexp.exec(text) - let position - while (match !== null) { - // JavaScript doesn't have lookbehinds; this hacks a check that first character is " " - // or the line beginning - const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index) + let match = regexp.exec(text) + let position + while (match !== null) { + // JavaScript doesn't have lookbehinds; this hacks a check that first character is " " + // or the line beginning + const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index) - if (/^[\s\0]?$/.test(matchPrefix)) { - // The absolute position of the match in the document - const from = match.index + $position.start() - let to = from + match[0].length + if (/^[\s\0]?$/.test(matchPrefix)) { + // The absolute position of the match in the document + const from = match.index + $position.start() + let to = from + match[0].length - // Edge case handling; if spaces are allowed and we're directly in between - // two triggers - if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) { - match[0] += ' ' - to += 1 - } + // Edge case handling; if spaces are allowed and we're directly in between + // two triggers + if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) { + match[0] += ' ' + to += 1 + } - // If the $position is located within the matched substring, return that range - if (from < $position.pos && to >= $position.pos) { - position = { - range: { - from, - to, - }, - query: match[0].slice(char.length), - text: match[0], - } - } - } + // If the $position is located within the matched substring, return that range + if (from < $position.pos && to >= $position.pos) { + position = { + range: { + from, + to, + }, + query: match[0].slice(char.length), + text: match[0], + } + } + } match = regexp.exec(text) - } + } return position - } + } } export default function SuggestionsPlugin({ - matcher = { - char: '@', - allowSpaces: false, - startOfLine: false, - }, - appendText = null, - suggestionClass = 'suggestion', - command = () => false, - items = [], - onEnter = () => false, - onChange = () => false, - onExit = () => false, - onKeyDown = () => false, - onFilter = (searchItems, query) => { - if (!query) { - return searchItems - } + matcher = { + char: '@', + allowSpaces: false, + startOfLine: false, + }, + appendText = null, + suggestionClass = 'suggestion', + command = () => false, + items = [], + onEnter = () => false, + onChange = () => false, + onExit = () => false, + onKeyDown = () => false, + onFilter = (searchItems, query) => { + if (!query) { + return searchItems + } - return searchItems - .filter(item => JSON.stringify(item).toLowerCase().includes(query.toLowerCase())) - }, + return searchItems + .filter(item => JSON.stringify(item).toLowerCase().includes(query.toLowerCase())) + }, }) { - return new Plugin({ - key: new PluginKey('suggestions'), + return new Plugin({ + key: new PluginKey('suggestions'), - view() { - return { - update: (view, prevState) => { - const prev = this.key.getState(prevState) - const next = this.key.getState(view.state) + view() { + return { + update: (view, prevState) => { + const prev = this.key.getState(prevState) + const next = this.key.getState(view.state) - // See how the state changed - const moved = prev.active && next.active && prev.range.from !== next.range.from - const started = !prev.active && next.active - const stopped = prev.active && !next.active - const changed = !started && !stopped && prev.query !== next.query - const handleStart = started || moved - const handleChange = changed && !moved - const handleExit = stopped || moved + // See how the state changed + const moved = prev.active && next.active && prev.range.from !== next.range.from + const started = !prev.active && next.active + const stopped = prev.active && !next.active + const changed = !started && !stopped && prev.query !== next.query + const handleStart = started || moved + const handleChange = changed && !moved + const handleExit = stopped || moved - // Cancel when suggestion isn't active - if (!handleStart && !handleChange && !handleExit) { - return - } + // Cancel when suggestion isn't active + if (!handleStart && !handleChange && !handleExit) { + return + } - const state = handleExit ? prev : next - const decorationNode = document.querySelector(`[data-decoration-id="${state.decorationId}"]`) + const state = handleExit ? prev : next + const decorationNode = document.querySelector(`[data-decoration-id="${state.decorationId}"]`) - // build a virtual node for popper.js or tippy.js - // this can be used for building popups without a DOM node - const virtualNode = decorationNode ? { - getBoundingClientRect() { - return decorationNode.getBoundingClientRect() - }, - clientWidth: decorationNode.clientWidth, - clientHeight: decorationNode.clientHeight, - } : null + // build a virtual node for popper.js or tippy.js + // this can be used for building popups without a DOM node + const virtualNode = decorationNode ? { + getBoundingClientRect() { + return decorationNode.getBoundingClientRect() + }, + clientWidth: decorationNode.clientWidth, + clientHeight: decorationNode.clientHeight, + } : null - const props = { - view, - range: state.range, - query: state.query, - text: state.text, - decorationNode, - virtualNode, - items: onFilter(Array.isArray(items) ? items : items(), state.query), - command: ({ range, attrs }) => { - command({ - range, - attrs, - schema: view.state.schema, - })(view.state, view.dispatch, view) + const props = { + view, + range: state.range, + query: state.query, + text: state.text, + decorationNode, + virtualNode, + items: onFilter(Array.isArray(items) ? items : items(), state.query), + command: ({ range, attrs }) => { + command({ + range, + attrs, + schema: view.state.schema, + })(view.state, view.dispatch, view) - if (appendText) { - insertText(appendText)(view.state, view.dispatch, view) - } - }, - } + if (appendText) { + insertText(appendText)(view.state, view.dispatch, view) + } + }, + } - // Trigger the hooks when necessary - if (handleExit) { - onExit(props) - } + // Trigger the hooks when necessary + if (handleExit) { + onExit(props) + } - if (handleChange) { - onChange(props) - } + if (handleChange) { + onChange(props) + } - if (handleStart) { - onEnter(props) - } - }, - } - }, + if (handleStart) { + onEnter(props) + } + }, + } + }, - state: { + state: { - // Initialize the plugin's internal state. - init() { - return { - active: false, - range: {}, - query: null, - text: null, - } - }, + // Initialize the plugin's internal state. + init() { + return { + active: false, + range: {}, + query: null, + text: null, + } + }, - // Apply changes to the plugin state from a view transaction. - apply(tr, prev) { - const { selection } = tr - const next = { ...prev } + // Apply changes to the plugin state from a view transaction. + apply(tr, prev) { + const { selection } = tr + const next = { ...prev } - // We can only be suggesting if there is no selection - if (selection.from === selection.to) { - // Reset active state if we just left the previous suggestion range - if (selection.from < prev.range.from || selection.from > prev.range.to) { - next.active = false - } + // We can only be suggesting if there is no selection + if (selection.from === selection.to) { + // Reset active state if we just left the previous suggestion range + if (selection.from < prev.range.from || selection.from > prev.range.to) { + next.active = false + } - // Try to match against where our cursor currently is - const $position = selection.$from - const match = triggerCharacter(matcher)($position) - const decorationId = (Math.random() + 1).toString(36).substr(2, 5) + // Try to match against where our cursor currently is + const $position = selection.$from + const match = triggerCharacter(matcher)($position) + const decorationId = (Math.random() + 1).toString(36).substr(2, 5) - // If we found a match, update the current state to show it - if (match) { - next.active = true - next.decorationId = prev.decorationId ? prev.decorationId : decorationId - next.range = match.range - next.query = match.query - next.text = match.text - } else { - next.active = false - } - } else { - next.active = false - } + // If we found a match, update the current state to show it + if (match) { + next.active = true + next.decorationId = prev.decorationId ? prev.decorationId : decorationId + next.range = match.range + next.query = match.query + next.text = match.text + } else { + next.active = false + } + } else { + next.active = false + } - // Make sure to empty the range if suggestion is inactive - if (!next.active) { - next.decorationId = null - next.range = {} - next.query = null - next.text = null - } + // Make sure to empty the range if suggestion is inactive + if (!next.active) { + next.decorationId = null + next.range = {} + next.query = null + next.text = null + } - return next - }, - }, + return next + }, + }, - props: { + props: { - // Call the keydown hook if suggestion is active. - handleKeyDown(view, event) { - const { active, range } = this.getState(view.state) + // Call the keydown hook if suggestion is active. + handleKeyDown(view, event) { + const { active, range } = this.getState(view.state) - if (!active) return false + if (!active) return false - return onKeyDown({ view, event, range }) - }, + return onKeyDown({ view, event, range }) + }, - // Setup decorator on the currently active suggestion. - decorations(editorState) { - const { active, range, decorationId } = this.getState(editorState) + // Setup decorator on the currently active suggestion. + decorations(editorState) { + const { active, range, decorationId } = this.getState(editorState) - if (!active) return null + if (!active) return null - return DecorationSet.create(editorState.doc, [ - Decoration.inline(range.from, range.to, { - nodeName: 'span', - class: suggestionClass, - 'data-decoration-id': decorationId, - }), - ]) - }, - }, - }) + return DecorationSet.create(editorState.doc, [ + Decoration.inline(range.from, range.to, { + nodeName: 'span', + class: suggestionClass, + 'data-decoration-id': decorationId, + }), + ]) + }, + }, + }) } diff --git a/packages/tiptap-utils/README.md b/packages/tiptap-utils/README.md index 138c768f..2950bf21 100644 --- a/packages/tiptap-utils/README.md +++ b/packages/tiptap-utils/README.md @@ -4,4 +4,4 @@ This is a collection of utility functions for [tiptap](https://www.npmjs.com/pac [![](https://img.shields.io/npm/v/tiptap-utils.svg?label=version)](https://www.npmjs.com/package/tiptap-utils) [![](https://img.shields.io/npm/dm/tiptap-utils.svg)](https://npmcharts.com/compare/tiptap-utils?minimal=true) [![](https://img.shields.io/npm/l/tiptap-utils.svg)](https://www.npmjs.com/package/tiptap-utils) -[![](http://img.badgesize.io/https://unpkg.com/tiptap-utils/dist/utils.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap-utils) \ No newline at end of file +[![](http://img.badgesize.io/https://unpkg.com/tiptap-utils/dist/utils.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap-utils) diff --git a/packages/tiptap-utils/src/utils/getMarkAttrs.js b/packages/tiptap-utils/src/utils/getMarkAttrs.js index 27ee1244..a4aaf53c 100644 --- a/packages/tiptap-utils/src/utils/getMarkAttrs.js +++ b/packages/tiptap-utils/src/utils/getMarkAttrs.js @@ -1,16 +1,16 @@ export default function (state, type) { - const { from, to } = state.selection - let marks = [] + const { from, to } = state.selection + let marks = [] - state.doc.nodesBetween(from, to, node => { - marks = [...marks, ...node.marks] - }) + state.doc.nodesBetween(from, to, node => { + marks = [...marks, ...node.marks] + }) - const mark = marks.find(markItem => markItem.type.name === type.name) + const mark = marks.find(markItem => markItem.type.name === type.name) - if (mark) { - return mark.attrs - } + if (mark) { + return mark.attrs + } - return {} + return {} } diff --git a/packages/tiptap-utils/src/utils/markIsActive.js b/packages/tiptap-utils/src/utils/markIsActive.js index 0f4c0fbc..951f7101 100644 --- a/packages/tiptap-utils/src/utils/markIsActive.js +++ b/packages/tiptap-utils/src/utils/markIsActive.js @@ -1,14 +1,14 @@ export default function (state, type) { - const { - from, - $from, - to, - empty, - } = state.selection + const { + from, + $from, + to, + empty, + } = state.selection - if (empty) { - return !!type.isInSet(state.storedMarks || $from.marks()) - } + if (empty) { + return !!type.isInSet(state.storedMarks || $from.marks()) + } - return !!state.doc.rangeHasMark(from, to, type) + return !!state.doc.rangeHasMark(from, to, type) } diff --git a/packages/tiptap-utils/src/utils/nodeIsActive.js b/packages/tiptap-utils/src/utils/nodeIsActive.js index a7d5c8d5..53f2037c 100644 --- a/packages/tiptap-utils/src/utils/nodeIsActive.js +++ b/packages/tiptap-utils/src/utils/nodeIsActive.js @@ -1,12 +1,12 @@ import { findParentNode } from 'prosemirror-utils' export default function (state, type, attrs = {}) { - const predicate = node => node.type === type - const parent = findParentNode(predicate)(state.selection) + const predicate = node => node.type === type + const parent = findParentNode(predicate)(state.selection) - if (!Object.keys(attrs).length || !parent) { - return !!parent - } + if (!Object.keys(attrs).length || !parent) { + return !!parent + } - return parent.node.hasMarkup(type, attrs) + return parent.node.hasMarkup(type, attrs) } diff --git a/packages/tiptap/README.md b/packages/tiptap/README.md index 1b3ab9be..0ef7f889 100644 --- a/packages/tiptap/README.md +++ b/packages/tiptap/README.md @@ -4,4 +4,4 @@ This is the core package of [tiptap](https://www.npmjs.com/package/tiptap). [![](https://img.shields.io/npm/v/tiptap.svg?label=version)](https://www.npmjs.com/package/tiptap) [![](https://img.shields.io/npm/dm/tiptap.svg)](https://npmcharts.com/compare/tiptap?minimal=true) [![](https://img.shields.io/npm/l/tiptap.svg)](https://www.npmjs.com/package/tiptap) -[![](http://img.badgesize.io/https://unpkg.com/tiptap/dist/tiptap.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap) \ No newline at end of file +[![](http://img.badgesize.io/https://unpkg.com/tiptap/dist/tiptap.min.js?compression=gzip&label=size&colorB=000000)](https://www.npmjs.com/package/tiptap) diff --git a/packages/tiptap/src/Components/EditorContent.js b/packages/tiptap/src/Components/EditorContent.js index 24276e44..0da13483 100644 --- a/packages/tiptap/src/Components/EditorContent.js +++ b/packages/tiptap/src/Components/EditorContent.js @@ -1,21 +1,21 @@ export default { - props: { - editor: { - default: null, - type: Object, - }, - }, - watch: { - 'editor.element': { - immediate: true, - handler(element) { - if (element) { - this.$nextTick(() => this.$el.append(element.firstChild)) - } - }, - }, - }, - render(createElement) { - return createElement('div') - }, + props: { + editor: { + default: null, + type: Object, + }, + }, + watch: { + 'editor.element': { + immediate: true, + handler(element) { + if (element) { + this.$nextTick(() => this.$el.append(element.firstChild)) + } + }, + }, + }, + render(createElement) { + return createElement('div') + }, } diff --git a/packages/tiptap/src/Components/FloatingMenu.js b/packages/tiptap/src/Components/FloatingMenu.js index 0577db1d..156be1ea 100644 --- a/packages/tiptap/src/Components/FloatingMenu.js +++ b/packages/tiptap/src/Components/FloatingMenu.js @@ -1,50 +1,50 @@ import FloatingMenu from '../Utils/FloatingMenu' export default { - props: { - editor: { - default: null, - type: Object, - }, - }, - data() { - return { - menu: { - isActive: false, - left: 0, - bottom: 0, - }, - } - }, - watch: { - editor: { - immediate: true, - handler(editor) { - if (editor) { - this.$nextTick(() => { - editor.registerPlugin(FloatingMenu({ - element: this.$el, - onUpdate: menu => { - this.menu = menu - }, - })) - }) - } - }, - }, - }, - render() { - if (!this.editor) { - return null - } + props: { + editor: { + default: null, + type: Object, + }, + }, + data() { + return { + menu: { + isActive: false, + left: 0, + bottom: 0, + }, + } + }, + watch: { + editor: { + immediate: true, + handler(editor) { + if (editor) { + this.$nextTick(() => { + editor.registerPlugin(FloatingMenu({ + element: this.$el, + onUpdate: menu => { + this.menu = menu + }, + })) + }) + } + }, + }, + }, + render() { + if (!this.editor) { + return null + } - return this.$scopedSlots.default({ - focused: this.editor.view.focused, - focus: this.editor.focus, - commands: this.editor.commands, - isActive: this.editor.isActive.bind(this.editor), - markAttrs: this.editor.markAttrs.bind(this.editor), - menu: this.menu, - }) - }, + return this.$scopedSlots.default({ + focused: this.editor.view.focused, + focus: this.editor.focus, + commands: this.editor.commands, + isActive: this.editor.isActive.bind(this.editor), + markAttrs: this.editor.markAttrs.bind(this.editor), + menu: this.menu, + }) + }, } diff --git a/packages/tiptap/src/Components/MenuBar.js b/packages/tiptap/src/Components/MenuBar.js index 09022321..b816582f 100644 --- a/packages/tiptap/src/Components/MenuBar.js +++ b/packages/tiptap/src/Components/MenuBar.js @@ -1,21 +1,21 @@ export default { - props: { - editor: { - default: null, - type: Object, - }, - }, - render() { - if (!this.editor) { - return null - } + props: { + editor: { + default: null, + type: Object, + }, + }, + render() { + if (!this.editor) { + return null + } - return this.$scopedSlots.default({ - focused: this.editor.view.focused, - focus: this.editor.focus, - commands: this.editor.commands, - isActive: this.editor.isActive.bind(this.editor), - markAttrs: this.editor.markAttrs.bind(this.editor), - }) - }, + return this.$scopedSlots.default({ + focused: this.editor.view.focused, + focus: this.editor.focus, + commands: this.editor.commands, + isActive: this.editor.isActive.bind(this.editor), + markAttrs: this.editor.markAttrs.bind(this.editor), + }) + }, } diff --git a/packages/tiptap/src/Components/MenuBubble.js b/packages/tiptap/src/Components/MenuBubble.js index 9648ff80..5334bb17 100644 --- a/packages/tiptap/src/Components/MenuBubble.js +++ b/packages/tiptap/src/Components/MenuBubble.js @@ -1,50 +1,50 @@ import MenuBubble from '../Utils/MenuBubble' export default { - props: { - editor: { - default: null, - type: Object, - }, - }, - data() { - return { - menu: { - isActive: false, - left: 0, - bottom: 0, - }, - } - }, - watch: { - editor: { - immediate: true, - handler(editor) { - if (editor) { - this.$nextTick(() => { - editor.registerPlugin(MenuBubble({ - element: this.$el, - onUpdate: menu => { - this.menu = menu - }, - })) - }) - } - }, - }, - }, - render() { - if (!this.editor) { - return null - } + props: { + editor: { + default: null, + type: Object, + }, + }, + data() { + return { + menu: { + isActive: false, + left: 0, + bottom: 0, + }, + } + }, + watch: { + editor: { + immediate: true, + handler(editor) { + if (editor) { + this.$nextTick(() => { + editor.registerPlugin(MenuBubble({ + element: this.$el, + onUpdate: menu => { + this.menu = menu + }, + })) + }) + } + }, + }, + }, + render() { + if (!this.editor) { + return null + } - return this.$scopedSlots.default({ - focused: this.editor.view.focused, - focus: this.editor.focus, - commands: this.editor.commands, - isActive: this.editor.isActive.bind(this.editor), - markAttrs: this.editor.markAttrs.bind(this.editor), - menu: this.menu, - }) - }, + return this.$scopedSlots.default({ + focused: this.editor.view.focused, + focus: this.editor.focus, + commands: this.editor.commands, + isActive: this.editor.isActive.bind(this.editor), + markAttrs: this.editor.markAttrs.bind(this.editor), + menu: this.menu, + }) + }, } diff --git a/packages/tiptap/src/index.js b/packages/tiptap/src/index.js index 720659d5..110ebdf2 100644 --- a/packages/tiptap/src/index.js +++ b/packages/tiptap/src/index.js @@ -7,4 +7,4 @@ export { default as FloatingMenu } from './Components/FloatingMenu' export { default as Extension } from './Utils/Extension' export { default as Node } from './Utils/Node' export { default as Mark } from './Utils/Mark' -export { default as Plugin } from './Utils/Plugin' \ No newline at end of file +export { default as Plugin } from './Utils/Plugin' diff --git a/packages/tiptap/src/nodes/Doc.js b/packages/tiptap/src/nodes/Doc.js index 07c3bdf8..ec21bbe8 100644 --- a/packages/tiptap/src/nodes/Doc.js +++ b/packages/tiptap/src/nodes/Doc.js @@ -2,14 +2,14 @@ import Node from '../Utils/Node' export default class Doc extends Node { - get name() { - return 'doc' - } + get name() { + return 'doc' + } - get schema() { - return { - content: 'block+', - } - } + get schema() { + return { + content: 'block+', + } + } } diff --git a/packages/tiptap/src/nodes/Paragraph.js b/packages/tiptap/src/nodes/Paragraph.js index 4b6f03cd..2f4496f6 100644 --- a/packages/tiptap/src/nodes/Paragraph.js +++ b/packages/tiptap/src/nodes/Paragraph.js @@ -3,24 +3,24 @@ import Node from '../Utils/Node' export default class Paragraph extends Node { - get name() { - return 'paragraph' - } + get name() { + return 'paragraph' + } - get schema() { - return { - content: 'inline*', - group: 'block', - draggable: false, - parseDOM: [{ - tag: 'p', - }], - toDOM: () => ['p', 0], - } - } + get schema() { + return { + content: 'inline*', + group: 'block', + draggable: false, + parseDOM: [{ + tag: 'p', + }], + toDOM: () => ['p', 0], + } + } - commands({ type }) { - return () => setBlockType(type) - } + commands({ type }) { + return () => setBlockType(type) + } } diff --git a/packages/tiptap/src/nodes/Text.js b/packages/tiptap/src/nodes/Text.js index 9a720384..b48aaeb8 100644 --- a/packages/tiptap/src/nodes/Text.js +++ b/packages/tiptap/src/nodes/Text.js @@ -2,14 +2,14 @@ import Node from '../Utils/Node' export default class Text extends Node { - get name() { - return 'text' - } + get name() { + return 'text' + } - get schema() { - return { - group: 'inline', - } - } + get schema() { + return { + group: 'inline', + } + } } diff --git a/packages/tiptap/src/nodes/index.js b/packages/tiptap/src/nodes/index.js index b4fc3ee2..a921a807 100644 --- a/packages/tiptap/src/nodes/index.js +++ b/packages/tiptap/src/nodes/index.js @@ -3,7 +3,7 @@ import Paragraph from './Paragraph' import Text from './Text' export default [ - new Doc(), - new Text(), - new Paragraph(), + new Doc(), + new Text(), + new Paragraph(), ] diff --git a/packages/tiptap/src/utils/ComponentView.js b/packages/tiptap/src/utils/ComponentView.js index d9bbab4a..6779ffa3 100644 --- a/packages/tiptap/src/utils/ComponentView.js +++ b/packages/tiptap/src/utils/ComponentView.js @@ -1,92 +1,92 @@ import Vue from 'vue' export default class ComponentView { - constructor(component, { - parent, - node, - view, - getPos, - decorations, - editable, - }) { - this.parent = parent - this.component = component - this.node = node - this.view = view - this.getPos = getPos - this.decorations = decorations - this.editable = editable + constructor(component, { + parent, + node, + view, + getPos, + decorations, + editable, + }) { + this.parent = parent + this.component = component + this.node = node + this.view = view + this.getPos = getPos + this.decorations = decorations + this.editable = editable - this.dom = this.createDOM() - this.contentDOM = this.vm.$refs.content - } + this.dom = this.createDOM() + this.contentDOM = this.vm.$refs.content + } - createDOM() { - const Component = Vue.extend(this.component) - this.vm = new Component({ - parent: this.parent, - propsData: { - node: this.node, - view: this.view, - getPos: this.getPos, - decorations: this.decorations, - editable: this.editable, - updateAttrs: attrs => this.updateAttrs(attrs), - updateContent: content => this.updateContent(content), - }, - }).$mount() - return this.vm.$el - } + createDOM() { + const Component = Vue.extend(this.component) + this.vm = new Component({ + parent: this.parent, + propsData: { + node: this.node, + view: this.view, + getPos: this.getPos, + decorations: this.decorations, + editable: this.editable, + updateAttrs: attrs => this.updateAttrs(attrs), + updateContent: content => this.updateContent(content), + }, + }).$mount() + return this.vm.$el + } - updateAttrs(attrs) { - if (!this.editable) { - return - } + updateAttrs(attrs) { + if (!this.editable) { + return + } - const transaction = this.view.state.tr.setNodeMarkup(this.getPos(), null, { - ...this.node.attrs, - ...attrs, - }) - this.view.dispatch(transaction) - } + const transaction = this.view.state.tr.setNodeMarkup(this.getPos(), null, { + ...this.node.attrs, + ...attrs, + }) + this.view.dispatch(transaction) + } - updateContent(content) { - if (!this.editable) { - return - } + updateContent(content) { + if (!this.editable) { + return + } - const transaction = this.view.state.tr.setNodeMarkup(this.getPos(), this.node.type, { content }) - this.view.dispatch(transaction) - } + const transaction = this.view.state.tr.setNodeMarkup(this.getPos(), this.node.type, { content }) + this.view.dispatch(transaction) + } - ignoreMutation() { - return true - } + ignoreMutation() { + return true + } - stopEvent(event) { - // TODO: find a way to pass full extensions to ComponentView - // so we could check for schema.draggable - // for now we're allowing all drag events for node views - return !/drag/.test(event.type) - } + stopEvent(event) { + // TODO: find a way to pass full extensions to ComponentView + // so we could check for schema.draggable + // for now we're allowing all drag events for node views + return !/drag/.test(event.type) + } - update(node, decorations) { - if (node.type !== this.node.type) { - return false - } + update(node, decorations) { + if (node.type !== this.node.type) { + return false + } - if (node === this.node && this.decorations === decorations) { - return true - } + if (node === this.node && this.decorations === decorations) { + return true + } - this.node = node - this.decorations = decorations - this.vm._props.node = node - this.vm._props.decorations = decorations - return true - } + this.node = node + this.decorations = decorations + this.vm._props.node = node + this.vm._props.decorations = decorations + return true + } - destroy() { - this.vm.$destroy() - } + destroy() { + this.vm.$destroy() + } } diff --git a/packages/tiptap/src/utils/Editor.js b/packages/tiptap/src/utils/Editor.js index 8b7514af..eee2224e 100644 --- a/packages/tiptap/src/utils/Editor.js +++ b/packages/tiptap/src/utils/Editor.js @@ -9,278 +9,278 @@ import { inputRules } from 'prosemirror-inputrules' import { markIsActive, nodeIsActive, getMarkAttrs } from 'tiptap-utils' import { - ExtensionManager, - initNodeViews, - builtInKeymap, + ExtensionManager, + initNodeViews, + builtInKeymap, } from '.' import builtInNodes from '../Nodes' export default class Editor { - constructor(options = {}) { - this.setOptions(options) - this.init() - } + constructor(options = {}) { + this.setOptions(options) + this.init() + } - setOptions(options) { - const defaultOptions = { - editable: true, - content: '', - onUpdate: () => {}, - } + setOptions(options) { + const defaultOptions = { + editable: true, + content: '', + onUpdate: () => {}, + } - this.options = { - ...defaultOptions, - ...options, - } - } + this.options = { + ...defaultOptions, + ...options, + } + } - init() { - this.bus = new Vue() - this.element = document.createElement('div') - this.extensions = this.createExtensions() - this.nodes = this.createNodes() - this.marks = this.createMarks() - this.views = this.createViews() - this.schema = this.createSchema() - this.plugins = this.createPlugins() - this.keymaps = this.createKeymaps() - this.inputRules = this.createInputRules() - this.state = this.createState() - this.view = this.createView() - this.commands = this.createCommands() - this.getActiveNodesAndMarks() - this.emit('init') - } + init() { + this.bus = new Vue() + this.element = document.createElement('div') + this.extensions = this.createExtensions() + this.nodes = this.createNodes() + this.marks = this.createMarks() + this.views = this.createViews() + this.schema = this.createSchema() + this.plugins = this.createPlugins() + this.keymaps = this.createKeymaps() + this.inputRules = this.createInputRules() + this.state = this.createState() + this.view = this.createView() + this.commands = this.createCommands() + this.getActiveNodesAndMarks() + this.emit('init') + } - createExtensions() { - return new ExtensionManager([ - ...builtInNodes, - ...this.options.extensions, - ]) - } + createExtensions() { + return new ExtensionManager([ + ...builtInNodes, + ...this.options.extensions, + ]) + } - createPlugins() { - return this.extensions.plugins - } + createPlugins() { + return this.extensions.plugins + } - createKeymaps() { - return this.extensions.keymaps({ - schema: this.schema, - }) - } + createKeymaps() { + return this.extensions.keymaps({ + schema: this.schema, + }) + } - createInputRules() { - return this.extensions.inputRules({ - schema: this.schema, - }) - } + createInputRules() { + return this.extensions.inputRules({ + schema: this.schema, + }) + } - createCommands() { - return this.extensions.commands({ - schema: this.schema, - view: this.view, - editable: this.options.editable, - }) - } + createCommands() { + return this.extensions.commands({ + schema: this.schema, + view: this.view, + editable: this.options.editable, + }) + } - createNodes() { - return this.extensions.nodes - } + createNodes() { + return this.extensions.nodes + } - createMarks() { - return this.extensions.marks - } + createMarks() { + return this.extensions.marks + } - createViews() { - return this.extensions.views - } + createViews() { + return this.extensions.views + } - createSchema() { - return new Schema({ - nodes: this.nodes, - marks: this.marks, - }) - } + createSchema() { + return new Schema({ + nodes: this.nodes, + marks: this.marks, + }) + } - createState() { - return EditorState.create({ - schema: this.schema, - doc: this.createDocument(this.options.content), - plugins: [ - ...this.plugins, - inputRules({ - rules: this.inputRules, - }), - ...this.keymaps, - keymap(builtInKeymap), - keymap(baseKeymap), - gapCursor(), - new Plugin({ - props: { - editable: () => this.options.editable, - }, - }), - ], - }) - } + createState() { + return EditorState.create({ + schema: this.schema, + doc: this.createDocument(this.options.content), + plugins: [ + ...this.plugins, + inputRules({ + rules: this.inputRules, + }), + ...this.keymaps, + keymap(builtInKeymap), + keymap(baseKeymap), + gapCursor(), + new Plugin({ + props: { + editable: () => this.options.editable, + }, + }), + ], + }) + } - createDocument(content) { - if (typeof content === 'object') { - return this.schema.nodeFromJSON(content) - } + createDocument(content) { + if (typeof content === 'object') { + return this.schema.nodeFromJSON(content) + } - if (typeof content === 'string') { - const element = document.createElement('div') - element.innerHTML = content.trim() + if (typeof content === 'string') { + const element = document.createElement('div') + element.innerHTML = content.trim() - return DOMParser.fromSchema(this.schema).parse(element) - } + return DOMParser.fromSchema(this.schema).parse(element) + } - return false - } + return false + } - createView() { - const view = new EditorView(this.element, { - state: this.state, - dispatchTransaction: this.dispatchTransaction.bind(this), - nodeViews: initNodeViews({ - nodes: this.views, - editable: this.options.editable, - }), - }) + createView() { + const view = new EditorView(this.element, { + state: this.state, + dispatchTransaction: this.dispatchTransaction.bind(this), + nodeViews: initNodeViews({ + nodes: this.views, + editable: this.options.editable, + }), + }) - view.dom.style.whiteSpace = 'pre-wrap' + view.dom.style.whiteSpace = 'pre-wrap' - return view - } + return view + } - dispatchTransaction(transaction) { - this.state = this.state.apply(transaction) - this.view.updateState(this.state) - this.getActiveNodesAndMarks() + dispatchTransaction(transaction) { + this.state = this.state.apply(transaction) + this.view.updateState(this.state) + this.getActiveNodesAndMarks() - if (!transaction.docChanged) { - return - } + if (!transaction.docChanged) { + return + } - this.emitUpdate() - } + this.emitUpdate() + } - emitUpdate() { - this.options.onUpdate({ - getHTML: this.getHTML.bind(this), - getJSON: this.getJSON.bind(this), - state: this.state, - }) - } + emitUpdate() { + this.options.onUpdate({ + getHTML: this.getHTML.bind(this), + getJSON: this.getJSON.bind(this), + state: this.state, + }) + } - getHTML() { - const div = document.createElement('div') - const fragment = DOMSerializer - .fromSchema(this.schema) - .serializeFragment(this.state.doc.content) + getHTML() { + const div = document.createElement('div') + const fragment = DOMSerializer + .fromSchema(this.schema) + .serializeFragment(this.state.doc.content) - div.appendChild(fragment) + div.appendChild(fragment) - return div.innerHTML - } + return div.innerHTML + } - getJSON() { - return this.state.doc.toJSON() - } + getJSON() { + return this.state.doc.toJSON() + } - setContent(content = {}, emitUpdate = false) { - this.state = EditorState.create({ - schema: this.state.schema, - doc: this.createDocument(content), - plugins: this.state.plugins, - }) + setContent(content = {}, emitUpdate = false) { + this.state = EditorState.create({ + schema: this.state.schema, + doc: this.createDocument(content), + plugins: this.state.plugins, + }) - this.view.updateState(this.state) + this.view.updateState(this.state) - if (emitUpdate) { - this.emitUpdate() - } - } + if (emitUpdate) { + this.emitUpdate() + } + } - clearContent(emitUpdate = false) { - this.setContent({ - type: 'doc', - content: [{ - type: 'paragraph', - }], - }, emitUpdate) - } + clearContent(emitUpdate = false) { + this.setContent({ + type: 'doc', + content: [{ + type: 'paragraph', + }], + }, emitUpdate) + } - getActiveNodesAndMarks() { - this.activeMarks = Object - .entries(this.schema.marks) - .reduce((marks, [name, mark]) => ({ - ...marks, - [name]: (attrs = {}) => markIsActive(this.state, mark, attrs), - }), {}) + getActiveNodesAndMarks() { + this.activeMarks = Object + .entries(this.schema.marks) + .reduce((marks, [name, mark]) => ({ + ...marks, + [name]: (attrs = {}) => markIsActive(this.state, mark, attrs), + }), {}) - this.activeMarkAttrs = Object - .entries(this.schema.marks) - .reduce((marks, [name, mark]) => ({ - ...marks, - [name]: getMarkAttrs(this.state, mark), - }), {}) + this.activeMarkAttrs = Object + .entries(this.schema.marks) + .reduce((marks, [name, mark]) => ({ + ...marks, + [name]: getMarkAttrs(this.state, mark), + }), {}) - this.activeNodes = Object - .entries(this.schema.nodes) - .reduce((nodes, [name, node]) => ({ - ...nodes, - [name]: (attrs = {}) => nodeIsActive(this.state, node, attrs), - }), {}) - } + this.activeNodes = Object + .entries(this.schema.nodes) + .reduce((nodes, [name, node]) => ({ + ...nodes, + [name]: (attrs = {}) => nodeIsActive(this.state, node, attrs), + }), {}) + } - focus() { - this.view.focus() - } + focus() { + this.view.focus() + } - emit(event, ...data) { - this.bus.$emit(event, ...data) - } + emit(event, ...data) { + this.bus.$emit(event, ...data) + } - on(event, callback) { - this.bus.$on(event, callback) - } + on(event, callback) { + this.bus.$on(event, callback) + } - registerPlugin(plugin = null) { - if (plugin) { - this.state = this.state.reconfigure({ - plugins: this.state.plugins.concat([plugin]), - }) - this.view.updateState(this.state) - } - } + registerPlugin(plugin = null) { + if (plugin) { + this.state = this.state.reconfigure({ + plugins: this.state.plugins.concat([plugin]), + }) + this.view.updateState(this.state) + } + } - markAttrs(type = null) { - return this.activeMarkAttrs[type] - } + markAttrs(type = null) { + return this.activeMarkAttrs[type] + } - isActive(type = null, attrs = {}) { - const types = { - ...this.activeMarks, - ...this.activeNodes, - } + isActive(type = null, attrs = {}) { + const types = { + ...this.activeMarks, + ...this.activeNodes, + } - if (!types[type]) { - return false - } + if (!types[type]) { + return false + } - return types[type](attrs) - } + return types[type](attrs) + } - destroy() { - this.emit('destroy') + destroy() { + this.emit('destroy') - if (this.view) { - this.view.destroy() - } - } + if (this.view) { + this.view.destroy() + } + } } diff --git a/packages/tiptap/src/utils/ExtensionManager.js b/packages/tiptap/src/utils/ExtensionManager.js index 510a1608..7b4710b8 100644 --- a/packages/tiptap/src/utils/ExtensionManager.js +++ b/packages/tiptap/src/utils/ExtensionManager.js @@ -2,148 +2,148 @@ import { keymap } from 'prosemirror-keymap' export default class ExtensionManager { - constructor(extensions = []) { - this.extensions = extensions - } + constructor(extensions = []) { + this.extensions = extensions + } - get nodes() { - return this.extensions - .filter(extension => extension.type === 'node') - .reduce((nodes, { name, schema }) => ({ - ...nodes, - [name]: schema, - }), {}) - } + get nodes() { + return this.extensions + .filter(extension => extension.type === 'node') + .reduce((nodes, { name, schema }) => ({ + ...nodes, + [name]: schema, + }), {}) + } - get marks() { - return this.extensions - .filter(extension => extension.type === 'mark') - .reduce((marks, { name, schema }) => ({ - ...marks, - [name]: schema, - }), {}) - } + get marks() { + return this.extensions + .filter(extension => extension.type === 'mark') + .reduce((marks, { name, schema }) => ({ + ...marks, + [name]: schema, + }), {}) + } - get plugins() { - return this.extensions - .filter(extension => extension.plugins) - .reduce((allPlugins, { plugins }) => ([ - ...allPlugins, - ...plugins, - ]), []) - } + get plugins() { + return this.extensions + .filter(extension => extension.plugins) + .reduce((allPlugins, { plugins }) => ([ + ...allPlugins, + ...plugins, + ]), []) + } - get views() { - return this.extensions - .filter(extension => ['node', 'mark'].includes(extension.type)) - .filter(extension => extension.view) - .reduce((views, { name, view }) => ({ - ...views, - [name]: view, - }), {}) - } + get views() { + return this.extensions + .filter(extension => ['node', 'mark'].includes(extension.type)) + .filter(extension => extension.view) + .reduce((views, { name, view }) => ({ + ...views, + [name]: view, + }), {}) + } - keymaps({ schema }) { - const extensionKeymaps = this.extensions - .filter(extension => ['extension'].includes(extension.type)) - .filter(extension => extension.keys) - .map(extension => extension.keys({ schema })) + keymaps({ schema }) { + const extensionKeymaps = this.extensions + .filter(extension => ['extension'].includes(extension.type)) + .filter(extension => extension.keys) + .map(extension => extension.keys({ schema })) - const nodeMarkKeymaps = this.extensions - .filter(extension => ['node', 'mark'].includes(extension.type)) - .filter(extension => extension.keys) - .map(extension => extension.keys({ - type: schema[`${extension.type}s`][extension.name], - schema, - })) + const nodeMarkKeymaps = this.extensions + .filter(extension => ['node', 'mark'].includes(extension.type)) + .filter(extension => extension.keys) + .map(extension => extension.keys({ + type: schema[`${extension.type}s`][extension.name], + schema, + })) - return [ - ...extensionKeymaps, - ...nodeMarkKeymaps, - ].map(keys => keymap(keys)) - } + return [ + ...extensionKeymaps, + ...nodeMarkKeymaps, + ].map(keys => keymap(keys)) + } - inputRules({ schema }) { - const extensionInputRules = this.extensions - .filter(extension => ['extension'].includes(extension.type)) - .filter(extension => extension.inputRules) - .map(extension => extension.inputRules({ schema })) + inputRules({ schema }) { + const extensionInputRules = this.extensions + .filter(extension => ['extension'].includes(extension.type)) + .filter(extension => extension.inputRules) + .map(extension => extension.inputRules({ schema })) - const nodeMarkInputRules = this.extensions - .filter(extension => ['node', 'mark'].includes(extension.type)) - .filter(extension => extension.inputRules) - .map(extension => extension.inputRules({ - type: schema[`${extension.type}s`][extension.name], - schema, - })) + const nodeMarkInputRules = this.extensions + .filter(extension => ['node', 'mark'].includes(extension.type)) + .filter(extension => extension.inputRules) + .map(extension => extension.inputRules({ + type: schema[`${extension.type}s`][extension.name], + schema, + })) - return [ - ...extensionInputRules, - ...nodeMarkInputRules, - ].reduce((allInputRules, inputRules) => ([ - ...allInputRules, - ...inputRules, - ]), []) - } + return [ + ...extensionInputRules, + ...nodeMarkInputRules, + ].reduce((allInputRules, inputRules) => ([ + ...allInputRules, + ...inputRules, + ]), []) + } - commands({ schema, view, editable }) { - return this.extensions - .filter(extension => extension.commands) - .reduce((allCommands, { name, type, commands: provider }) => { + commands({ schema, view, editable }) { + return this.extensions + .filter(extension => extension.commands) + .reduce((allCommands, { name, type, commands: provider }) => { - const commands = {} - const value = provider({ - schema, - ...['node', 'mark'].includes(type) ? { - type: schema[`${type}s`][name], - } : {}, - }) + const commands = {} + const value = provider({ + schema, + ...['node', 'mark'].includes(type) ? { + type: schema[`${type}s`][name], + } : {}, + }) - if (Array.isArray(value)) { - commands[name] = attrs => value - .forEach(callback => { - if (!editable) { - return false - } - view.focus() - return callback(attrs)(view.state, view.dispatch, view) - }) - } else if (typeof value === 'function') { - commands[name] = attrs => { - if (!editable) { - return false - } - view.focus() - return value(attrs)(view.state, view.dispatch, view) - } - } else if (typeof value === 'object') { - Object.entries(value).forEach(([commandName, commandValue]) => { - if (Array.isArray(commandValue)) { - commands[commandName] = attrs => commandValue - .forEach(callback => { - if (!editable) { - return false - } - view.focus() - return callback(attrs)(view.state, view.dispatch, view) - }) - } else { - commands[commandName] = attrs => { - if (!editable) { - return false - } - view.focus() - return commandValue(attrs)(view.state, view.dispatch, view) - } - } - }) - } + if (Array.isArray(value)) { + commands[name] = attrs => value + .forEach(callback => { + if (!editable) { + return false + } + view.focus() + return callback(attrs)(view.state, view.dispatch, view) + }) + } else if (typeof value === 'function') { + commands[name] = attrs => { + if (!editable) { + return false + } + view.focus() + return value(attrs)(view.state, view.dispatch, view) + } + } else if (typeof value === 'object') { + Object.entries(value).forEach(([commandName, commandValue]) => { + if (Array.isArray(commandValue)) { + commands[commandName] = attrs => commandValue + .forEach(callback => { + if (!editable) { + return false + } + view.focus() + return callback(attrs)(view.state, view.dispatch, view) + }) + } else { + commands[commandName] = attrs => { + if (!editable) { + return false + } + view.focus() + return commandValue(attrs)(view.state, view.dispatch, view) + } + } + }) + } - return { - ...allCommands, - ...commands, - } - }, {}) - } + return { + ...allCommands, + ...commands, + } + }, {}) + } } diff --git a/packages/tiptap/src/utils/FloatingMenu.js b/packages/tiptap/src/utils/FloatingMenu.js index e812a0b3..d071cbac 100644 --- a/packages/tiptap/src/utils/FloatingMenu.js +++ b/packages/tiptap/src/utils/FloatingMenu.js @@ -2,81 +2,81 @@ import { Plugin } from 'prosemirror-state' class Menu { - constructor({ options, editorView }) { - this.options = { - ...{ - element: null, - onUpdate: () => false, - }, - ...options, - } - this.editorView = editorView - this.isActive = false - this.top = 0 + constructor({ options, editorView }) { + this.options = { + ...{ + element: null, + onUpdate: () => false, + }, + ...options, + } + this.editorView = editorView + this.isActive = false + this.top = 0 - this.editorView.dom.addEventListener('blur', this.hide.bind(this)) - } + this.editorView.dom.addEventListener('blur', this.hide.bind(this)) + } - update(view, lastState) { - const { state } = view + update(view, lastState) { + const { state } = view - // Don't do anything if the document/selection didn't change - if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) { - return - } + // Don't do anything if the document/selection didn't change + if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) { + return + } - if (!state.selection.empty) { - this.hide() - return - } + if (!state.selection.empty) { + this.hide() + return + } - const currentDom = view.domAtPos(state.selection.$anchor.pos) + const currentDom = view.domAtPos(state.selection.$anchor.pos) - const isActive = currentDom.node.innerHTML === '
    ' - && currentDom.node.tagName === 'P' - && currentDom.node.parentNode === view.dom + const isActive = currentDom.node.innerHTML === '
    ' + && currentDom.node.tagName === 'P' + && currentDom.node.parentNode === view.dom - if (!isActive) { - this.hide() - return - } + if (!isActive) { + this.hide() + return + } - const editorBoundings = this.options.element.offsetParent.getBoundingClientRect() - const cursorBoundings = view.coordsAtPos(state.selection.$anchor.pos) - const top = cursorBoundings.top - editorBoundings.top + const editorBoundings = this.options.element.offsetParent.getBoundingClientRect() + const cursorBoundings = view.coordsAtPos(state.selection.$anchor.pos) + const top = cursorBoundings.top - editorBoundings.top - this.isActive = true - this.top = top + this.isActive = true + this.top = top - this.sendUpdate() - } + this.sendUpdate() + } - sendUpdate() { - this.options.onUpdate({ - isActive: this.isActive, - top: this.top, - }) - } + sendUpdate() { + this.options.onUpdate({ + isActive: this.isActive, + top: this.top, + }) + } - hide(event) { - if (event && event.relatedTarget) { - return - } + hide(event) { + if (event && event.relatedTarget) { + return + } - this.isActive = false - this.sendUpdate() - } + this.isActive = false + this.sendUpdate() + } - destroy() { - this.editorView.dom.removeEventListener('blur', this.hide) - } + destroy() { + this.editorView.dom.removeEventListener('blur', this.hide) + } } export default function (options) { - return new Plugin({ - view(editorView) { - return new Menu({ editorView, options }) - }, - }) + return new Plugin({ + view(editorView) { + return new Menu({ editorView, options }) + }, + }) } diff --git a/packages/tiptap/src/utils/MenuBubble.js b/packages/tiptap/src/utils/MenuBubble.js index 2e7ec1a3..95510b77 100644 --- a/packages/tiptap/src/utils/MenuBubble.js +++ b/packages/tiptap/src/utils/MenuBubble.js @@ -2,84 +2,84 @@ import { Plugin } from 'prosemirror-state' class Menu { - constructor({ options, editorView }) { - this.options = { - ...{ - element: null, - onUpdate: () => false, - }, - ...options, - } - this.editorView = editorView - this.isActive = false - this.left = 0 - this.bottom = 0 + constructor({ options, editorView }) { + this.options = { + ...{ + element: null, + onUpdate: () => false, + }, + ...options, + } + this.editorView = editorView + this.isActive = false + this.left = 0 + this.bottom = 0 - this.editorView.dom.addEventListener('blur', this.hide.bind(this)) - } + this.editorView.dom.addEventListener('blur', this.hide.bind(this)) + } - update(view, lastState) { - const { state } = view + update(view, lastState) { + const { state } = view - // Don't do anything if the document/selection didn't change - if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) { - return - } + // Don't do anything if the document/selection didn't change + if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) { + return + } - // Hide the tooltip if the selection is empty - if (state.selection.empty) { - this.hide() - return - } + // Hide the tooltip if the selection is empty + if (state.selection.empty) { + this.hide() + return + } - // Otherwise, reposition it and update its content - const { from, to } = state.selection + // Otherwise, reposition it and update its content + const { from, to } = state.selection - // These are in screen coordinates - const start = view.coordsAtPos(from) - const end = view.coordsAtPos(to) + // These are in screen coordinates + const start = view.coordsAtPos(from) + const end = view.coordsAtPos(to) - // The box in which the tooltip is positioned, to use as base - const box = this.options.element.offsetParent.getBoundingClientRect() + // The box in which the tooltip is positioned, to use as base + const box = this.options.element.offsetParent.getBoundingClientRect() - // Find a center-ish x position from the selection endpoints (when - // crossing lines, end may be more to the left) - const left = Math.max((start.left + end.left) / 2, start.left + 3) + // Find a center-ish x position from the selection endpoints (when + // crossing lines, end may be more to the left) + const left = Math.max((start.left + end.left) / 2, start.left + 3) - this.isActive = true - this.left = parseInt(left - box.left, 10) - this.bottom = parseInt(box.bottom - start.top, 10) + this.isActive = true + this.left = parseInt(left - box.left, 10) + this.bottom = parseInt(box.bottom - start.top, 10) - this.sendUpdate() - } + this.sendUpdate() + } - sendUpdate() { - this.options.onUpdate({ - isActive: this.isActive, - left: this.left, - bottom: this.bottom, - }) - } + sendUpdate() { + this.options.onUpdate({ + isActive: this.isActive, + left: this.left, + bottom: this.bottom, + }) + } - hide(event) { - if (event && event.relatedTarget) { - return - } + hide(event) { + if (event && event.relatedTarget) { + return + } - this.isActive = false - this.sendUpdate() - } + this.isActive = false + this.sendUpdate() + } - destroy() { - this.editorView.dom.removeEventListener('blur', this.hide) - } + destroy() { + this.editorView.dom.removeEventListener('blur', this.hide) + } } export default function (options) { - return new Plugin({ - view(editorView) { - return new Menu({ editorView, options }) - }, - }) + return new Plugin({ + view(editorView) { + return new Menu({ editorView, options }) + }, + }) } diff --git a/packages/tiptap/src/utils/builtInKeymap.js b/packages/tiptap/src/utils/builtInKeymap.js index 0f4b497e..9a323e6e 100644 --- a/packages/tiptap/src/utils/builtInKeymap.js +++ b/packages/tiptap/src/utils/builtInKeymap.js @@ -2,9 +2,9 @@ import { lift, selectParentNode } from 'prosemirror-commands' import { undoInputRule } from 'prosemirror-inputrules' const keymap = { - 'Mod-BracketLeft': lift, - Backspace: undoInputRule, - Escape: selectParentNode, + 'Mod-BracketLeft': lift, + Backspace: undoInputRule, + Escape: selectParentNode, } export default keymap diff --git a/packages/tiptap/src/utils/extension.js b/packages/tiptap/src/utils/extension.js index a8c8e7a5..e86851d2 100644 --- a/packages/tiptap/src/utils/extension.js +++ b/packages/tiptap/src/utils/extension.js @@ -1,34 +1,34 @@ export default class Extension { - constructor(options = {}) { - this.options = { - ...this.defaultOptions, - ...options, - } - } + constructor(options = {}) { + this.options = { + ...this.defaultOptions, + ...options, + } + } - get name() { - return null - } + get name() { + return null + } - get type() { - return 'extension' - } + get type() { + return 'extension' + } - get defaultOptions() { - return {} - } + get defaultOptions() { + return {} + } - get plugins() { - return [] - } + get plugins() { + return [] + } - inputRules() { - return [] - } + inputRules() { + return [] + } - keys() { - return {} - } + keys() { + return {} + } } diff --git a/packages/tiptap/src/utils/mark.js b/packages/tiptap/src/utils/mark.js index 3d4189ea..379311e3 100644 --- a/packages/tiptap/src/utils/mark.js +++ b/packages/tiptap/src/utils/mark.js @@ -2,24 +2,24 @@ import Extension from './Extension' export default class Mark extends Extension { - constructor(options = {}) { - super(options) - } + constructor(options = {}) { + super(options) + } - get type() { - return 'mark' - } + get type() { + return 'mark' + } - get view() { - return null - } + get view() { + return null + } - get schema() { - return null - } + get schema() { + return null + } - command() { - return () => {} - } + command() { + return () => {} + } } diff --git a/packages/tiptap/src/utils/node.js b/packages/tiptap/src/utils/node.js index 6ffba259..241e0306 100644 --- a/packages/tiptap/src/utils/node.js +++ b/packages/tiptap/src/utils/node.js @@ -2,24 +2,24 @@ import Extension from './Extension' export default class Node extends Extension { - constructor(options = {}) { - super(options) - } + constructor(options = {}) { + super(options) + } - get type() { - return 'node' - } + get type() { + return 'node' + } - get view() { - return null - } + get view() { + return null + } - get schema() { - return null - } + get schema() { + return null + } - command() { - return () => {} - } + command() { + return () => {} + } }