mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-27 21:05:53 +00:00
4.24.0
* Changed: The settings for Animated Emotes and chat user color correction now default to enabled or disabled based on your vanilla Twitch settings. * Changed: Strip automatic error reporting from builds till it can be fixed. * Fixed: Native viewer count and uptime not hiding correctly when a stream goes live. * API Added: Settings can now depend on `localStorage` values by using `ls.{name}` keys for JSON or `ls.raw.{name}` for raw strings. * Maintenance: Update dependencies.
This commit is contained in:
parent
ce38c3c251
commit
2340992977
17 changed files with 2689 additions and 1438 deletions
3639
package-lock.json
generated
3639
package-lock.json
generated
File diff suppressed because it is too large
Load diff
72
package.json
72
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "frankerfacez",
|
||||
"author": "Dan Salvato LLC",
|
||||
"version": "4.23.2",
|
||||
"version": "4.24.0",
|
||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
|
@ -25,40 +25,40 @@
|
|||
"font:update": "node bin/update_fonts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.13",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.10.4",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.10.4",
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.5",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-react-jsx": "^7.10.4",
|
||||
"@babel/plugin-transform-react-jsx": "^7.14.5",
|
||||
"@ffz/fontello-cli": "^1.0.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"cross-env": "^7.0.2",
|
||||
"css-loader": "^3.1.0",
|
||||
"eslint": "^7.3.1",
|
||||
"eslint-plugin-react": "^7.20.3",
|
||||
"copy-webpack-plugin": "^5.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^3.6.0",
|
||||
"eslint": "^7.28.0",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"extract-loader": "^2.0.1",
|
||||
"file-loader": "^4.1.0",
|
||||
"file-loader": "^4.3.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"jszip": "^3.6.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"sass-loader": "^7.1.0",
|
||||
"raw-loader": "^3.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.2",
|
||||
"terser-webpack-plugin": "^3.0.6",
|
||||
"vue": "^2.6.11",
|
||||
"vue-loader": "^15.8.3",
|
||||
"sass-loader": "^7.1.0",
|
||||
"semver": "^7.3.5",
|
||||
"terser-webpack-plugin": "^3.1.0",
|
||||
"vue": "^2.6.14",
|
||||
"vue-loader": "^15.9.7",
|
||||
"vue-observe-visibility": "^0.4.6",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack": "^4.43.0",
|
||||
"vue-template-compiler": "^2.6.14",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
"webpack-merge": "^4.2.2"
|
||||
},
|
||||
|
@ -71,27 +71,27 @@
|
|||
"chartjs": "^0.3.24",
|
||||
"chartjs-plugin-waterfall": "^1.0.3",
|
||||
"chartjs-plugin-zoom": "^0.7.7",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"dayjs": "^1.8.29",
|
||||
"crypto-js": "^3.3.0",
|
||||
"dayjs": "^1.10.5",
|
||||
"displacejs": "^1.4.1",
|
||||
"emoji-regex": "^9.0.0",
|
||||
"file-saver": "^2.0.1",
|
||||
"graphql": "^15.2.0",
|
||||
"graphql-tag": "^2.10.3",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"graphql": "^15.5.0",
|
||||
"graphql-tag": "^2.12.4",
|
||||
"js-cookie": "^2.2.1",
|
||||
"markdown-it": "^11.0.0",
|
||||
"markdown-it": "^11.0.1",
|
||||
"markdown-it-link-attributes": "^3.0.0",
|
||||
"mnemonist": "^0.38.0",
|
||||
"path-to-regexp": "^3.0.0",
|
||||
"popper.js": "^1.14.3",
|
||||
"mnemonist": "^0.38.3",
|
||||
"path-to-regexp": "^3.2.0",
|
||||
"popper.js": "^1.16.1",
|
||||
"raven-js": "^3.24.2",
|
||||
"react": "^16.13.1",
|
||||
"react": "^16.14.0",
|
||||
"safe-regex": "^2.1.1",
|
||||
"sortablejs": "^1.10.2",
|
||||
"sortablejs": "^1.13.0",
|
||||
"sourcemapped-stacktrace": "^1.1.11",
|
||||
"text-diff": "^1.0.1",
|
||||
"vue-clickaway": "^2.2.2",
|
||||
"vue-color": "^2.7.1",
|
||||
"vuedraggable": "^2.23.2"
|
||||
"vue-color": "^2.8.1",
|
||||
"vuedraggable": "^2.24.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
import RavenLogger from './raven';
|
||||
|
||||
import Logger from 'utilities/logging';
|
||||
import Module from 'utilities/module';
|
||||
|
||||
|
@ -23,12 +21,10 @@ class FFZBridge extends Module {
|
|||
this.__modules.core = this;
|
||||
|
||||
// ========================================================================
|
||||
// Error Reporting and Logging
|
||||
// Logging
|
||||
// ========================================================================
|
||||
|
||||
this.inject('raven', RavenLogger);
|
||||
|
||||
this.log = new Logger(null, null, null, this.raven);
|
||||
this.log = new Logger(null, null, null);
|
||||
this.log.label = 'FFZBridge';
|
||||
this.log.init = true;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import RavenLogger from './raven';
|
||||
//import RavenLogger from './raven';
|
||||
|
||||
import Logger from 'utilities/logging';
|
||||
import Module from 'utilities/module';
|
||||
|
@ -35,9 +35,9 @@ class FrankerFaceZ extends Module {
|
|||
// Error Reporting and Logging
|
||||
// ========================================================================
|
||||
|
||||
this.inject('raven', RavenLogger);
|
||||
//this.inject('raven', RavenLogger);
|
||||
|
||||
this.log = new Logger(null, null, null, this.raven);
|
||||
this.log = new Logger(null, null, null); //, this.raven);
|
||||
this.log.label = 'FFZClips';
|
||||
this.log.init = true;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import RavenLogger from './raven';
|
||||
//import RavenLogger from './raven';
|
||||
|
||||
import Logger from 'utilities/logging';
|
||||
import Module from 'utilities/module';
|
||||
|
@ -40,9 +40,9 @@ class FrankerFaceZ extends Module {
|
|||
// Error Reporting and Logging
|
||||
// ========================================================================
|
||||
|
||||
this.inject('raven', RavenLogger);
|
||||
//this.inject('raven', RavenLogger);
|
||||
|
||||
this.log = new Logger(null, null, null, this.raven);
|
||||
this.log = new Logger(null, null, null); //, this.raven);
|
||||
this.log.init = true;
|
||||
|
||||
this.core_log = this.log.get('core');
|
||||
|
|
|
@ -1014,12 +1014,23 @@ export default class Chat extends Module {
|
|||
|
||||
|
||||
this.settings.add('chat.adjustment-mode', {
|
||||
default: 1,
|
||||
default: null,
|
||||
process(ctx, val) {
|
||||
if ( val == null )
|
||||
return (ctx.get('ls.useHighContrastColors') ?? true) ? 1 : 0;
|
||||
|
||||
return val;
|
||||
},
|
||||
requires: ['ls.useHighContrastColors'],
|
||||
ui: {
|
||||
path: 'Chat > Appearance >> Colors',
|
||||
title: 'Adjustment',
|
||||
description: 'Alter user colors to ensure that they remain readable.',
|
||||
|
||||
default(ctx) {
|
||||
return (ctx.get('ls.useHighContrastColors') ?? true) ? 1 : 0;
|
||||
},
|
||||
|
||||
component: 'setting-select-box',
|
||||
|
||||
data: [
|
||||
|
@ -1079,12 +1090,22 @@ export default class Chat extends Module {
|
|||
});
|
||||
|
||||
this.settings.add('chat.emotes.animated', {
|
||||
default: 1,
|
||||
default: null,
|
||||
requires: ['ls.emoteAnimationsEnabled'],
|
||||
process(ctx, val) {
|
||||
if ( val == null )
|
||||
return (ctx.get('ls.emoteAnimationsEnabled') ?? true) ? 1 : 0;
|
||||
return val;
|
||||
},
|
||||
ui: {
|
||||
path: 'Chat > Appearance >> Emotes',
|
||||
sort: -50,
|
||||
title: 'Animated Emotes',
|
||||
|
||||
default(ctx) {
|
||||
return (ctx.get('ls.emoteAnimationsEnabled') ?? true) ? 1 : 0;
|
||||
},
|
||||
|
||||
getExtraTerms: () => GIF_TERMS,
|
||||
|
||||
description: 'This controls whether or not animated emotes are allowed to play in chat. When this is `Disabled`, emotes will appear as static images. Setting this to `Enable on Hover` may cause performance issues.',
|
||||
|
|
|
@ -1333,10 +1333,15 @@ export const AddonEmotes = {
|
|||
|
||||
if ( emote_set ) {
|
||||
const type = emote_set.type;
|
||||
if ( type === EmoteTypes.Global )
|
||||
source = this.i18n.t('emote.global', 'Twitch Global');
|
||||
if ( type === EmoteTypes.Global ) {
|
||||
if ( emote_set.owner?.login ) {
|
||||
source = this.i18n.t('tooltip.channel', 'Channel: {source}', {
|
||||
source: emote_set.owner.displayName || emote_set.owner.login
|
||||
});
|
||||
} else
|
||||
source = this.i18n.t('emote.global', 'Twitch Global');
|
||||
|
||||
else if ( type === EmoteTypes.BitsTier ) {
|
||||
} else if ( type === EmoteTypes.BitsTier ) {
|
||||
source = this.i18n.t('emote.bits', 'Twitch Bits Reward');
|
||||
if ( emote_set.owner?.login )
|
||||
source = this.i18n.t('emote.bits-owner', '{source}\nChannel: {channel}', {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import RavenLogger from './raven';
|
||||
//import RavenLogger from './raven';
|
||||
|
||||
import Logger from 'utilities/logging';
|
||||
import Module from 'utilities/module';
|
||||
|
@ -32,9 +32,9 @@ class FrankerFaceZ extends Module {
|
|||
// Error Reporting and Logging
|
||||
// ========================================================================
|
||||
|
||||
this.inject('raven', RavenLogger);
|
||||
//this.inject('raven', RavenLogger);
|
||||
|
||||
this.log = new Logger(null, null, null, this.raven);
|
||||
this.log = new Logger(null, null, null); //, this.raven);
|
||||
this.log.label = 'FFZPlayer';
|
||||
this.log.init = true;
|
||||
|
||||
|
|
|
@ -75,6 +75,9 @@ export default class SettingsContext extends EventEmitter {
|
|||
if ( context )
|
||||
this._updateContext(context, undefined, undefined, new Set);*/
|
||||
|
||||
this.__ls_listening = false;
|
||||
this.__ls_wanted = new Map;
|
||||
|
||||
this.__cache = new Map;
|
||||
this.__meta = new Map;
|
||||
this.__profiles = [];
|
||||
|
@ -98,6 +101,34 @@ export default class SettingsContext extends EventEmitter {
|
|||
}
|
||||
|
||||
|
||||
// ========================================================================
|
||||
// Local Storage Handling
|
||||
// ========================================================================
|
||||
|
||||
_watchLS() {
|
||||
if ( this.__ls_watched )
|
||||
return;
|
||||
|
||||
this.__ls_watched = true;
|
||||
this.manager.on(':ls-update', this._onLSUpdate, this);
|
||||
}
|
||||
|
||||
_unwatchLS() {
|
||||
if ( ! this.__ls_watched )
|
||||
return;
|
||||
|
||||
this.__ls_watched = false;
|
||||
this.manager.off(':ls-update', this._onLSUpdate, this);
|
||||
}
|
||||
|
||||
_onLSUpdate(key) {
|
||||
const keys = this.__ls_wanted.get(`ls.${key}`);
|
||||
if ( keys )
|
||||
for(const key of keys)
|
||||
this._update(key, key, []);
|
||||
}
|
||||
|
||||
|
||||
// ========================================================================
|
||||
// State Construction
|
||||
// ========================================================================
|
||||
|
@ -340,7 +371,7 @@ export default class SettingsContext extends EventEmitter {
|
|||
const definition = this.manager.definitions.get(key);
|
||||
if ( definition && definition.required_by )
|
||||
for(const req_key of definition.required_by)
|
||||
if ( ! req_key.startsWith('context.') )
|
||||
if ( ! req_key.startsWith('context.') && ! req_key.startsWith('ls.') )
|
||||
this._update(req_key, initial, Array.from(visited));
|
||||
}
|
||||
|
||||
|
@ -382,7 +413,15 @@ export default class SettingsContext extends EventEmitter {
|
|||
|
||||
if ( definition.requires )
|
||||
for(const req_key of definition.requires)
|
||||
if ( ! req_key.startsWith('context.') && ! this.__cache.has(req_key) )
|
||||
if ( req_key.startsWith('ls.') ) {
|
||||
this._watchLS();
|
||||
let keys = this.__ls_wanted.get(req_key);
|
||||
if ( ! keys )
|
||||
this.__ls_wanted.set(req_key, keys = new Set);
|
||||
|
||||
keys.add(key);
|
||||
|
||||
} else if ( ! req_key.startsWith('context.') && ! this.__cache.has(req_key) )
|
||||
this._get(req_key, initial, Array.from(visited));
|
||||
|
||||
if ( definition.process )
|
||||
|
@ -432,6 +471,9 @@ export default class SettingsContext extends EventEmitter {
|
|||
}
|
||||
|
||||
get(key) {
|
||||
if ( key.startsWith('ls.') )
|
||||
return this.manager.getLS(key.slice(3));
|
||||
|
||||
if ( key.startsWith('context.') )
|
||||
//return this.__context[key.slice(8)];
|
||||
return getter(key.slice(8), this.__context);
|
||||
|
@ -453,6 +495,9 @@ export default class SettingsContext extends EventEmitter {
|
|||
|
||||
|
||||
uses(key) {
|
||||
if ( key.startsWith('ls.') )
|
||||
return null;
|
||||
|
||||
if ( key.startsWith('context.') )
|
||||
return null;
|
||||
|
||||
|
|
|
@ -71,6 +71,12 @@ export default class SettingsManager extends Module {
|
|||
}
|
||||
} catch(err) { /* no-op */ }
|
||||
|
||||
// Local Storage
|
||||
this.__ls_scheduled = new Set;
|
||||
this.__ls_cache = new Map;
|
||||
this.__ls_hooked = false;
|
||||
this._updateLS = this._updateLS.bind(this);
|
||||
|
||||
// State
|
||||
this.__contexts = [];
|
||||
this.__profiles = [];
|
||||
|
@ -277,6 +283,107 @@ export default class SettingsManager extends Module {
|
|||
}
|
||||
|
||||
|
||||
// ========================================================================
|
||||
// LocalStorage Management
|
||||
// ========================================================================
|
||||
|
||||
_updateLSKey(key) {
|
||||
if ( this.__ls_cache.has(key) || this.__ls_cache.has(`raw.${key}`) ) {
|
||||
this.__ls_scheduled.add(key);
|
||||
if ( ! this.__ls_timer )
|
||||
this.__ls_timer = setTimeout(this._updateLS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
_hookLS() {
|
||||
if ( this.__ls_hooked )
|
||||
return;
|
||||
|
||||
this.__ls_hooked = true;
|
||||
const original = localStorage.setItem,
|
||||
t = this;
|
||||
|
||||
localStorage.setItem = function(key, ...args) {
|
||||
// Guard this because we never want to break
|
||||
// localStorage, even if something really
|
||||
// weird happens.
|
||||
try {
|
||||
t._updateLSKey(key);
|
||||
} catch(err) { /* no-op */ }
|
||||
|
||||
return original.call(this, key, ...args);
|
||||
}
|
||||
|
||||
this._handleLSEvent = this._handleLSEvent.bind(this);
|
||||
window.addEventListener('storage', this._handleLSEvent);
|
||||
}
|
||||
|
||||
_handleLSEvent(event) {
|
||||
if ( event.storageArea === localStorage )
|
||||
this._updateLSKey(event.key);
|
||||
}
|
||||
|
||||
_updateLS() {
|
||||
clearTimeout(this.__ls_timer);
|
||||
this.__ls_timer = null;
|
||||
const keys = this.__ls_scheduled;
|
||||
this.__ls_scheduled = new Set;
|
||||
|
||||
for(const key of keys) {
|
||||
const has_value = this.__ls_cache.has(key),
|
||||
raw_key = `raw.${key}`,
|
||||
has_raw = this.__ls_cache.has(raw_key);
|
||||
|
||||
if ( ! has_raw && ! has_value )
|
||||
continue;
|
||||
|
||||
const raw = localStorage.getItem(key);
|
||||
|
||||
if ( has_raw ) {
|
||||
this.__ls_cache.set(raw_key, raw);
|
||||
this.emit(':ls-update', raw_key, raw);
|
||||
}
|
||||
|
||||
if ( has_value ) {
|
||||
let value;
|
||||
if ( raw )
|
||||
try {
|
||||
value = JSON.parse(raw);
|
||||
} catch(err) {
|
||||
this.log.warn(`Unable to parse localStorage value as JSON for "${key}"`, err);
|
||||
}
|
||||
|
||||
this.__ls_cache.set(key, value);
|
||||
this.emit(':ls-update', key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getLS(key) {
|
||||
if ( this.__ls_cache.has(key) )
|
||||
return this.__ls_cache.get(key);
|
||||
|
||||
if ( ! this.__ls_hooked )
|
||||
this._hookLS();
|
||||
|
||||
const is_raw = key.startsWith('raw.'),
|
||||
raw = localStorage.getItem(is_raw ? key.slice(4) : key);
|
||||
|
||||
let value;
|
||||
if ( is_raw )
|
||||
value = raw;
|
||||
else
|
||||
try {
|
||||
value = JSON.parse(raw);
|
||||
} catch(err) {
|
||||
this.log.warn(`Unable to parse localStorage value as JSON for "${key}"`, err);
|
||||
}
|
||||
|
||||
this.__ls_cache.set(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// ========================================================================
|
||||
// Backup and Restore
|
||||
// ========================================================================
|
||||
|
|
|
@ -583,6 +583,7 @@ export default class Input extends Module {
|
|||
return {emotes: [], length: 0};
|
||||
|
||||
const out = [],
|
||||
anim = this.chat.context.get('chat.emotes.animated') > 0,
|
||||
hidden_sets = this.settings.provider.get('emote-menu.hidden-sets'),
|
||||
has_hidden = Array.isArray(hidden_sets) && hidden_sets.length > 0,
|
||||
hidden_emotes = this.emotes.getHidden('twitch'),
|
||||
|
@ -624,14 +625,12 @@ export default class Input extends Module {
|
|||
continue;
|
||||
|
||||
const replacement = REPLACEMENTS[id];
|
||||
let srcSet, animSrcSet;
|
||||
let srcSet;
|
||||
|
||||
if ( replacement && this.chat.context.get('chat.fix-bad-emotes') ) {
|
||||
srcSet = `${REPLACEMENT_BASE}${replacement} 1x`;
|
||||
} else {
|
||||
srcSet = getTwitchEmoteSrcSet(id, false);
|
||||
animSrcSet = getTwitchEmoteSrcSet(id, true);
|
||||
}
|
||||
} else
|
||||
srcSet = getTwitchEmoteSrcSet(id, anim);
|
||||
|
||||
out.push({
|
||||
id,
|
||||
|
@ -641,7 +640,6 @@ export default class Input extends Module {
|
|||
token,
|
||||
tokenLower: token.toLowerCase(),
|
||||
srcSet,
|
||||
animSrcSet,
|
||||
favorite: favorites.includes(id)
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,8 +2,4 @@
|
|||
.live-time {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
& > :first-child > :last-child {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
.ffz--meta-tray {
|
||||
& > :first-child > :first-child:not(.tw-core-button) {
|
||||
.tw-svg svg[type="color-text-accessible-red"],
|
||||
p[data-a-target="animated-channel-viewers-count"] {
|
||||
display: none !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ export const NEW_API = '//api2.frankerfacez.com';
|
|||
//export const SENTRY_ID = 'https://07ded545d3224ca59825daee02dc7745@catbag.frankerfacez.com:444/2';
|
||||
export const SENTRY_ID = 'https://74b46b3894114f399d51949c6d237489@sentry.frankerfacez.com/2';
|
||||
|
||||
|
||||
export const LV_SERVER = 'https://cbenni.com/api';
|
||||
export const LV_SOCKET_SERVER = 'wss://cbenni.com/socket.io/';
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
/* global module __dirname */
|
||||
|
||||
module.exports = merge(common, {
|
||||
resolve: {
|
||||
alias: {
|
||||
site: path.resolve(__dirname, 'src/sites/twitch-clips/')
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,97 +0,0 @@
|
|||
/* eslint-disable */
|
||||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const common = require('./webpack.clips.common.js');
|
||||
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
|
||||
/* global module */
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'development',
|
||||
devtool: 'inline-source-map',
|
||||
|
||||
plugins: [
|
||||
new CopyPlugin([
|
||||
{
|
||||
from: './src/entry.js',
|
||||
to: 'script.js'
|
||||
}
|
||||
]),
|
||||
new webpack.DefinePlugin({
|
||||
__git_commit__: null
|
||||
})
|
||||
],
|
||||
|
||||
devServer: {
|
||||
https: true,
|
||||
port: 8000,
|
||||
compress: true,
|
||||
inline: false,
|
||||
|
||||
allowedHosts: [
|
||||
'.twitch.tv',
|
||||
'.frankerfacez.com'
|
||||
],
|
||||
|
||||
contentBase: path.join(__dirname, 'dev_cdn'),
|
||||
publicPath: '/script/clips/',
|
||||
|
||||
proxy: {
|
||||
'**': {
|
||||
target: 'https://cdn.frankerfacez.com/',
|
||||
changeOrigin: true
|
||||
}
|
||||
},
|
||||
|
||||
before(app) {
|
||||
// Because the headers config option is broken.
|
||||
app.get('/*', (req, res, next) => {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/update_font', (req, res) => {
|
||||
const proc = exec('npm run font:save');
|
||||
|
||||
proc.stdout.on('data', data => {
|
||||
console.log('FONT>>', data);
|
||||
});
|
||||
|
||||
proc.stderr.on('data', data => {
|
||||
console.error('FONT>>', data);
|
||||
});
|
||||
|
||||
proc.on('close', code => {
|
||||
console.log('FONT>> Exited with code', code);
|
||||
res.redirect(req.headers.referer);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/script/script.js', (req, res, next) => {
|
||||
req.url = req.url.replace(/^\/script/, '/script/clips');
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/script/bridge.js', (req, res, next) => {
|
||||
req.url = req.url.replace(/^\/script/, '/script/clips');
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/dev_server', (req, res) => {
|
||||
res.json({
|
||||
path: process.cwd(),
|
||||
version: 2
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
output: {
|
||||
publicPath: '//localhost:8000/script/clips/',
|
||||
filename: '[name].js',
|
||||
jsonpFunction: 'ffzWebpackJsonp',
|
||||
crossOriginLoading: 'anonymous'
|
||||
}
|
||||
})
|
|
@ -1,69 +0,0 @@
|
|||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge');
|
||||
const common = require('./webpack.clips.common.js');
|
||||
const path = require('path');
|
||||
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
||||
|
||||
const Terser = require('terser');
|
||||
|
||||
// Get Git info
|
||||
|
||||
const commit_hash = require('child_process').execSync('git rev-parse HEAD').toString().trim();
|
||||
|
||||
/* global module Buffer __dirname */
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
|
||||
optimization: {
|
||||
concatenateModules: false,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
sourceMap: true,
|
||||
terserOptions: {
|
||||
keep_classnames: true,
|
||||
keep_fnames: true
|
||||
}
|
||||
})
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new CleanWebpackPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
__git_commit__: JSON.stringify(commit_hash)
|
||||
}),
|
||||
new CopyPlugin([
|
||||
{
|
||||
from: './src/entry.js',
|
||||
to: 'script.min.js',
|
||||
transform: content => {
|
||||
const text = content.toString('utf8');
|
||||
const minified = Terser.minify(text);
|
||||
return (minified && minified.code) ? Buffer.from(minified.code) : content;
|
||||
}
|
||||
}
|
||||
]),
|
||||
new ManifestPlugin({
|
||||
basePath: 'clips/',
|
||||
publicPath: 'clips/',
|
||||
map: data => {
|
||||
if ( data.name.endsWith('.scss') )
|
||||
data.name = `${data.name.substr(0,data.name.length - 5)}.css`;
|
||||
|
||||
return data;
|
||||
}
|
||||
})
|
||||
],
|
||||
|
||||
output: {
|
||||
publicPath: '//cdn.frankerfacez.com/static/clips/',
|
||||
path: path.resolve(__dirname, 'dist/clips'),
|
||||
filename: '[name].[hash].js'
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue