Reorganize source files in preparation for transition to vue-cli

The biggest changes here include splitting the server-side JS into multiple directories (under /src/app), moving all web content to /src/web, and compiling the web app to /dist instead of /public. This layout makes more sense overall, and more closely mirrors what is used for vue-cli v3 projects.
This commit is contained in:
Matt Isenhower 2018-07-27 11:08:37 -07:00
parent 50460e8fa4
commit 8f2bc6d5cd
168 changed files with 216 additions and 207 deletions

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
node_modules
.env
docker-compose.override.yml
public/*
/dist
logs
test-screenshot-*
/storage

View File

@ -14,4 +14,4 @@ services:
volumes:
- ./docker/nginx/conf.d:/etc/nginx/conf.d:ro
- ./logs:/logs
- ./public:/usr/share/nginx/html:ro
- ./dist:/usr/share/nginx/html:ro

View File

@ -4,11 +4,14 @@
"dev": "webpack",
"watch": "npm run dev -- --watch",
"build": "webpack -p --env production",
"serve": "webpack-dev-server --hot --content-base public/",
"splatnet": "node src/updater/update.js updateAll",
"twitter": "node src/updater/twitter.js maybePostTweets",
"twitter-test": "node src/updater/twitter.js testScreenshots",
"cron": "node src/updater/cron.js",
"serve": "webpack-dev-server --hot --content-base dist/",
"splatnet": "node src/app splatnet",
"twitter": "node src/app twitter",
"twitter:test": "node src/app twitterTest",
"cron": "node src/app/cron",
"utility:updateGear": "node src/utility updateGear",
"utility:getSplatNetLanguageFiles": "node src/utility getSplatNetLanguageFiles",
"utility:copyTranslation": "node src/utility copyTranslation",
"locale-man": "node node_modules/locale-man/ -l en,es,es-MX,fr,fr-CA,de,nl,it,ru,ja -o src/locale"
},
"dependencies": {
@ -39,6 +42,7 @@
"lodash": "^4.17.4",
"make-runnable": "^1.3.6",
"mkdirp": "^0.5.1",
"module-alias": "^2.1.0",
"moment-timezone": "^0.5.13",
"node-sass": "^4.5.3",
"postcss-loader": "^2.0.6",
@ -63,5 +67,8 @@
"devDependencies": {
"locale-man": "^0.0.5",
"shipit-cli": "^3.0.0"
},
"_moduleAliases": {
"@": "src"
}
}

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -8,20 +8,20 @@
<meta name="description" content="Splatoon 2 map rotation, upcoming Salmon Run schedules, SplatNet gear, and Splatfest info.">
<meta property="og:title" content="Splatoon 2 Map Schedules">
<meta property="og:description" content="Current/upcoming maps and Salmon Run schedules.">
<meta property="og:image" content="https://splatoon2.ink/<%= require('../icons/apple-touch-icon.png') %>">
<meta property="og:image" content="https://splatoon2.ink/<%= require('../src/web/assets/icons/apple-touch-icon.png') %>">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Splatoon2.ink">
<% for (var css in htmlWebpackPlugin.files.chunks.main.css) { %>
<link href="<%= htmlWebpackPlugin.files.chunks.main.css[css] %>" rel="stylesheet">
<% } %>
<link rel="apple-touch-icon" sizes="180x180" href="<%= require('../icons/apple-touch-icon.png') %>">
<link rel="icon" type="image/png" sizes="32x32" href="<%= require('../icons/favicon-32x32.png') %>">
<link rel="icon" type="image/png" sizes="16x16" href="<%= require('../icons/favicon-16x16.png') %>">
<link rel="apple-touch-icon" sizes="180x180" href="<%= require('../src/web/assets/icons/apple-touch-icon.png') %>">
<link rel="icon" type="image/png" sizes="32x32" href="<%= require('../src/web/assets/icons/favicon-32x32.png') %>">
<link rel="icon" type="image/png" sizes="16x16" href="<%= require('../src/web/assets/icons/favicon-16x16.png') %>">
<link rel="manifest" href="/manifest.json">
<meta name="msapplication-config" content="/browserconfig.xml">
<link rel="mask-icon" href="<%= require('../icons/safari-pinned-tab.svg') %>" color="#ff470f">
<link rel="shortcut icon" href="<%= require('../icons/favicon.ico') %>">
<link rel="mask-icon" href="<%= require('../src/web/assets/icons/safari-pinned-tab.svg') %>" color="#ff470f">
<link rel="shortcut icon" href="<%= require('../src/web/assets/icons/favicon.ico') %>">
<meta name="theme-color" content="#cccccc">
</head>
<body>

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -1,12 +1,12 @@
require('./bootstrap');
require('../common/bootstrap');
const CronJob = require('cron').CronJob;
const update = require('./update');
const updater = require('./updater');
const twitter = require('./twitter');
console.info('Starting periodic tasks...');
// Run every hour at 10sec after the hour
new CronJob('10 0 * * * *', async () => {
await update.updateAll();
await updater.updateAll();
await twitter.maybePostTweets();
}, null, true);

9
src/app/index.js Normal file
View File

@ -0,0 +1,9 @@
require('../common/bootstrap');
module.exports = {
splatnet: require('./updater').updateAll,
twitter: require('./twitter').maybePostTweets,
twitterTest: require('./twitter').testScreenshots,
};
require('make-runnable/custom')({ printOutputFrame: false });

View File

@ -0,0 +1,3 @@
const screenshots = require('./screenshots');
module.exports = screenshots;

View File

@ -1,9 +1,8 @@
require('./bootstrap');
const path = require('path');
const { URL } = require('url');
const puppeteer = require('puppeteer');
const htmlPath = path.resolve('./public/screenshots.html');
const htmlPath = path.resolve('./dist/screenshots.html');
const htmlUrl = new URL('file://'+htmlPath);
const viewport = {
width: 1012, // Twitter's in-stream image width is 506px, 506*2 = 1012

View File

@ -1,4 +1,3 @@
require('../bootstrap');
const Twitter = require('twitter');
// Twitter API parameters

3
src/app/twitter/index.js Normal file
View File

@ -0,0 +1,3 @@
const twitter = require('./twitter');
module.exports = twitter;

View File

@ -1,6 +1,6 @@
const TwitterPostBase = require('./TwitterPostBase');
const { captureGearScreenshot } = require('../screenshots');
const { readData, getTopOfCurrentHour } = require('../utilities');
const { captureGearScreenshot } = require('@/app/screenshots');
const { readData, getTopOfCurrentHour } = require('@/common/utilities');
class GearTweet extends TwitterPostBase {
getKey() { return 'gear'; }

View File

@ -1,10 +1,10 @@
const TwitterPostBase = require('./TwitterPostBase');
const { readJson } = require('../utilities');
const { readJson } = require('@/common/utilities');
const path = require('path');
const fs = require('fs');
const stagesPath = path.resolve('storage/stages.json');
const splatnetAssetPath = path.resolve('public/assets/splatnet');
const splatnetAssetPath = path.resolve('dist/assets/splatnet');
class NewStageTweet extends TwitterPostBase {
getKey() { return 'newstage'; }

View File

@ -1,6 +1,6 @@
const TwitterPostBase = require('./TwitterPostBase');
const { captureNewWeaponScreenshot } = require('../screenshots');
const { readData } = require('../utilities');
const { captureNewWeaponScreenshot } = require('@/app/screenshots');
const { readData } = require('@/common/utilities');
class NewWeaponTweet extends TwitterPostBase {
getKey() { return 'weapon'; }

View File

@ -1,6 +1,6 @@
const TwitterPostBase = require('./TwitterPostBase');
const { captureSalmonRunGearScreenshot } = require('../screenshots');
const { readData } = require('../utilities');
const { captureSalmonRunGearScreenshot } = require('@/app/screenshots');
const { readData } = require('@/common/utilities');
const moment = require('moment-timezone');
class SalmonRunTweet extends TwitterPostBase {

View File

@ -1,6 +1,6 @@
const TwitterPostBase = require('./TwitterPostBase');
const { captureSalmonRunScreenshot } = require('../screenshots');
const { readData } = require('../utilities');
const { captureSalmonRunScreenshot } = require('@/app/screenshots');
const { readData } = require('@/common/utilities');
class SalmonRunTweet extends TwitterPostBase {
getKey() { return 'salmonrun'; }

View File

@ -1,6 +1,6 @@
const TwitterPostBase = require('./TwitterPostBase');
const { captureScheduleScreenshot } = require('../screenshots');
const { readData, readJson } = require('../utilities');
const { captureScheduleScreenshot } = require('@/app/screenshots');
const { readData, readJson } = require('@/common/utilities');
const path = require('path');
const stagesPath = path.resolve('storage/stages.json');

View File

@ -1,7 +1,7 @@
const TwitterPostBase = require('./TwitterPostBase');
const { captureSplatfestScreenshot } = require('../screenshots');
const { readData } = require('../utilities');
const { splatoonRegions } = require('../../js/regions');
const { captureSplatfestScreenshot } = require('@/app/screenshots');
const { readData } = require('@/common/utilities');
const { splatoonRegions } = require('@/common/regions');
class SplatfestTweet extends TwitterPostBase {
constructor(region) {

View File

@ -1,7 +1,7 @@
const path = require('path');
const fs = require('fs');
const { postMediaTweet } = require('./client');
const { getTopOfCurrentHour, readJson, writeJson } = require('../utilities');
const { postMediaTweet } = require('../client');
const { getTopOfCurrentHour, readJson, writeJson } = require('@/common/utilities');
const lastTweetTimesPath = path.resolve('storage/twitter-lastTweetTimes.json');

View File

@ -0,0 +1,19 @@
const ScheduleTweet = require('./ScheduleTweet');
const GearTweet = require('./GearTweet');
const SalmonRunTweet = require('./SalmonRunTweet');
const SalmonRunGearTweet = require('./SalmonRunGearTweet');
const NewWeaponTweet = require('./NewWeaponTweet');
const NewStageTweet = require('./NewStageTweet');
const SplatfestTweet = require('./SplatfestTweet');
module.exports = [
new ScheduleTweet,
new GearTweet,
new SalmonRunTweet,
new SalmonRunGearTweet,
new NewWeaponTweet,
new NewStageTweet,
new SplatfestTweet('na'),
new SplatfestTweet('eu'),
new SplatfestTweet('jp'),
];

View File

@ -0,0 +1,22 @@
const { canTweet } = require('./client');
const tweets = require('./tweets');
async function maybePostTweets() {
if (!canTweet()) {
console.warn('Twitter API parameters not specified');
return;
}
for (let tweet of tweets)
await tweet.maybePostTweet();
}
async function testScreenshots() {
for (let tweet of tweets)
await tweet.saveTestScreenshot();
}
module.exports = {
maybePostTweets,
testScreenshots,
}

View File

@ -3,9 +3,9 @@ const fs = require('fs');
const mkdirp = require('mkdirp');
const jsonpath = require('jsonpath');
const _ = require('lodash');
const { readJson, writeJson } = require('./utilities');
const { readJson, writeJson } = require('@/common/utilities');
const localizationsPath = path.resolve('public/data/locale');
const localizationsPath = path.resolve('dist/data/locale');
class LocalizationProcessor {
constructor(ruleset, languageInfo) {

3
src/app/updater/index.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
updateAll: require('./updateAll'),
};

View File

@ -1,6 +1,3 @@
require('./bootstrap');
const Updater = require('./updaters/Updater');
const SchedulesUpdater = require('./updaters/SchedulesUpdater');
const CoopSchedulesUpdater = require('./updaters/CoopSchedulesUpdater');
const TimelineUpdater = require('./updaters/TimelineUpdater');
@ -31,8 +28,4 @@ async function updateAll() {
return 'Done';
}
module.exports = {
updateAll,
}
require('make-runnable/custom')({ printOutputFrame: false });
module.exports = updateAll;

View File

@ -4,8 +4,8 @@ const fs = require('fs');
const path = require('path');
const _ = require('lodash');
const jsonpath = require('jsonpath');
const { readJson } = require('../utilities');
const { languages } = require('../../js/regions');
const { readJson } = require('@/common/utilities');
const { languages } = require('@/common/regions');
class FestivalsUpdater extends Updater {
constructor(region) {

View File

@ -1,6 +1,6 @@
const Updater = require('./Updater');
const SplatNet = require('../splatnet');
const { getOriginalGear } = require('../../js/splatoon');
const SplatNet = require('@/common/splatnet');
const { getOriginalGear } = require('@/common/splatoon');
class MerchandisesUpdater extends Updater {
constructor() {

View File

@ -1,7 +1,7 @@
const Updater = require('./Updater');
const path = require('path');
const fs = require('fs');
const dataPath = path.resolve('src/js/data');
const dataPath = path.resolve('src/common/data');
class OriginalGearImageUpdater extends Updater {
constructor() {

View File

@ -1,8 +1,8 @@
const Updater = require('./Updater');
const SplatNet = require('../splatnet');
const SplatNet = require('@/common/splatnet');
const path = require('path');
const fs = require('fs');
const { getTopOfCurrentHour, readJson } = require('../utilities');
const { getTopOfCurrentHour, readJson } = require('@/common/utilities');
const stagesPath = path.resolve('storage/stages.json');

View File

@ -3,15 +3,15 @@ const fs = require('fs');
const mkdirp = require('mkdirp');
const _ = require('lodash');
const jsonpath = require('jsonpath');
const SplatNet = require('../splatnet');
const SplatNet = require('@/common/splatnet');
const iCal = require('cozy-ical');
const moment = require('moment-timezone');
const raven = require('raven');
const { languages } = require('../../js/regions');
const { languages } = require('@/common/regions');
const LocalizationProcessor = require('../LocalizationProcessor');
const dataPath = path.resolve('public/data');
const splatnetAssetPath = path.resolve('public/assets/splatnet');
const dataPath = path.resolve('dist/data');
const splatnetAssetPath = path.resolve('dist/assets/splatnet');
class Updater {
constructor(options = {}) {
@ -184,13 +184,7 @@ class Updater {
this.info(`Downloading image: ${imagePath}`);
let splatnet = new SplatNet;
let image = await this.handleRequest(splatnet.getImage(imagePath));
// console.log(image.length)
this.writeFile(localPath, image);
// Temporary: Also save the file to the old path for now
// This allows for old versions of the site to continue downloading images
let oldPath = path.resolve('public/assets/img/splatnet') + '/' + path.basename(imagePath);
this.writeFile(oldPath, image);
}
/**

View File

@ -1,5 +1,6 @@
require('dotenv').config();
require('console-stamp')(console);
require('module-alias/register');
// Sentry error reporting
const raven = require('raven');

View File

@ -1,6 +1,6 @@
const brands = require('./data/brands');
const skills = require('./data/skills');
const inkipediaGear = require('./data/inkipediaGear');
const inkipediaGear = require('./data/gear');
function getOriginalGear(gear) {
if (!gear || !gear.name)

View File

@ -3,7 +3,7 @@ const path = require('path');
const mkdirp = require('mkdirp');
const stringify = require('json-stable-stringify');
const dataPath = path.resolve('public/data');
const dataPath = path.resolve('dist/data');
function getTopOfCurrentHour() {
let date = new Date;

View File

@ -1,43 +0,0 @@
require('./bootstrap');
const { canTweet } = require('./twitter/client');
const ScheduleTweet = require('./twitter/ScheduleTweet');
const GearTweet = require('./twitter/GearTweet');
const SalmonRunTweet = require('./twitter/SalmonRunTweet');
const SalmonRunGearTweet = require('./twitter/SalmonRunGearTweet');
const NewWeaponTweet = require('./twitter/NewWeaponTweet');
const NewStageTweet = require('./twitter/NewStageTweet');
const SplatfestTweet = require('./twitter/SplatfestTweet');
let tweets = [
new ScheduleTweet,
new GearTweet,
new SalmonRunTweet,
new SalmonRunGearTweet,
new NewWeaponTweet,
new NewStageTweet,
new SplatfestTweet('na'),
new SplatfestTweet('eu'),
new SplatfestTweet('jp'),
];
async function maybePostTweets() {
if (!canTweet()) {
console.warn('Twitter API parameters not specified');
return;
}
for (let tweet of tweets)
await tweet.maybePostTweet();
}
async function testScreenshots() {
for (let tweet of tweets)
await tweet.saveTestScreenshot();
}
module.exports = {
maybePostTweets,
testScreenshots,
}
require('make-runnable/custom')({ printOutputFrame: false });

View File

@ -1,17 +1,15 @@
// This file copies translations from SplatNet language files to our own language files
require('./bootstrap');
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
const { readJson } = require('./utilities');
const { languages } = require('../js/regions');
const SplatNet = require('./splatnet');
const { readJson } = require('@/common/utilities');
const { languages } = require('@/common/regions');
const sourcePath = path.resolve('storage/lang');
const destinationPath = path.resolve('src/locale');
const destinationPath = path.resolve('src/web/locale');
function copyTranslation(source, destination) {
module.exports = function (source, destination) {
for (let { region, language } of languages) {
let sourceLang = readJson(`${sourcePath}/${region}-${language}.json`);
let outputFile = `${destinationPath}/${language}.json`;
@ -21,9 +19,3 @@ function copyTranslation(source, destination) {
fs.writeFileSync(outputFile, JSON.stringify(output, null, 4) + '\n');
}
}
module.exports = {
copyTranslation,
};
require('make-runnable/custom')({ printOutputFrame: false });

View File

@ -1,20 +1,17 @@
// This is a helper used to retrieve language files from SplatNet.
// These files aren't used directly, but are just downloaded for help with updating manual translation files.
require('./bootstrap');
const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const axios = require('axios');
const { writeFormattedJson } = require('./utilities');
const { languages } = require('../js/regions');
const SplatNet = require('./splatnet');
const { writeFormattedJson } = require('@/common/utilities');
const { languages } = require('@/common/regions');
const SplatNet = require('@/common/splatnet');
const outputPath = path.resolve('storage/lang');
mkdirp(outputPath);
module.exports = async () => {
mkdirp(outputPath);
(async () => {
for (let { region, language } of languages) {
let splatnet = new SplatNet(region, language);
let client = splatnet.getClient();
@ -33,4 +30,4 @@ mkdirp(outputPath);
// Store the data to a JSON file
writeFormattedJson(`${outputPath}/${region}-${language}.json`, window.LocalizedMessage);
}
})();
};

9
src/utility/index.js Normal file
View File

@ -0,0 +1,9 @@
require('../common/bootstrap');
module.exports = {
updateGear: require('./updateGear'),
getSplatNetLanguageFiles: require('./getSplatNetLanguageFiles'),
copyTranslation: require('./copyTranslation'),
};
require('make-runnable/custom')({ printOutputFrame: false });

View File

@ -1,5 +1,5 @@
const delay = require('delay');
const splatnet = require('./splatnet');
const splatnet = require('@/common/splatnet');
/**
* We can't retrieve gear/brand/skill data directly.

View File

@ -1,21 +1,18 @@
// Note: this script is intended to be run during development (not in production).
// It updates the gear/brand/skill data located at /src/js/data/.
require('./bootstrap');
const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const axios = require('axios');
const retrieveGearData = require('./retrieveGearData');
const { writeFormattedJson } = require('./utilities');
const { writeFormattedJson } = require('@/common/utilities');
const he = require('he');
const dataPath = path.resolve('src/js/data');
const dataPath = path.resolve('src/common/data');
const brandsFilename = `${dataPath}/brands.json`;
const skillsFilename = `${dataPath}/skills.json`;
const inkipediaGearFilename = `${dataPath}/inkipediaGear.json`;
mkdirp(dataPath);
const inkipediaGearFilename = `${dataPath}/gear.json`;
function applyData(oldData, newData) {
if (!Array.isArray(newData))
@ -29,7 +26,9 @@ function applyData(oldData, newData) {
}
}
(async () => {
module.exports = async () => {
mkdirp(dataPath);
let brands = {};
let skills = {};
@ -73,7 +72,6 @@ function applyData(oldData, newData) {
.reduce((map, kvp) => { kvp = kvp.split('='); map[kvp[0]] = kvp[1]; return map; }, {});
// Make sure we have the necessary info
// console.log(details);
if (details.category && details.name && details.brand && details.ability && details.rarity) {
let key;
switch (details.category) {
@ -112,4 +110,4 @@ function applyData(oldData, newData) {
writeFormattedJson(brandsFilename, brands);
writeFormattedJson(skillsFilename, skills);
writeFormattedJson(inkipediaGearFilename, inkipediaGear);
})();
};

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

Before

Width:  |  Height:  |  Size: 251 B

After

Width:  |  Height:  |  Size: 251 B

View File

Before

Width:  |  Height:  |  Size: 567 B

After

Width:  |  Height:  |  Size: 567 B

View File

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 762 B

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 782 B

After

Width:  |  Height:  |  Size: 782 B

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 733 B

After

Width:  |  Height:  |  Size: 733 B

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 99 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Some files were not shown because too many files have changed in this diff Show More