forked from AkkomaGang/akkoma-fe
format (almost) everything remaining with prettier
This commit is contained in:
parent
142f90c4cf
commit
b07cf33a04
6
.babelrc
6
.babelrc
|
@ -1,5 +1,9 @@
|
|||
{
|
||||
"presets": ["@babel/preset-env"],
|
||||
"plugins": ["@babel/plugin-transform-runtime", "lodash", "@vue/babel-plugin-jsx"],
|
||||
"plugins": [
|
||||
"@babel/plugin-transform-runtime",
|
||||
"lodash",
|
||||
"@vue/babel-plugin-jsx"
|
||||
],
|
||||
"comments": false
|
||||
}
|
||||
|
|
|
@ -11,14 +11,17 @@ var webpackConfig = require('./webpack.prod.conf')
|
|||
|
||||
console.log(
|
||||
' Tip:\n' +
|
||||
' Built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
' Built files are meant to be served over an HTTP server.\n' +
|
||||
" Opening index.html over file:// won't work.\n"
|
||||
)
|
||||
|
||||
var spinner = ora('building for production...')
|
||||
spinner.start()
|
||||
|
||||
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
|
||||
var assetsPath = path.join(
|
||||
config.build.assetsRoot,
|
||||
config.build.assetsSubDirectory
|
||||
)
|
||||
rm('-rf', assetsPath)
|
||||
mkdir('-p', assetsPath)
|
||||
cp('-R', 'static/*', assetsPath)
|
||||
|
@ -26,11 +29,13 @@ cp('-R', 'static/*', assetsPath)
|
|||
webpack(webpackConfig, function (err, stats) {
|
||||
spinner.stop()
|
||||
if (err) throw err
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n')
|
||||
process.stdout.write(
|
||||
stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n'
|
||||
)
|
||||
})
|
||||
|
|
|
@ -2,8 +2,7 @@ var semver = require('semver')
|
|||
var chalk = require('chalk')
|
||||
var packageConfig = require('../package.json')
|
||||
var exec = function (cmd) {
|
||||
return require('child_process')
|
||||
.execSync(cmd).toString().trim()
|
||||
return require('child_process').execSync(cmd).toString().trim()
|
||||
}
|
||||
|
||||
var versionRequirements = [
|
||||
|
@ -24,16 +23,23 @@ module.exports = function () {
|
|||
for (var i = 0; i < versionRequirements.length; i++) {
|
||||
var mod = versionRequirements[i]
|
||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||
warnings.push(mod.name + ': ' +
|
||||
chalk.red(mod.currentVersion) + ' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
warnings.push(
|
||||
mod.name +
|
||||
': ' +
|
||||
chalk.red(mod.currentVersion) +
|
||||
' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
console.log('')
|
||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'To use this template, you must update following to modules:'
|
||||
)
|
||||
)
|
||||
console.log()
|
||||
for (var i = 0; i < warnings.length; i++) {
|
||||
var warning = warnings[i]
|
||||
|
|
|
@ -6,9 +6,10 @@ var express = require('express')
|
|||
var webpack = require('webpack')
|
||||
var opn = require('opn')
|
||||
var proxyMiddleware = require('http-proxy-middleware')
|
||||
var webpackConfig = process.env.NODE_ENV === 'testing'
|
||||
? require('./webpack.prod.conf')
|
||||
: require('./webpack.dev.conf')
|
||||
var webpackConfig =
|
||||
process.env.NODE_ENV === 'testing'
|
||||
? require('./webpack.prod.conf')
|
||||
: require('./webpack.dev.conf')
|
||||
|
||||
// default port where dev server listens for incoming traffic
|
||||
var port = process.env.PORT || config.dev.port
|
||||
|
@ -50,7 +51,10 @@ app.use(devMiddleware)
|
|||
app.use(hotMiddleware)
|
||||
|
||||
// serve pure static assets
|
||||
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
|
||||
var staticPath = path.posix.join(
|
||||
config.dev.assetsPublicPath,
|
||||
config.dev.assetsSubDirectory
|
||||
)
|
||||
app.use(staticPath, express.static('./static'))
|
||||
|
||||
module.exports = app.listen(port, function (err) {
|
||||
|
|
|
@ -4,7 +4,8 @@ var sass = require('sass')
|
|||
var MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
|
||||
exports.assetsPath = function (_path) {
|
||||
var assetsSubDirectory = process.env.NODE_ENV === 'production'
|
||||
var assetsSubDirectory =
|
||||
process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory
|
||||
return path.posix.join(assetsSubDirectory, _path)
|
||||
|
@ -13,7 +14,7 @@ exports.assetsPath = function (_path) {
|
|||
exports.cssLoaders = function (options) {
|
||||
options = options || {}
|
||||
|
||||
function generateLoaders (loaders) {
|
||||
function generateLoaders(loaders) {
|
||||
// Extract CSS when that option is specified
|
||||
// (which is the case during production build)
|
||||
if (options.extract) {
|
||||
|
@ -27,11 +28,11 @@ exports.cssLoaders = function (options) {
|
|||
return [
|
||||
{
|
||||
test: /\.(post)?css$/,
|
||||
use: generateLoaders(['css-loader', 'postcss-loader']),
|
||||
use: generateLoaders(['css-loader', 'postcss-loader'])
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: generateLoaders(['css-loader', 'postcss-loader', 'less-loader']),
|
||||
use: generateLoaders(['css-loader', 'postcss-loader', 'less-loader'])
|
||||
},
|
||||
{
|
||||
test: /\.sass$/,
|
||||
|
@ -52,8 +53,8 @@ exports.cssLoaders = function (options) {
|
|||
},
|
||||
{
|
||||
test: /\.styl(us)?$/,
|
||||
use: generateLoaders(['css-loader', 'postcss-loader', 'stylus-loader']),
|
||||
},
|
||||
use: generateLoaders(['css-loader', 'postcss-loader', 'stylus-loader'])
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ var { VueLoaderPlugin } = require('vue-loader')
|
|||
var env = process.env.NODE_ENV
|
||||
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the
|
||||
// various preprocessor loaders added to vue-loader at the end of this file
|
||||
var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
|
||||
var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
|
||||
var cssSourceMapDev = env === 'development' && config.dev.cssSourceMap
|
||||
var cssSourceMapProd = env === 'production' && config.build.productionSourceMap
|
||||
var useCssSourceMap = cssSourceMapDev || cssSourceMapProd
|
||||
|
||||
var now = Date.now()
|
||||
|
@ -18,9 +18,12 @@ module.exports = {
|
|||
app: './src/main.js'
|
||||
},
|
||||
output: {
|
||||
hashFunction: "sha256", // Workaround for builds with OpenSSL 3.
|
||||
hashFunction: 'sha256', // Workaround for builds with OpenSSL 3.
|
||||
path: config.build.assetsRoot,
|
||||
publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
|
||||
publicPath:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsPublicPath
|
||||
: config.dev.assetsPublicPath,
|
||||
filename: '[name].js'
|
||||
},
|
||||
optimization: {
|
||||
|
@ -30,17 +33,15 @@ module.exports = {
|
|||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.vue', '.mjs'],
|
||||
modules: [
|
||||
path.join(__dirname, '../node_modules')
|
||||
],
|
||||
modules: [path.join(__dirname, '../node_modules')],
|
||||
fallback: {
|
||||
"url": require.resolve("url/"),
|
||||
url: require.resolve('url/')
|
||||
},
|
||||
alias: {
|
||||
'static': path.resolve(__dirname, '../static'),
|
||||
'src': path.resolve(__dirname, '../src'),
|
||||
'assets': path.resolve(__dirname, '../src/assets'),
|
||||
'components': path.resolve(__dirname, '../src/components'),
|
||||
static: path.resolve(__dirname, '../static'),
|
||||
src: path.resolve(__dirname, '../src'),
|
||||
assets: path.resolve(__dirname, '../src/assets'),
|
||||
components: path.resolve(__dirname, '../src/components'),
|
||||
'vue-i18n': 'vue-i18n/dist/vue-i18n.runtime.esm-bundler.js'
|
||||
}
|
||||
},
|
||||
|
@ -66,14 +67,15 @@ module.exports = {
|
|||
test: /\.(json5?|ya?ml)$/, // target json, json5, yaml and yml files
|
||||
type: 'javascript/auto',
|
||||
loader: '@intlify/vue-i18n-loader',
|
||||
include: [ // Use `Rule.include` to specify the files of locale messages to be pre-compiled
|
||||
include: [
|
||||
// Use `Rule.include` to specify the files of locale messages to be pre-compiled
|
||||
path.resolve(__dirname, '../src/i18n')
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.mjs$/,
|
||||
include: /node_modules/,
|
||||
type: "javascript/auto"
|
||||
test: /\.mjs$/,
|
||||
include: /node_modules/,
|
||||
type: 'javascript/auto'
|
||||
},
|
||||
{
|
||||
test: /\.vue$/,
|
||||
|
@ -114,10 +116,8 @@ module.exports = {
|
|||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new VueLoaderPlugin()
|
||||
]
|
||||
plugins: [new VueLoaderPlugin()]
|
||||
}
|
||||
|
|
|
@ -7,7 +7,9 @@ var HtmlWebpackPlugin = require('html-webpack-plugin')
|
|||
|
||||
// add hot-reload related code to entry chunks
|
||||
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
|
||||
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
|
||||
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(
|
||||
baseWebpackConfig.entry[name]
|
||||
)
|
||||
})
|
||||
|
||||
module.exports = merge(baseWebpackConfig, {
|
||||
|
@ -20,10 +22,10 @@ module.exports = merge(baseWebpackConfig, {
|
|||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': config.dev.env,
|
||||
'COMMIT_HASH': JSON.stringify('DEV'),
|
||||
'DEV_OVERRIDES': JSON.stringify(config.dev.settings),
|
||||
'__VUE_OPTIONS_API__': true,
|
||||
'__VUE_PROD_DEVTOOLS__': false
|
||||
COMMIT_HASH: JSON.stringify('DEV'),
|
||||
DEV_OVERRIDES: JSON.stringify(config.dev.settings),
|
||||
__VUE_OPTIONS_API__: true,
|
||||
__VUE_PROD_DEVTOOLS__: false
|
||||
}),
|
||||
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
|
|
|
@ -2,23 +2,27 @@ var path = require('path')
|
|||
var config = require('../config')
|
||||
var utils = require('./utils')
|
||||
var webpack = require('webpack')
|
||||
const WorkboxPlugin = require('workbox-webpack-plugin');
|
||||
const WorkboxPlugin = require('workbox-webpack-plugin')
|
||||
var { merge } = require('webpack-merge')
|
||||
var baseWebpackConfig = require('./webpack.base.conf')
|
||||
var MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
var env = process.env.NODE_ENV === 'testing'
|
||||
var env =
|
||||
process.env.NODE_ENV === 'testing'
|
||||
? require('../config/test.env')
|
||||
: config.build.env
|
||||
|
||||
let commitHash = require('child_process')
|
||||
.execSync('git rev-parse --short HEAD')
|
||||
.toString();
|
||||
.execSync('git rev-parse --short HEAD')
|
||||
.toString()
|
||||
|
||||
var webpackConfig = merge(baseWebpackConfig, {
|
||||
mode: 'production',
|
||||
module: {
|
||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, extract: true })
|
||||
rules: utils.styleLoaders({
|
||||
sourceMap: config.dev.cssSourceMap,
|
||||
extract: true
|
||||
})
|
||||
},
|
||||
devtool: 'source-map',
|
||||
optimization: {
|
||||
|
@ -36,15 +40,15 @@ var webpackConfig = merge(baseWebpackConfig, {
|
|||
new WorkboxPlugin.InjectManifest({
|
||||
swSrc: path.join(__dirname, '..', 'src/sw.js'),
|
||||
swDest: 'sw-pleroma.js',
|
||||
maximumFileSizeToCacheInBytes: 15 * 1024 * 1024,
|
||||
maximumFileSizeToCacheInBytes: 15 * 1024 * 1024
|
||||
}),
|
||||
// http://vuejs.github.io/vue-loader/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env,
|
||||
'COMMIT_HASH': JSON.stringify(commitHash),
|
||||
'DEV_OVERRIDES': JSON.stringify(undefined),
|
||||
'__VUE_OPTIONS_API__': true,
|
||||
'__VUE_PROD_DEVTOOLS__': false
|
||||
COMMIT_HASH: JSON.stringify(commitHash),
|
||||
DEV_OVERRIDES: JSON.stringify(undefined),
|
||||
__VUE_OPTIONS_API__: true,
|
||||
__VUE_PROD_DEVTOOLS__: false
|
||||
}),
|
||||
// extract css into its own file
|
||||
new MiniCssExtractPlugin({
|
||||
|
@ -54,9 +58,8 @@ var webpackConfig = merge(baseWebpackConfig, {
|
|||
// you can customize output by editing /index.html
|
||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: process.env.NODE_ENV === 'testing'
|
||||
? 'index.html'
|
||||
: config.build.index,
|
||||
filename:
|
||||
process.env.NODE_ENV === 'testing' ? 'index.html' : config.build.index,
|
||||
template: 'index.html',
|
||||
inject: true,
|
||||
minify: {
|
||||
|
@ -69,7 +72,7 @@ var webpackConfig = merge(baseWebpackConfig, {
|
|||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'auto'
|
||||
}),
|
||||
})
|
||||
// split vendor js into its own file
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
|
@ -87,9 +90,7 @@ if (config.build.productionGzip) {
|
|||
asset: '[path].gz[query]',
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp(
|
||||
'\\.(' +
|
||||
config.build.productionGzipExtensions.join('|') +
|
||||
')$'
|
||||
'\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
|
||||
),
|
||||
threshold: 10240,
|
||||
minRatio: 0.8
|
||||
|
|
|
@ -38,7 +38,7 @@ module.exports = {
|
|||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
proxyTable: {
|
||||
'/manifest.json': {
|
||||
'/manifest.json': {
|
||||
target,
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: 'localhost'
|
||||
|
@ -59,7 +59,7 @@ module.exports = {
|
|||
cookieDomainRewrite: 'localhost',
|
||||
ws: true,
|
||||
headers: {
|
||||
'Origin': target
|
||||
Origin: target
|
||||
}
|
||||
},
|
||||
'/oauth/revoke': {
|
||||
|
@ -76,7 +76,7 @@ module.exports = {
|
|||
target,
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: 'localhost'
|
||||
},
|
||||
}
|
||||
},
|
||||
// CSS Sourcemaps off by default because relative paths are "buggy"
|
||||
// with this option, according to the CSS-Loader README
|
||||
|
|
48
index.html
48
index.html
|
@ -1,18 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1,user-scalable=no"
|
||||
/>
|
||||
<title>Akkoma</title>
|
||||
<link rel="stylesheet" href="/static/font/css/fontello.css">
|
||||
<link rel="stylesheet" href="/static/font/css/animation.css">
|
||||
<link rel="stylesheet" href="/static/font/tiresias.css">
|
||||
<link rel="stylesheet" href="/static/font/css/lato.css">
|
||||
<link rel="stylesheet" href="/static/mfm.css">
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/font/css/fontello.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/font/css/animation.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/font/tiresias.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/font/css/lato.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/mfm.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/custom.css"
|
||||
/>
|
||||
<!--server-generated-meta-->
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="/favicon.png"
|
||||
/>
|
||||
<link
|
||||
rel="manifest"
|
||||
href="/manifest.json"
|
||||
/>
|
||||
</head>
|
||||
<body class="hidden">
|
||||
<noscript>To use Akkoma, please enable JavaScript.</noscript>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
"extends": ["config:base"]
|
||||
}
|
||||
|
|
|
@ -117,7 +117,6 @@
|
|||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
|
||||
.play-icon {
|
||||
position: absolute;
|
||||
font-size: 64px;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
flex: 0 0 0;
|
||||
max-width: 9em;
|
||||
align-items: stretch;
|
||||
padding: .2em 8px;
|
||||
padding: 0.2em 8px;
|
||||
|
||||
input {
|
||||
background: none;
|
||||
|
@ -40,9 +40,10 @@
|
|||
}
|
||||
.transparentIndicator {
|
||||
// forgot to install counter-strike source, ooops
|
||||
background-color: #FF00FF;
|
||||
background-color: #ff00ff;
|
||||
position: relative;
|
||||
&::before, &::after {
|
||||
&::before,
|
||||
&::after {
|
||||
display: block;
|
||||
content: '';
|
||||
background-color: #000000;
|
||||
|
@ -64,5 +65,4 @@
|
|||
.label {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
display: grid;
|
||||
grid-template-rows: var(--navbar-height);
|
||||
grid-template-columns: 2fr auto 2fr;
|
||||
grid-template-areas: "nav-left logo actions";
|
||||
grid-template-areas: 'nav-left logo actions';
|
||||
box-sizing: border-box;
|
||||
padding: 0 1.2em;
|
||||
margin: auto;
|
||||
|
@ -24,11 +24,12 @@
|
|||
|
||||
&.-logoLeft .inner-nav {
|
||||
grid-template-columns: auto 2fr 2fr;
|
||||
grid-template-areas: "logo nav-left actions";
|
||||
grid-template-areas: 'logo nav-left actions';
|
||||
}
|
||||
|
||||
.button-default {
|
||||
&, svg {
|
||||
&,
|
||||
svg {
|
||||
color: $fallback--text;
|
||||
color: var(--btnTopBarText, $fallback--text);
|
||||
}
|
||||
|
@ -49,7 +50,7 @@
|
|||
color: $fallback--text;
|
||||
color: var(--btnToggledTopBarText, $fallback--text);
|
||||
background-color: $fallback--fg;
|
||||
background-color: var(--btnToggledTopBar, $fallback--fg)
|
||||
background-color: var(--btnToggledTopBar, $fallback--fg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: .4em;
|
||||
padding: 0.4em;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
|
@ -133,7 +133,7 @@
|
|||
}
|
||||
|
||||
.sticker-picker {
|
||||
flex: 1 1 auto
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.stickers,
|
||||
|
@ -168,8 +168,8 @@
|
|||
overflow: auto;
|
||||
user-select: none;
|
||||
mask: linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
|
||||
linear-gradient(to bottom, white 0, transparent 100%) top no-repeat,
|
||||
linear-gradient(to top, white, white);
|
||||
linear-gradient(to bottom, white 0, transparent 100%) top no-repeat,
|
||||
linear-gradient(to top, white, white);
|
||||
transition: mask-size 150ms;
|
||||
mask-size: 100% 20px, 100% 20px, auto;
|
||||
// Autoprefixed seem to ignore this one, and also syntax is different
|
||||
|
@ -221,7 +221,5 @@
|
|||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,19 +2,21 @@
|
|||
margin: 1em;
|
||||
|
||||
table {
|
||||
width:100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding-left:10px;
|
||||
padding-bottom:20px;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 20px;
|
||||
|
||||
th, td {
|
||||
th,
|
||||
td {
|
||||
width: 180px;
|
||||
max-width: 360px;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
th+th, td+td {
|
||||
th + th,
|
||||
td + td {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,21 +74,23 @@
|
|||
&.-striped {
|
||||
& .shortName,
|
||||
& .full {
|
||||
background-image:
|
||||
repeating-linear-gradient(
|
||||
135deg,
|
||||
var(--____highlight-tintColor),
|
||||
var(--____highlight-tintColor) 5px,
|
||||
var(--____highlight-tintColor2) 5px,
|
||||
var(--____highlight-tintColor2) 10px
|
||||
);
|
||||
background-image: repeating-linear-gradient(
|
||||
135deg,
|
||||
var(--____highlight-tintColor),
|
||||
var(--____highlight-tintColor) 5px,
|
||||
var(--____highlight-tintColor2) 5px,
|
||||
var(--____highlight-tintColor2) 10px
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
&.-solid {
|
||||
& .shortName,
|
||||
& .full {
|
||||
background-image: linear-gradient(var(--____highlight-tintColor2), var(--____highlight-tintColor2));
|
||||
background-image: linear-gradient(
|
||||
var(--____highlight-tintColor2),
|
||||
var(--____highlight-tintColor2)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
margin: 1em 1em 1.4em;
|
||||
|
||||
> div {
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -2,19 +2,21 @@
|
|||
margin: 1em;
|
||||
|
||||
table {
|
||||
width:100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding-left:10px;
|
||||
padding-bottom:20px;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 20px;
|
||||
|
||||
th, td {
|
||||
th,
|
||||
td {
|
||||
width: 180px;
|
||||
max-width: 360px;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
th+th, td+td {
|
||||
th + th,
|
||||
td + td {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
|
||||
// TODO Copypaste from Status, should unify it somehow
|
||||
.Notification {
|
||||
border-bottom: 1px solid;
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
--emoji-size: 14px;
|
||||
border-bottom: 1px solid;
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
--emoji-size: 14px;
|
||||
|
||||
&:hover {
|
||||
--_still-image-img-visibility: visible;
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import { unescape, flattenDeep } from 'lodash'
|
||||
import { getTagName, processTextForEmoji, getAttrs } from 'src/services/html_converter/utility.service.js'
|
||||
import {
|
||||
getTagName,
|
||||
processTextForEmoji,
|
||||
getAttrs
|
||||
} from 'src/services/html_converter/utility.service.js'
|
||||
import { convertHtmlToTree } from 'src/services/html_converter/html_tree_converter.service.js'
|
||||
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
||||
import StillImage from 'src/components/still-image/still-image.vue'
|
||||
import MentionsLine, { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.vue'
|
||||
import MentionsLine, {
|
||||
MENTIONS_LIMIT
|
||||
} from 'src/components/mentions_line/mentions_line.vue'
|
||||
import HashtagLink from 'src/components/hashtag_link/hashtag_link.vue'
|
||||
|
||||
import './rich_content.scss'
|
||||
|
@ -67,7 +73,7 @@ export default {
|
|||
}
|
||||
},
|
||||
// NEVER EVER TOUCH DATA INSIDE RENDER
|
||||
render () {
|
||||
render() {
|
||||
// Don't greentext MFM
|
||||
const greentext = this.mfm ? false : this.greentext
|
||||
|
||||
|
@ -87,10 +93,12 @@ export default {
|
|||
let tagsIndex = 0
|
||||
|
||||
const renderImage = (tag) => {
|
||||
return <StillImage
|
||||
{...getAttrs(tag)}
|
||||
class="img"
|
||||
/>
|
||||
return (
|
||||
<StillImage
|
||||
{...getAttrs(tag)}
|
||||
class="img"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const renderHashtag = (attrs, children, encounteredTextReverse) => {
|
||||
|
@ -100,12 +108,20 @@ export default {
|
|||
lastTags.push(linkData)
|
||||
}
|
||||
const { url, tag, content } = linkData
|
||||
return <HashtagLink url={url} tag={tag} content={content}/>
|
||||
return (
|
||||
<HashtagLink
|
||||
url={url}
|
||||
tag={tag}
|
||||
content={content}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const renderMention = (attrs, children) => {
|
||||
const linkData = getLinkData(attrs, children, mentionIndex++)
|
||||
linkData.notifying = this.attentions.some(a => a.statusnet_profile_url === linkData.url)
|
||||
linkData.notifying = this.attentions.some(
|
||||
(a) => a.statusnet_profile_url === linkData.url
|
||||
)
|
||||
writtenMentions.push(linkData)
|
||||
if (currentMentions === null) {
|
||||
currentMentions = []
|
||||
|
@ -115,7 +131,7 @@ export default {
|
|||
invisibleMentions.push(linkData)
|
||||
}
|
||||
if (currentMentions.length === 1) {
|
||||
return <MentionsLine mentions={ currentMentions } />
|
||||
return <MentionsLine mentions={currentMentions} />
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
|
@ -134,23 +150,26 @@ export default {
|
|||
// in MentionsLine
|
||||
lastSpacing = item
|
||||
// Don't remove last space in a container (fixes poast mentions)
|
||||
return (index !== array.length - 1) && (currentMentions !== null) ? item.trim() : item
|
||||
return index !== array.length - 1 && currentMentions !== null
|
||||
? item.trim()
|
||||
: item
|
||||
}
|
||||
|
||||
currentMentions = null
|
||||
if (item.includes(':')) {
|
||||
item = ['', processTextForEmoji(
|
||||
item,
|
||||
this.emoji,
|
||||
({ shortcode, url }) => {
|
||||
return <StillImage
|
||||
class="emoji img"
|
||||
src={url}
|
||||
title={`:${shortcode}:`}
|
||||
alt={`:${shortcode}:`}
|
||||
/>
|
||||
}
|
||||
)]
|
||||
item = [
|
||||
'',
|
||||
processTextForEmoji(item, this.emoji, ({ shortcode, url }) => {
|
||||
return (
|
||||
<StillImage
|
||||
class="emoji img"
|
||||
src={url}
|
||||
title={`:${shortcode}:`}
|
||||
alt={`:${shortcode}:`}
|
||||
/>
|
||||
)
|
||||
})
|
||||
]
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
@ -166,12 +185,16 @@ export default {
|
|||
* we have a tag right next to mentions
|
||||
*/
|
||||
const mentionsLinePadding =
|
||||
// Padding is only needed if we just finished parsing mentions
|
||||
previouslyMentions &&
|
||||
// Don't add padding if content is string and has padding already
|
||||
!(children && typeof children[0] === 'string' && children[0].match(/^\s/))
|
||||
? lastSpacing
|
||||
: ''
|
||||
// Padding is only needed if we just finished parsing mentions
|
||||
previouslyMentions &&
|
||||
// Don't add padding if content is string and has padding already
|
||||
!(
|
||||
children &&
|
||||
typeof children[0] === 'string' &&
|
||||
children[0].match(/^\s/)
|
||||
)
|
||||
? lastSpacing
|
||||
: ''
|
||||
switch (Tag) {
|
||||
case 'br':
|
||||
currentMentions = null
|
||||
|
@ -188,7 +211,11 @@ export default {
|
|||
break
|
||||
}
|
||||
case 'span':
|
||||
if (this.handleLinks && attrs['class'] && attrs['class'].includes('h-card')) {
|
||||
if (
|
||||
this.handleLinks &&
|
||||
attrs['class'] &&
|
||||
attrs['class'].includes('h-card')
|
||||
) {
|
||||
return ['', children.map(processItem), '']
|
||||
}
|
||||
}
|
||||
|
@ -196,10 +223,7 @@ export default {
|
|||
if (children !== undefined) {
|
||||
return [
|
||||
'',
|
||||
[
|
||||
mentionsLinePadding,
|
||||
[opener, children.map(processItem), closer]
|
||||
],
|
||||
[mentionsLinePadding, [opener, children.map(processItem), closer]],
|
||||
''
|
||||
]
|
||||
} else {
|
||||
|
@ -228,16 +252,17 @@ export default {
|
|||
// should only be this
|
||||
if (
|
||||
(attrs['class'] && attrs['class'].includes('hashtag')) || // Pleroma style
|
||||
(attrs['rel'] === 'tag') // Mastodon style
|
||||
attrs['rel'] === 'tag' // Mastodon style
|
||||
) {
|
||||
return renderHashtag(attrs, children, encounteredTextReverse)
|
||||
} else {
|
||||
attrs.target = '_blank'
|
||||
const newChildren = [...children].reverse().map(processItemReverse).reverse()
|
||||
const newChildren = [...children]
|
||||
.reverse()
|
||||
.map(processItemReverse)
|
||||
.reverse()
|
||||
|
||||
return <a {...attrs}>
|
||||
{ newChildren }
|
||||
</a>
|
||||
return <a {...attrs}>{newChildren}</a>
|
||||
}
|
||||
case '':
|
||||
return [...children].reverse().map(processItemReverse).reverse()
|
||||
|
@ -248,11 +273,9 @@ export default {
|
|||
const newChildren = Array.isArray(children)
|
||||
? [...children].reverse().map(processItemReverse).reverse()
|
||||
: children
|
||||
return <Tag {...getAttrs(opener)}>
|
||||
{ newChildren }
|
||||
</Tag>
|
||||
return <Tag {...getAttrs(opener)}>{newChildren}</Tag>
|
||||
} else {
|
||||
return <Tag/>
|
||||
return <Tag />
|
||||
}
|
||||
}
|
||||
return item
|
||||
|
@ -263,9 +286,7 @@ export default {
|
|||
// DO NOT USE SLOTS they cause a re-render feedback loop here.
|
||||
// slots updated -> rerender -> emit -> update up the tree -> rerender -> ...
|
||||
// at least until vue3?
|
||||
const result = <span class="RichContent">
|
||||
{ pass2 }
|
||||
</span>
|
||||
const result = <span class="RichContent">{pass2}</span>
|
||||
|
||||
const event = {
|
||||
lastTags,
|
||||
|
@ -311,31 +332,36 @@ export const preProcessPerLine = (html, greentext) => {
|
|||
const greentextHandle = new Set(['p', 'div'])
|
||||
|
||||
const lines = convertHtmlToLines(html)
|
||||
const newHtml = lines.reverse().map((item, index, array) => {
|
||||
if (!item.text) return item
|
||||
const string = item.text
|
||||
const newHtml = lines
|
||||
.reverse()
|
||||
.map((item, index, array) => {
|
||||
if (!item.text) return item
|
||||
const string = item.text
|
||||
|
||||
// Greentext stuff
|
||||
if (
|
||||
// Only if greentext is engaged
|
||||
greentext &&
|
||||
// Greentext stuff
|
||||
if (
|
||||
// Only if greentext is engaged
|
||||
greentext &&
|
||||
// Only handle p's and divs. Don't want to affect blockquotes, code etc
|
||||
item.level.every(l => greentextHandle.has(l)) &&
|
||||
item.level.every((l) => greentextHandle.has(l)) &&
|
||||
// Only if line begins with '>' or '<'
|
||||
(string.includes('>') || string.includes('<'))
|
||||
) {
|
||||
const cleanedString = string.replace(/<[^>]+?>/gi, '') // remove all tags
|
||||
.replace(/@\w+/gi, '') // remove mentions (even failed ones)
|
||||
.trim()
|
||||
if (cleanedString.startsWith('>')) {
|
||||
return `<span class='greentext'>${string}</span>`
|
||||
} else if (cleanedString.startsWith('<')) {
|
||||
return `<span class='cyantext'>${string}</span>`
|
||||
) {
|
||||
const cleanedString = string
|
||||
.replace(/<[^>]+?>/gi, '') // remove all tags
|
||||
.replace(/@\w+/gi, '') // remove mentions (even failed ones)
|
||||
.trim()
|
||||
if (cleanedString.startsWith('>')) {
|
||||
return `<span class='greentext'>${string}</span>`
|
||||
} else if (cleanedString.startsWith('<')) {
|
||||
return `<span class='cyantext'>${string}</span>`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string
|
||||
}).reverse().join('')
|
||||
return string
|
||||
})
|
||||
.reverse()
|
||||
.join('')
|
||||
|
||||
return { newHtml }
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
margin-bottom: 0.5em;
|
||||
}
|
||||
.suboptions {
|
||||
margin-top: 0.3em
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
>.panel-body {
|
||||
> .panel-body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
|||
|
||||
.settings-footer {
|
||||
display: flex;
|
||||
>* {
|
||||
> * {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
> div,
|
||||
> label {
|
||||
display: block;
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
.option-list {
|
||||
margin: 0;
|
||||
padding-left: .5em;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
.mutes-and-blocks-tab {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
|
||||
.usersearch-wrapper {
|
||||
padding: 1em;
|
||||
}
|
||||
.usersearch-wrapper {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.bulk-actions {
|
||||
text-align: right;
|
||||
padding: 0 1em;
|
||||
min-height: 2em;
|
||||
}
|
||||
.bulk-actions {
|
||||
text-align: right;
|
||||
padding: 0 1em;
|
||||
min-height: 2em;
|
||||
}
|
||||
|
||||
.bulk-action-button {
|
||||
width: 10em
|
||||
}
|
||||
.bulk-action-button {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.domain-mute-form {
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
flex-direction: column
|
||||
}
|
||||
.domain-mute-form {
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.domain-mute-button {
|
||||
align-self: flex-end;
|
||||
margin-top: 1em;
|
||||
width: 10em
|
||||
}
|
||||
.domain-mute-button {
|
||||
align-self: flex-end;
|
||||
margin-top: 1em;
|
||||
width: 10em;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
padding-top: 5px;
|
||||
}
|
||||
|
||||
input[type=file] {
|
||||
input[type='file'] {
|
||||
padding: 5px;
|
||||
height: auto;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
.theme-warning {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
.buttons {
|
||||
.btn {
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,29 +25,31 @@
|
|||
}
|
||||
|
||||
&.disabled {
|
||||
input, select {
|
||||
opacity: .5
|
||||
input,
|
||||
select {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.opt {
|
||||
margin: .5em;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
.color-input {
|
||||
flex: 0 0 0;
|
||||
}
|
||||
|
||||
input, select {
|
||||
input,
|
||||
select {
|
||||
min-width: 3em;
|
||||
margin: 0;
|
||||
flex: 0;
|
||||
|
||||
&[type=number] {
|
||||
&[type='number'] {
|
||||
min-width: 5em;
|
||||
}
|
||||
|
||||
&[type=range] {
|
||||
&[type='range'] {
|
||||
flex: 1;
|
||||
min-width: 3em;
|
||||
align-self: flex-start;
|
||||
|
@ -63,8 +65,7 @@
|
|||
.reset-container,
|
||||
.apply-container,
|
||||
.radius-container,
|
||||
.color-container,
|
||||
{
|
||||
.color-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,7 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.color-container{
|
||||
.color-container {
|
||||
> h4 {
|
||||
width: 99%;
|
||||
}
|
||||
|
@ -100,7 +101,7 @@
|
|||
p {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
margin-right: .5em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,14 +113,14 @@
|
|||
min-width: 1px;
|
||||
flex: 0 auto;
|
||||
padding: 0 1em;
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.shadow-selector {
|
||||
.override {
|
||||
flex: 1;
|
||||
margin-left: .5em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.select-container {
|
||||
margin-top: -4px;
|
||||
|
@ -136,7 +137,7 @@
|
|||
|
||||
.presets,
|
||||
.import-export {
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.import-export {
|
||||
|
@ -144,16 +145,16 @@
|
|||
}
|
||||
|
||||
.override {
|
||||
margin-left: .5em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.save-load-options {
|
||||
flex-wrap: wrap;
|
||||
margin-top: .5em;
|
||||
margin-top: 0.5em;
|
||||
justify-content: center;
|
||||
.keep-option {
|
||||
margin: 0 .5em .5em;
|
||||
margin: 0 0.5em 0.5em;
|
||||
min-width: 25%;
|
||||
}
|
||||
}
|
||||
|
@ -179,11 +180,11 @@
|
|||
flex: 1;
|
||||
|
||||
h4 {
|
||||
margin-bottom: .25em;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.icons {
|
||||
margin-top: .5em;
|
||||
margin-top: 0.5em;
|
||||
display: flex;
|
||||
|
||||
i {
|
||||
|
@ -199,8 +200,19 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar, .avatar-alt{
|
||||
background: linear-gradient(135deg, #b8e1fc 0%,#a9d2f3 10%,#90bae4 25%,#90bcea 37%,#90bff0 50%,#6ba8e5 51%,#a2daf5 83%,#bdf3fd 100%);
|
||||
.avatar,
|
||||
.avatar-alt {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
#b8e1fc 0%,
|
||||
#a9d2f3 10%,
|
||||
#90bae4 25%,
|
||||
#90bcea 37%,
|
||||
#90bff0 50%,
|
||||
#6ba8e5 51%,
|
||||
#a2daf5 83%,
|
||||
#bdf3fd 100%
|
||||
);
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
|
@ -255,21 +267,21 @@
|
|||
.color-item {
|
||||
min-width: 20em;
|
||||
margin: 5px 6px 0 0;
|
||||
display:flex;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 0;
|
||||
|
||||
&.wide {
|
||||
min-width: 60%
|
||||
min-width: 60%;
|
||||
}
|
||||
|
||||
&:not(.wide):nth-child(2n+1) {
|
||||
&:not(.wide):nth-child(2n + 1) {
|
||||
margin-right: 7px;
|
||||
|
||||
}
|
||||
|
||||
.color, .opacity {
|
||||
display:flex;
|
||||
.color,
|
||||
.opacity {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
}
|
||||
|
@ -301,7 +313,7 @@
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
.theme-radius-lb{
|
||||
.theme-radius-lb {
|
||||
max-width: 50em;
|
||||
}
|
||||
|
||||
|
@ -310,8 +322,8 @@
|
|||
}
|
||||
|
||||
.btn {
|
||||
margin-left: .25em;
|
||||
margin-right: .25em;
|
||||
margin-left: 0.25em;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,8 +105,8 @@
|
|||
|
||||
.media-body-wrapper {
|
||||
min-height: 0;
|
||||
mask:
|
||||
linear-gradient(to top, white, transparent) bottom/100% 70px no-repeat,
|
||||
mask: linear-gradient(to top, white, transparent) bottom/100% 70px
|
||||
no-repeat,
|
||||
linear-gradient(to top, white, white);
|
||||
|
||||
/* Autoprefixed seem to ignore this one, and also syntax is different */
|
||||
|
@ -210,4 +210,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { FontAwesomeIcon as FAIcon } from '@fortawesome/vue-fontawesome'
|
|||
|
||||
import './tab_switcher.scss'
|
||||
|
||||
const findFirstUsable = (slots) => slots.findIndex(_ => _.props)
|
||||
const findFirstUsable = (slots) => slots.findIndex((_) => _.props)
|
||||
|
||||
export default {
|
||||
name: 'TabSwitcher',
|
||||
|
@ -41,58 +41,61 @@ export default {
|
|||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
active: findFirstUsable(this.slots())
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activeIndex () {
|
||||
activeIndex() {
|
||||
// In case of controlled component
|
||||
if (this.activeTab) {
|
||||
return this.slots().findIndex(slot => slot && slot.props && this.activeTab === slot.props.key)
|
||||
return this.slots().findIndex(
|
||||
(slot) => slot && slot.props && this.activeTab === slot.props.key
|
||||
)
|
||||
} else {
|
||||
return this.active
|
||||
}
|
||||
},
|
||||
isActive () {
|
||||
return tabName => {
|
||||
const isWanted = slot => slot.props && slot.props['data-tab-name'] === tabName
|
||||
isActive() {
|
||||
return (tabName) => {
|
||||
const isWanted = (slot) =>
|
||||
slot.props && slot.props['data-tab-name'] === tabName
|
||||
return this.$slots.default().findIndex(isWanted) === this.activeIndex
|
||||
}
|
||||
},
|
||||
settingsModalVisible () {
|
||||
settingsModalVisible() {
|
||||
return this.settingsModalState === 'visible'
|
||||
},
|
||||
modModalVisible () {
|
||||
modModalVisible() {
|
||||
return this.modModalState === 'visible'
|
||||
},
|
||||
...mapState({
|
||||
settingsModalState: state => state.interface.settingsModalState,
|
||||
modModalState: state => state.interface.modModalState
|
||||
settingsModalState: (state) => state.interface.settingsModalState,
|
||||
modModalState: (state) => state.interface.modModalState
|
||||
})
|
||||
},
|
||||
beforeUpdate () {
|
||||
beforeUpdate() {
|
||||
const currentSlot = this.slots()[this.active]
|
||||
if (!currentSlot.props) {
|
||||
this.active = findFirstUsable(this.slots())
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickTab (index) {
|
||||
clickTab(index) {
|
||||
return (e) => {
|
||||
e.preventDefault()
|
||||
this.setTab(index)
|
||||
}
|
||||
},
|
||||
// DO NOT put it to computed, it doesn't work (caching?)
|
||||
slots () {
|
||||
slots() {
|
||||
if (this.$slots.default()[0].type === Fragment) {
|
||||
return this.$slots.default()[0].children
|
||||
}
|
||||
return this.$slots.default()
|
||||
},
|
||||
setTab (index) {
|
||||
setTab(index) {
|
||||
if (typeof this.onSwitch === 'function') {
|
||||
this.onSwitch.call(null, this.slots()[index].key)
|
||||
}
|
||||
|
@ -102,32 +105,17 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const tabs = this.slots()
|
||||
.map((slot, index) => {
|
||||
const props = slot.props
|
||||
if (!props) return
|
||||
const classesTab = ['tab', 'button-default']
|
||||
const classesWrapper = ['tab-wrapper']
|
||||
if (this.activeIndex === index) {
|
||||
classesTab.push('active')
|
||||
classesWrapper.push('active')
|
||||
}
|
||||
if (props.image) {
|
||||
return (
|
||||
<div class={classesWrapper.join(' ')}>
|
||||
<button
|
||||
disabled={props.disabled}
|
||||
onClick={this.clickTab(index)}
|
||||
class={classesTab.join(' ')}
|
||||
type="button"
|
||||
>
|
||||
<img src={props.image} title={props['image-tooltip']}/>
|
||||
{props.label ? '' : props.label}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
render() {
|
||||
const tabs = this.slots().map((slot, index) => {
|
||||
const props = slot.props
|
||||
if (!props) return
|
||||
const classesTab = ['tab', 'button-default']
|
||||
const classesWrapper = ['tab-wrapper']
|
||||
if (this.activeIndex === index) {
|
||||
classesTab.push('active')
|
||||
classesWrapper.push('active')
|
||||
}
|
||||
if (props.image) {
|
||||
return (
|
||||
<div class={classesWrapper.join(' ')}>
|
||||
<button
|
||||
|
@ -136,44 +124,62 @@ export default {
|
|||
class={classesTab.join(' ')}
|
||||
type="button"
|
||||
>
|
||||
{!props.icon ? '' : (<FAIcon class="tab-icon" size="2x" fixed-width icon={props.icon}/>)}
|
||||
<span class="text">
|
||||
{props.label}
|
||||
</span>
|
||||
<img
|
||||
src={props.image}
|
||||
title={props['image-tooltip']}
|
||||
/>
|
||||
{props.label ? '' : props.label}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div class={classesWrapper.join(' ')}>
|
||||
<button
|
||||
disabled={props.disabled}
|
||||
onClick={this.clickTab(index)}
|
||||
class={classesTab.join(' ')}
|
||||
type="button"
|
||||
>
|
||||
{!props.icon ? (
|
||||
''
|
||||
) : (
|
||||
<FAIcon
|
||||
class="tab-icon"
|
||||
size="2x"
|
||||
fixed-width
|
||||
icon={props.icon}
|
||||
/>
|
||||
)}
|
||||
<span class="text">{props.label}</span>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const contents = this.slots().map((slot, index) => {
|
||||
const props = slot.props
|
||||
if (!props) return
|
||||
const active = this.activeIndex === index
|
||||
const classes = [ active ? 'active' : 'hidden' ]
|
||||
const classes = [active ? 'active' : 'hidden']
|
||||
if (props.fullHeight) {
|
||||
classes.push('full-height')
|
||||
}
|
||||
const renderSlot = (!this.renderOnlyFocused || active)
|
||||
? slot
|
||||
: ''
|
||||
const renderSlot = !this.renderOnlyFocused || active ? slot : ''
|
||||
|
||||
return (
|
||||
<div class={classes}>
|
||||
{
|
||||
this.sideTabBar
|
||||
? <h1 class="mobile-label">{props.label}</h1>
|
||||
: ''
|
||||
}
|
||||
{this.sideTabBar ? <h1 class="mobile-label">{props.label}</h1> : ''}
|
||||
{renderSlot}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<div class={'tab-switcher ' + (this.sideTabBar ? 'side-tabs' : 'top-tabs')}>
|
||||
<div class="tabs">
|
||||
{tabs}
|
||||
</div>
|
||||
<div
|
||||
class={'tab-switcher ' + (this.sideTabBar ? 'side-tabs' : 'top-tabs')}
|
||||
>
|
||||
<div class="tabs">{tabs}</div>
|
||||
<div
|
||||
ref="contents"
|
||||
class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
}
|
||||
|
||||
.timeline-heading {
|
||||
.button-default, .alert {
|
||||
.button-default,
|
||||
.alert {
|
||||
line-height: 2em;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -6,104 +6,113 @@ import './with_load_more.scss'
|
|||
|
||||
import { FontAwesomeIcon as FAIcon } from '@fortawesome/vue-fontawesome'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
faCircleNotch
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
faCircleNotch
|
||||
)
|
||||
library.add(faCircleNotch)
|
||||
|
||||
const withLoadMore = ({
|
||||
fetch, // function to fetch entries and return a promise
|
||||
select, // function to select data from store
|
||||
unmounted, // function called at "destroyed" lifecycle
|
||||
childPropName = 'entries', // name of the prop to be passed into the wrapped component
|
||||
additionalPropNames = [] // additional prop name list of the wrapper component
|
||||
}) => (WrappedComponent) => {
|
||||
const originalProps = Object.keys(getComponentProps(WrappedComponent))
|
||||
const props = originalProps.filter(v => v !== childPropName).concat(additionalPropNames)
|
||||
const withLoadMore =
|
||||
({
|
||||
fetch, // function to fetch entries and return a promise
|
||||
select, // function to select data from store
|
||||
unmounted, // function called at "destroyed" lifecycle
|
||||
childPropName = 'entries', // name of the prop to be passed into the wrapped component
|
||||
additionalPropNames = [] // additional prop name list of the wrapper component
|
||||
}) =>
|
||||
(WrappedComponent) => {
|
||||
const originalProps = Object.keys(getComponentProps(WrappedComponent))
|
||||
const props = originalProps
|
||||
.filter((v) => v !== childPropName)
|
||||
.concat(additionalPropNames)
|
||||
|
||||
return {
|
||||
props,
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
bottomedOut: false,
|
||||
error: false,
|
||||
entries: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('scroll', this.scrollLoad)
|
||||
if (this.entries.length === 0) {
|
||||
this.fetchEntries()
|
||||
}
|
||||
},
|
||||
unmounted () {
|
||||
window.removeEventListener('scroll', this.scrollLoad)
|
||||
unmounted && unmounted(this.$props, this.$store)
|
||||
},
|
||||
methods: {
|
||||
// Entries is not a computed because computed can't track the dynamic
|
||||
// selector for changes and won't trigger after fetch.
|
||||
updateEntries () {
|
||||
this.entries = select(this.$props, this.$store) || []
|
||||
},
|
||||
fetchEntries () {
|
||||
if (!this.loading) {
|
||||
this.loading = true
|
||||
this.error = false
|
||||
fetch(this.$props, this.$store)
|
||||
.then((newEntries) => {
|
||||
this.loading = false
|
||||
this.bottomedOut = isEmpty(newEntries)
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
this.error = true
|
||||
})
|
||||
.finally(() => {
|
||||
this.updateEntries()
|
||||
})
|
||||
return {
|
||||
props,
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
bottomedOut: false,
|
||||
error: false,
|
||||
entries: []
|
||||
}
|
||||
},
|
||||
scrollLoad (e) {
|
||||
const bodyBRect = document.body.getBoundingClientRect()
|
||||
const height = Math.max(bodyBRect.height, -(bodyBRect.y))
|
||||
if (this.loading === false &&
|
||||
this.bottomedOut === false &&
|
||||
this.$el.offsetHeight > 0 &&
|
||||
(window.innerHeight + window.pageYOffset) >= (height - 750)
|
||||
) {
|
||||
created() {
|
||||
window.addEventListener('scroll', this.scrollLoad)
|
||||
if (this.entries.length === 0) {
|
||||
this.fetchEntries()
|
||||
}
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const props = {
|
||||
...this.$props,
|
||||
[childPropName]: this.entries
|
||||
}
|
||||
const children = this.$slots
|
||||
return (
|
||||
<div class="with-load-more">
|
||||
<WrappedComponent {...props}>
|
||||
{children}
|
||||
</WrappedComponent>
|
||||
<div class="with-load-more-footer">
|
||||
{this.error &&
|
||||
<button onClick={this.fetchEntries} class="button-unstyled -link -fullwidth alert error">
|
||||
{this.$t('general.generic_error')}
|
||||
</button>
|
||||
}
|
||||
{!this.error && this.loading && <FAIcon spin icon="circle-notch"/>}
|
||||
{!this.error && !this.loading && !this.bottomedOut && <a onClick={this.fetchEntries}>{this.$t('general.more')}</a>}
|
||||
},
|
||||
unmounted() {
|
||||
window.removeEventListener('scroll', this.scrollLoad)
|
||||
unmounted && unmounted(this.$props, this.$store)
|
||||
},
|
||||
methods: {
|
||||
// Entries is not a computed because computed can't track the dynamic
|
||||
// selector for changes and won't trigger after fetch.
|
||||
updateEntries() {
|
||||
this.entries = select(this.$props, this.$store) || []
|
||||
},
|
||||
fetchEntries() {
|
||||
if (!this.loading) {
|
||||
this.loading = true
|
||||
this.error = false
|
||||
fetch(this.$props, this.$store)
|
||||
.then((newEntries) => {
|
||||
this.loading = false
|
||||
this.bottomedOut = isEmpty(newEntries)
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
this.error = true
|
||||
})
|
||||
.finally(() => {
|
||||
this.updateEntries()
|
||||
})
|
||||
}
|
||||
},
|
||||
scrollLoad(e) {
|
||||
const bodyBRect = document.body.getBoundingClientRect()
|
||||
const height = Math.max(bodyBRect.height, -bodyBRect.y)
|
||||
if (
|
||||
this.loading === false &&
|
||||
this.bottomedOut === false &&
|
||||
this.$el.offsetHeight > 0 &&
|
||||
window.innerHeight + window.pageYOffset >= height - 750
|
||||
) {
|
||||
this.fetchEntries()
|
||||
}
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const props = {
|
||||
...this.$props,
|
||||
[childPropName]: this.entries
|
||||
}
|
||||
const children = this.$slots
|
||||
return (
|
||||
<div class="with-load-more">
|
||||
<WrappedComponent {...props}>{children}</WrappedComponent>
|
||||
<div class="with-load-more-footer">
|
||||
{this.error && (
|
||||
<button
|
||||
onClick={this.fetchEntries}
|
||||
class="button-unstyled -link -fullwidth alert error"
|
||||
>
|
||||
{this.$t('general.generic_error')}
|
||||
</button>
|
||||
)}
|
||||
{!this.error && this.loading && (
|
||||
<FAIcon
|
||||
spin
|
||||
icon="circle-notch"
|
||||
/>
|
||||
)}
|
||||
{!this.error && !this.loading && !this.bottomedOut && (
|
||||
<a onClick={this.fetchEntries}>{this.$t('general.more')}</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default withLoadMore
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.with-load-more {
|
||||
|
|
|
@ -6,86 +6,93 @@ import './with_subscription.scss'
|
|||
|
||||
import { FontAwesomeIcon as FAIcon } from '@fortawesome/vue-fontawesome'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
faCircleNotch
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
faCircleNotch
|
||||
)
|
||||
library.add(faCircleNotch)
|
||||
|
||||
const withSubscription = ({
|
||||
fetch, // function to fetch entries and return a promise
|
||||
select, // function to select data from store
|
||||
childPropName = 'content', // name of the prop to be passed into the wrapped component
|
||||
additionalPropNames = [] // additional prop name list of the wrapper component
|
||||
}) => (WrappedComponent) => {
|
||||
const originalProps = Object.keys(getComponentProps(WrappedComponent))
|
||||
const props = originalProps.filter(v => v !== childPropName).concat(additionalPropNames)
|
||||
const withSubscription =
|
||||
({
|
||||
fetch, // function to fetch entries and return a promise
|
||||
select, // function to select data from store
|
||||
childPropName = 'content', // name of the prop to be passed into the wrapped component
|
||||
additionalPropNames = [] // additional prop name list of the wrapper component
|
||||
}) =>
|
||||
(WrappedComponent) => {
|
||||
const originalProps = Object.keys(getComponentProps(WrappedComponent))
|
||||
const props = originalProps
|
||||
.filter((v) => v !== childPropName)
|
||||
.concat(additionalPropNames)
|
||||
|
||||
return {
|
||||
props: [
|
||||
...props,
|
||||
'refresh' // boolean saying to force-fetch data whenever created
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
error: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fetchedData () {
|
||||
return select(this.$props, this.$store)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.refresh || isEmpty(this.fetchedData)) {
|
||||
this.fetchData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
if (!this.loading) {
|
||||
this.loading = true
|
||||
this.error = false
|
||||
fetch(this.$props, this.$store)
|
||||
.then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.error = true
|
||||
this.loading = false
|
||||
})
|
||||
return {
|
||||
props: [
|
||||
...props,
|
||||
'refresh' // boolean saying to force-fetch data whenever created
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
error: false
|
||||
}
|
||||
}
|
||||
},
|
||||
render () {
|
||||
if (!this.error && !this.loading) {
|
||||
const props = {
|
||||
...this.$props,
|
||||
[childPropName]: this.fetchedData
|
||||
},
|
||||
computed: {
|
||||
fetchedData() {
|
||||
return select(this.$props, this.$store)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.refresh || isEmpty(this.fetchedData)) {
|
||||
this.fetchData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
if (!this.loading) {
|
||||
this.loading = true
|
||||
this.error = false
|
||||
fetch(this.$props, this.$store)
|
||||
.then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.error = true
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
render() {
|
||||
if (!this.error && !this.loading) {
|
||||
const props = {
|
||||
...this.$props,
|
||||
[childPropName]: this.fetchedData
|
||||
}
|
||||
const children = this.$slots
|
||||
return (
|
||||
<div class="with-subscription">
|
||||
<WrappedComponent {...props}>{children}</WrappedComponent>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div class="with-subscription-loading">
|
||||
{this.error ? (
|
||||
<a
|
||||
onClick={this.fetchData}
|
||||
class="alert error"
|
||||
>
|
||||
{this.$t('general.generic_error')}
|
||||
</a>
|
||||
) : (
|
||||
<FAIcon
|
||||
spin
|
||||
icon="circle-notch"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const children = this.$slots
|
||||
return (
|
||||
<div class="with-subscription">
|
||||
<WrappedComponent {...props}>
|
||||
{children}
|
||||
</WrappedComponent>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div class="with-subscription-loading">
|
||||
{this.error
|
||||
? <a onClick={this.fetchData} class="alert error">{this.$t('general.generic_error')}</a>
|
||||
: <FAIcon spin icon="circle-notch"/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default withSubscription
|
||||
|
|
|
@ -17,10 +17,14 @@ exports.assertion = function (selector, count) {
|
|||
}
|
||||
this.command = function (cb) {
|
||||
var self = this
|
||||
return this.api.execute(function (selector) {
|
||||
return document.querySelectorAll(selector).length
|
||||
}, [selector], function (res) {
|
||||
cb.call(self, res)
|
||||
})
|
||||
return this.api.execute(
|
||||
function (selector) {
|
||||
return document.querySelectorAll(selector).length
|
||||
},
|
||||
[selector],
|
||||
function (res) {
|
||||
cb.call(self, res)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,43 +3,45 @@ var config = require('../../config')
|
|||
|
||||
// http://nightwatchjs.org/guide#settings-file
|
||||
module.exports = {
|
||||
'src_folders': ['test/e2e/specs'],
|
||||
'output_folder': 'test/e2e/reports',
|
||||
'custom_assertions_path': ['test/e2e/custom-assertions'],
|
||||
src_folders: ['test/e2e/specs'],
|
||||
output_folder: 'test/e2e/reports',
|
||||
custom_assertions_path: ['test/e2e/custom-assertions'],
|
||||
|
||||
'selenium': {
|
||||
'start_process': true,
|
||||
'server_path': 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar',
|
||||
'host': '127.0.0.1',
|
||||
'port': 4444,
|
||||
'cli_args': {
|
||||
selenium: {
|
||||
start_process: true,
|
||||
server_path:
|
||||
'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar',
|
||||
host: '127.0.0.1',
|
||||
port: 4444,
|
||||
cli_args: {
|
||||
'webdriver.chrome.driver': require('chromedriver').path
|
||||
}
|
||||
},
|
||||
|
||||
'test_settings': {
|
||||
'default': {
|
||||
'selenium_port': 4444,
|
||||
'selenium_host': 'localhost',
|
||||
'silent': true,
|
||||
'globals': {
|
||||
'devServerURL': 'http://localhost:' + (process.env.PORT || config.dev.port)
|
||||
test_settings: {
|
||||
default: {
|
||||
selenium_port: 4444,
|
||||
selenium_host: 'localhost',
|
||||
silent: true,
|
||||
globals: {
|
||||
devServerURL:
|
||||
'http://localhost:' + (process.env.PORT || config.dev.port)
|
||||
}
|
||||
},
|
||||
|
||||
'chrome': {
|
||||
'desiredCapabilities': {
|
||||
'browserName': 'chrome',
|
||||
'javascriptEnabled': true,
|
||||
'acceptSslCerts': true
|
||||
chrome: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true
|
||||
}
|
||||
},
|
||||
|
||||
'firefox': {
|
||||
'desiredCapabilities': {
|
||||
'browserName': 'firefox',
|
||||
'javascriptEnabled': true,
|
||||
'acceptSslCerts': true
|
||||
firefox: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'firefox',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2059
test/fixtures/mastoapi.json
vendored
2059
test/fixtures/mastoapi.json
vendored
File diff suppressed because it is too large
Load diff
564
test/fixtures/statuses.json
vendored
564
test/fixtures/statuses.json
vendored
File diff suppressed because it is too large
Load diff
|
@ -63,16 +63,12 @@ module.exports = function (config) {
|
|||
frameworks: ['mocha', 'sinon-chai'],
|
||||
reporters: ['mocha'],
|
||||
customLaunchers: {
|
||||
'FirefoxHeadless': {
|
||||
FirefoxHeadless: {
|
||||
base: 'Firefox',
|
||||
flags: [
|
||||
'-headless'
|
||||
]
|
||||
flags: ['-headless']
|
||||
}
|
||||
},
|
||||
files: [
|
||||
'./index.js'
|
||||
],
|
||||
files: ['./index.js'],
|
||||
preprocessors: {
|
||||
'./index.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
|
@ -85,10 +81,7 @@ module.exports = function (config) {
|
|||
},
|
||||
coverageReporter: {
|
||||
dir: './coverage',
|
||||
reporters: [
|
||||
{ type: 'lcov', subdir: '.' },
|
||||
{ type: 'text-summary' }
|
||||
]
|
||||
reporters: [{ type: 'lcov', subdir: '.' }, { type: 'text-summary' }]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -26,10 +26,10 @@ const run = () => {
|
|||
let data = fs.readFileSync(newEmojiFilename, 'utf8')
|
||||
|
||||
// First filter out anything that's more than one codepoint
|
||||
const newEmojis = JSON.parse(data).emojis.filter(e => e.emoji.length <= 2)
|
||||
const newEmojis = JSON.parse(data).emojis.filter((e) => e.emoji.length <= 2)
|
||||
|
||||
// Create a table with format { shortname: emoji }, remove the :
|
||||
newEmojis.forEach(e => {
|
||||
newEmojis.forEach((e) => {
|
||||
const name = e.shortname.slice(1, e.shortname.length - 1).toLowerCase()
|
||||
if (name.length > 0) {
|
||||
newEmojisObject[name] = e.emoji
|
||||
|
@ -41,27 +41,34 @@ const run = () => {
|
|||
emojisObject = JSON.parse(data)
|
||||
|
||||
// Get rid of longer emojis that don't play nice with reactions
|
||||
Object.keys(emojisObject).forEach(e => {
|
||||
Object.keys(emojisObject).forEach((e) => {
|
||||
if (emojisObject[e].length > 2) emojisObject[e] = undefined
|
||||
})
|
||||
|
||||
// Add new emojis from the new tables to the old table
|
||||
Object.keys(newEmojisObject).forEach(e => {
|
||||
Object.keys(newEmojisObject).forEach((e) => {
|
||||
if (!emojisObject[e] && newEmojisObject[e].length <= 2) {
|
||||
emojisObject[e] = newEmojisObject[e]
|
||||
}
|
||||
})
|
||||
|
||||
// Sort by key
|
||||
const sorted = Object.keys(emojisObject).sort().reduce((acc, key) => {
|
||||
if (key.length === 0) return acc
|
||||
acc[key] = emojisObject[key]
|
||||
return acc
|
||||
}, {})
|
||||
const sorted = Object.keys(emojisObject)
|
||||
.sort()
|
||||
.reduce((acc, key) => {
|
||||
if (key.length === 0) return acc
|
||||
acc[key] = emojisObject[key]
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
fs.writeFile(outputFilename, JSON.stringify(sorted, null, 2), 'utf8', (err) => {
|
||||
if (err) console.log('Error writing file', err)
|
||||
})
|
||||
fs.writeFile(
|
||||
outputFilename,
|
||||
JSON.stringify(sorted, null, 2),
|
||||
'utf8',
|
||||
(err) => {
|
||||
if (err) console.log('Error writing file', err)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
run()
|
||||
|
|
Loading…
Reference in a new issue