29
0
mirror of https://github.com/joomla/joomla-cms.git synced 2024-06-25 23:02:55 +00:00

[4.0] Media manager compiled using rollup (#32459)

This commit is contained in:
Dimitris Grammatikogiannis 2021-02-20 22:30:44 +01:00 committed by GitHub
parent 46c72e9da8
commit 1bf1514f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 1334 additions and 4485 deletions

View File

@ -1,6 +1,5 @@
import { notifications } from './Notifications.es6';
const path = require('path');
import { dirname } from './path';
/**
* Api class for communication with the server
@ -230,7 +229,7 @@ class Api {
item.files = [];
}
item.directory = path.dirname(item.path);
item.directory = dirname(item.path);
if (item.directory.indexOf(':', item.directory.length - 1) !== -1) {
item.directory += '/';

View File

@ -1,4 +1,4 @@
import Vue from 'vue';
import Vue from 'vue/dist/vue.esm.browser.min.js';
/**
* Media Event bus - used for communication between joomla and vue

View File

@ -0,0 +1,27 @@
export const dirname = (path) => {
if (typeof path !== 'string') {
throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
}
if (path.length === 0) return '.';
let code = path.charCodeAt(0);
const hasRoot = code === 47;
let end = -1;
let matchedSlash = true;
for (let i = path.length - 1; i >= 1; --i) {
code = path.charCodeAt(i);
if (code === 47) {
if (!matchedSlash) {
end = i;
break;
}
} else {
// We saw the first non-path separator
matchedSlash = false;
}
}
if (end === -1) return hasRoot ? '/' : '.';
if (hasRoot && end === 1) return '//';
return path.slice(0, end);
}

View File

@ -1,5 +1,5 @@
import Vue from 'vue';
import Lock from 'vue-focus-lock';
import Vue from 'vue/dist/vue.esm.browser.min.js';
import Lock from 'vue-focus-lock/src/index.js';
import Event from './app/Event.es6';
import App from './components/app.vue';
import Disk from './components/tree/disk.vue';

View File

@ -2,38 +2,29 @@
* Translate plugin
*/
const Translate = {};
// eslint-disable-next-line func-names
Translate.translate = function (key) {
const Translate = {
// Translate from Joomla text
return Joomla.JText._(key, key);
};
translate: (key) => Joomla.JText._(key, key),
sprintf: (string, ...args) => {
// eslint-disable-next-line no-param-reassign
string = Translate.translate(string);
let i = 0;
return string.replace(/%((%)|s|d)/g, (m) => {
let val = args[i];
// eslint-disable-next-line func-names
Translate.sprintf = function (string, ...args) {
// eslint-disable-next-line no-param-reassign
string = this.translate(string);
let i = 0;
return string.replace(/%((%)|s|d)/g, (m) => {
let val = args[i];
if (m === '%d') {
val = parseFloat(val);
// eslint-disable-next-line no-restricted-globals
if (isNaN(val)) {
val = 0;
if (m === '%d') {
val = parseFloat(val);
// eslint-disable-next-line no-restricted-globals
if (isNaN(val)) {
val = 0;
}
}
}
// eslint-disable-next-line no-plusplus
i++;
return val;
});
};
// eslint-disable-next-line func-names
Translate.install = function (Vue) {
Vue.mixin({
// eslint-disable-next-line no-plusplus
i++;
return val;
});
},
install: (Vue) => Vue.mixin({
methods: {
translate(key) {
return Translate.translate(key);
@ -42,7 +33,7 @@ Translate.install = function (Vue) {
return Translate.sprintf(key, args);
},
},
});
}),
};
export default Translate;

View File

@ -2,7 +2,6 @@ import { api } from '../app/Api.es6';
import * as types from './mutation-types.es6';
import translate from '../plugins/translate.es6';
import { notifications } from '../app/Notifications.es6';
import * as FileSaver from '../../../../../../node_modules/file-saver/src/FileSaver';
// Actions are similar to mutations, the difference being that:
// - Instead of mutating the state, actions commit mutations.
@ -81,7 +80,7 @@ export const download = (context, payload) => {
.then((contents) => {
const file = contents.files[0];
// Converte the base 64 encoded string to a blob
// Convert the base 64 encoded string to a blob
const byteCharacters = atob(file.content);
const byteArrays = [];
@ -99,8 +98,14 @@ export const download = (context, payload) => {
byteArrays.push(byteArray);
}
// Open the save as file dialog
FileSaver.saveAs(new Blob(byteArrays, { type: file.mime_type }), file.name);
// Download file
const blobURL = URL.createObjectURL(new Blob(byteArrays, { type: file.mime_type }));
const a = document.createElement('a');
a.href = blobURL;
a.download = file.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
})
.catch((error) => {
// eslint-disable-next-line no-console

View File

@ -1,6 +1,5 @@
import * as types from './mutation-types.es6';
const nodePath = require('path');
import { dirname } from '../app/path';
// The only way to actually change state in a store is by committing a mutation.
// Mutations are very similar to events: each mutation has a string type and a handler.
@ -57,7 +56,7 @@ export default {
*/
function directoryFromPath(path) {
const parts = path.split('/');
let directory = nodePath.dirname(path);
let directory = dirname(path);
if (directory.indexOf(':', directory.length - 1) !== -1) {
directory += '/';
}

View File

@ -1,6 +1,6 @@
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import Vue from 'vue/dist/vue.esm.browser.min.js';
import Vuex from 'vuex/dist/vuex.esm.browser.min.js';
import createPersistedState from 'vuex-persistedstate/dist/vuex-persistedstate.es.js';
import state from './state.es6';
import * as getters from './getters.es6';
import * as actions from './actions.es6';

View File

@ -1,81 +0,0 @@
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
mode: process.env.NODE_ENV,
entry: [
'./administrator/components/com_media/resources/scripts/mediamanager.es6.js',
'./administrator/components/com_media/resources/styles/mediamanager.scss',
],
output: {
path: path.resolve(__dirname, './../../../media/com_media/js'),
publicPath: '/',
filename: 'mediamanager.min.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
'scss': 'vue-style-loader!css-loader!sass-loader',
'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: false
}
},
'sass-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: './../css/mediamanager.min.css',
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}),
new webpack.LoaderOptionsPlugin({
minimize: process.env.NODE_ENV === 'production'
}),
new VueLoaderPlugin()
],
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
performance: {
hints: false
},
devtool: process.env.NODE_ENV === 'production' ? 'source-map' : 'eval-source-map'
};

View File

@ -7,7 +7,6 @@
],
"parser": "vue-eslint-parser",
"parserOptions": {
"sourceType": "module"
},
// ESLint will not look in parent folders for eslint configs
@ -22,7 +21,7 @@
"globals": {
"Joomla": true,
"MediaManager" : true,
"bootstrap": true,
"bootstrap": true
},
// Rule overrides
"rules": {
@ -33,6 +32,8 @@
// Allow strict mode (we are not dealing with modules)
"strict": [0],
// Disable alert rule till we have a CE in place
"no-alert": 0
"no-alert": 0,
// Allow extensions on imports
"import/extensions": 0
}
}

View File

@ -33,6 +33,21 @@ const build = async () => {
replace({
'process.env.NODE_ENV': '\'production\'',
}),
babel({
exclude: 'node_modules/core-js/**',
babelHelpers: 'bundled',
babelrc: false,
presets: [
[
'@babel/preset-env',
{
targets: {
esmodules: true,
},
},
],
],
}),
],
external: [
'./base-component.js',

View File

@ -0,0 +1,120 @@
const { readFile, writeFile } = require('fs').promises;
const { resolve } = require('path');
const { minify } = require('terser');
const rollup = require('rollup');
const { nodeResolve } = require('@rollup/plugin-node-resolve');
const replace = require('@rollup/plugin-replace');
const { babel } = require('@rollup/plugin-babel');
const VuePlugin = require('rollup-plugin-vue');
const commonjs = require('@rollup/plugin-commonjs');
const inputJS = 'administrator/components/com_media/resources/scripts/mediamanager.es6.js';
const createMinified = async (file, contents) => {
const mini = await minify(contents, { sourceMap: false, format: { comments: false } });
await writeFile(file, mini.code, { encoding: 'utf8' });
};
const buildLegacy = async (file) => {
// eslint-disable-next-line no-console
console.log('Building Legacy Media Manager...');
const bundle = await rollup.rollup({
input: file,
plugins: [
nodeResolve(),
commonjs(),
babel({
exclude: 'node_modules/core-js/**',
babelHelpers: 'bundled',
babelrc: false,
presets: [
[
'@babel/preset-env',
{
corejs: '3.8',
useBuiltIns: 'usage',
targets: {
ie: '11',
},
loose: true,
bugfixes: true,
modules: false,
ignoreBrowserslistConfig: true,
},
],
],
}),
],
external: [],
});
await bundle.write({
format: 'iife',
sourcemap: false,
name: 'JoomlaMediaManager',
file: 'media/com_media/js/media-manager-es5.js',
});
// closes the bundle
await bundle.close();
const contents = await readFile('media/com_media/js/media-manager-es5.js', { encoding: 'utf8' });
await createMinified(resolve('media/com_media/js/media-manager-es5.min.js'), contents);
// eslint-disable-next-line no-console
console.log('Legacy Media Manager ready ✅');
};
module.exports.mediaManager = async () => {
// eslint-disable-next-line no-console
console.log('Building Media Manager ES Module...');
const bundle = await rollup.rollup({
input: resolve(inputJS),
plugins: [
VuePlugin({
target: 'browser',
css: false,
compileTemplate: true,
template: {
isProduction: true,
},
}),
nodeResolve(),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
babel({
exclude: 'node_modules/core-js/**',
babelHelpers: 'bundled',
babelrc: false,
presets: [
[
'@babel/preset-env',
{
targets: {
esmodules: true,
},
loose: true,
bugfixes: false,
ignoreBrowserslistConfig: true,
},
],
],
}),
],
});
await bundle.write({
format: 'es',
sourcemap: false,
file: 'media/com_media/js/media-manager.js',
});
// closes the bundle
await bundle.close();
const contents = await readFile('media/com_media/js/media-manager.js', { encoding: 'utf8' });
await createMinified(resolve('media/com_media/js/media-manager.min.js'), contents);
// eslint-disable-next-line no-console
console.log('ES2017 Media Manager ready ✅');
await buildLegacy(resolve('media/com_media/js/media-manager.js'));
};

View File

@ -6,12 +6,14 @@
* npm ci
*
* For dedicated tasks, please run:
* node build.js --build-pages === will create the error pages (for incomplete repo build PHP+NPM)
* node build.js --copy-assets === will clean the media/vendor folder and then will populate the folder from node_modules
* node build.js --compile-js === will transpile ES6 files and also uglify the ES6,ES5 files
* node build.js --compile-css === will compile all the scss defined files and also create a minified version of the css
* node build.js --compile-bs === will compile all the Bootstrap javascript components
* node build.js --gzip === will create gzip files for all the minified stylesheets and scripts.'
* node build.js --build-pages will create the error pages (for incomplete repo build PHP+NPM)
* node build.js --copy-assets will clean the media/vendor folder and then will populate the folder from node_modules
* node build.js --compile-js will transpile ES6 files and also uglify the ES6,ES5 files
* node build.js --compile-css will compile all the scss defined files and also create a minified version of the css
* node build.js --compile-bs will compile all the Bootstrap javascript components
* node build.js --com-media will compile the media manager Vue application
* node build.js --watch-com-media will compile the media manager Vue application
* node build.js --gzip will create gzip files for all the minified stylesheets and scripts.
*/
// eslint-disable-next-line import/no-extraneous-dependencies
@ -30,6 +32,7 @@ const { patchPackages } = require('./build-modules-js/init/patches.es6.js');
const { cleanVendors } = require('./build-modules-js/init/cleanup-media.es6.js');
const { recreateMediaFolder } = require('./build-modules-js/init/recreate-media.es6');
const { watching } = require('./build-modules-js/watch.es6.js');
const { mediaManager } = require('./build-modules-js/javascript/build-com_media-js.es6');
const { compressFiles } = require('./build-modules-js/compress.es6.js');
// The settings
@ -74,6 +77,8 @@ Program
.option('--compile-css, --compile-css path', 'Compiles all the scss files to css')
.option('--compile-bs', 'Compiles all the Bootstrap component scripts.')
.option('--watch', 'Watch file changes and re-compile (ATM only works for the js in the media_source).')
.option('--com-media', 'Compile the Media Manager client side App.')
.option('--watch-com-media', 'Watch and Compile the Media Manager client side App.')
.option('--gzip', 'Compress all the minified stylesheets and scripts.')
.option('--prepare', 'Run all the needed tasks to initialise the repo')
.on('--help', () => {
@ -136,6 +141,17 @@ if (Program.gzip) {
compressFiles();
}
// Compile the media manager
if (Program.comMedia) {
// false indicates "no watch"
mediaManager(false);
}
// Watch & Compile the media manager
if (Program.watchComMedia) {
mediaManager(true);
}
// Prepare the repo for dev work
if (Program.prepare) {
(async () => {

View File

@ -19,18 +19,30 @@
{
"name": "com_media.mediamanager",
"type": "style",
"uri": "com_media/mediamanager.min.css"
"uri": "com_media/media-manager.min.css"
},
{
"name": "com_media.mediamanager",
"name": "com_media.mediamanager.es5",
"type": "script",
"uri": "com_media/mediamanager.min.js",
"uri": "com_media/media-manager-es5.min.js",
"dependencies": [
"core"
],
"attributes": {
"nomodule": true,
"defer": true
}
},
{
"name": "com_media.mediamanager",
"type": "script",
"uri": "com_media/media-manager.min.js",
"dependencies": [
"com_media.mediamanager.es5"
],
"attributes": {
"type": "module"
}
}
]
}

5403
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -15,17 +15,16 @@
"build:js": "node build/build.js --compile-js",
"build:css": "node build/build.js --compile-css",
"build:bs5": "node build/build.js --compile-bs",
"build:com_media": "node build/build.js --com-media",
"watch": "node build/build.js --watch",
"watch:com_media": "node build/build.js --watch-com-media",
"lint:js": "eslint --config build/.eslintrc --ignore-pattern '/media/' --ext .es6.js,.es6,.vue .",
"lint:css": "stylelint --config build/.stylelintrc.json -s scss \"administrator/components/com_media/resources/**/*.scss\" \"administrator/templates/**/*.scss\" \"build/media_source/**/*.scss\" \"templates/**/*.scss\" \"installation/template/**/*.scss\"",
"test": "karma start tests/javascript/karma.conf.js --single-run",
"install": "node build/build.js --prepare",
"postinstall": "npm run build:com_media",
"update": "node build/build.js --copy-assets && node build/build.js --build-pages && node build/build.js --compile-js && node build/build.js --compile-css && node build/build.js --compile-bs && npm run build:com_media",
"gzip": "node build/build.js --gzip",
"watch:com_media": "cross-env NODE_ENV=development webpack --progress --hide-modules --watch --config administrator/components/com_media/webpack.config.js",
"dev:com_media": "cross-env NODE_ENV=development webpack --progress --hide-modules --config administrator/components/com_media/webpack.config.js",
"build:com_media": "cross-env NODE_ENV=production webpack --progress --hide-modules --config administrator/components/com_media/webpack.config.js"
"prepare:tests": "cd tests && npm i",
"test": "cd tests && karma start javascript/karma.conf.js --single-run",
"install": "node build/build.js --prepare && node build/build.js --com-media",
"update": "node build/build.js --copy-assets && node build/build.js --build-pages && node build/build.js --compile-js && node build/build.js --compile-css && node build/build.js --compile-bs && node build/build.js --com-media",
"gzip": "node build/build.js --gzip"
},
"browserslist": [
"last 1 version",
@ -45,7 +44,6 @@
"cropperjs": "^1.5.9",
"diff": "^4.0.2",
"dragula": "3.7.2",
"file-saver": "^2.0.5",
"focus-visible": "^5.2.0",
"joomla-ui-custom-elements": "0.0.40",
"jquery": "^3.5",
@ -70,24 +68,18 @@
"@babel/preset-env": "^7.12.11",
"@dgrammatiko/compress": "^1.0.4",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-node-resolve": "^11.1.0",
"@rollup/plugin-replace": "^2.3.4",
"autoprefixer": "^9.8.6",
"babel-loader": "^8.2.2",
"babel-plugin-add-header-comment": "^1.0.3",
"babel-preset-minify": "^0.5.1",
"babelify": "^10.0.0",
"browserify": "^16.5.2",
"commander": "^5.1.0",
"core-js": "^3.8.3",
"cross-env": "^7.0.3",
"css-loader": "^3.6.0",
"cssnano": "^4.1.10",
"eslint": "^7.18.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-vue": "^7.5.0",
"file-loader": "^6.2.0",
"fs-extra": "^9.1.0",
"ini": "^1.3.8",
"jasmine-core": "^3.6.0",
@ -100,23 +92,19 @@
"karma-jasmine-ajax": "^0.1.13",
"karma-json-fixtures-preprocessor": "0.0.6",
"karma-verbose-reporter": "^0.0.6",
"mini-css-extract-plugin": "^0.9.0",
"postcss": "^7.0.35",
"recursive-readdir": "^2.2.2",
"rimraf": "^3.0.2",
"rollup": "^2.38.0",
"rollup-plugin-vue": "^5.1.9",
"sass": "^1.32.5",
"sass-loader": "^8.0.2",
"selenium-standalone": "^6.23.0",
"selenium-standalone": "6.23.0",
"stylelint": "^13.9.0",
"stylelint-config-standard": "^20.0.0",
"stylelint-order": "^4.1.0",
"stylelint-scss": "^3.18.0",
"terser": "^5.5.1",
"vue-loader": "^15.9.6",
"vue-template-compiler": "^2.6.12",
"watch": "^1.0.2",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12"
"watch": "^1.0.2"
}
}