Build: Webpack instead of Browserify as JavaScript bundler.
Use Webpack as our bundler of choice, enabling improved JavaScript build chain capabilities. Props aduth, netweb, kadamwhite, schlessera. Fixes #40894. git-svn-id: https://develop.svn.wordpress.org/trunk@41752 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
a500586603
commit
851d51ebd6
@ -21,6 +21,9 @@
|
||||
"Backbone": false,
|
||||
"jQuery": false,
|
||||
"JSON": false,
|
||||
"wp": false
|
||||
"wp": false,
|
||||
"export": false,
|
||||
"module": false,
|
||||
"require": false
|
||||
}
|
||||
}
|
||||
|
45
Gruntfile.js
45
Gruntfile.js
@ -1,5 +1,8 @@
|
||||
/* jshint node:true */
|
||||
/* globals Set */
|
||||
var webpackConfig = require( './webpack.config.prod' );
|
||||
var webpackDevConfig = require( './webpack.config.dev' );
|
||||
|
||||
module.exports = function(grunt) {
|
||||
var path = require('path'),
|
||||
fs = require( 'fs' ),
|
||||
@ -7,21 +10,13 @@ module.exports = function(grunt) {
|
||||
SOURCE_DIR = 'src/',
|
||||
BUILD_DIR = 'build/',
|
||||
BANNER_TEXT = '/*! This file is auto-generated */',
|
||||
autoprefixer = require('autoprefixer'),
|
||||
mediaConfig = {},
|
||||
mediaBuilds = ['audiovideo', 'grid', 'models', 'views'];
|
||||
autoprefixer = require( 'autoprefixer' );
|
||||
|
||||
// Load tasks.
|
||||
require('matchdep').filterDev(['grunt-*', '!grunt-legacy-util']).forEach( grunt.loadNpmTasks );
|
||||
// Load legacy utils
|
||||
grunt.util = require('grunt-legacy-util');
|
||||
|
||||
mediaBuilds.forEach( function ( build ) {
|
||||
var path = SOURCE_DIR + 'wp-includes/js/media';
|
||||
mediaConfig[ build ] = { files : {} };
|
||||
mediaConfig[ build ].files[ path + '-' + build + '.js' ] = [ path + '/' + build + '.manifest.js' ];
|
||||
} );
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
postcss: {
|
||||
@ -177,7 +172,6 @@ module.exports = function(grunt) {
|
||||
}
|
||||
}
|
||||
},
|
||||
browserify: mediaConfig,
|
||||
sass: {
|
||||
colors: {
|
||||
expand: true,
|
||||
@ -338,9 +332,6 @@ module.exports = function(grunt) {
|
||||
]
|
||||
},
|
||||
media: {
|
||||
options: {
|
||||
browserify: true
|
||||
},
|
||||
src: [
|
||||
SOURCE_DIR + 'wp-includes/js/media/**/*.js'
|
||||
]
|
||||
@ -553,7 +544,10 @@ module.exports = function(grunt) {
|
||||
dest: SOURCE_DIR + 'wp-includes/js/jquery/jquery.masonry.min.js'
|
||||
}
|
||||
},
|
||||
|
||||
webpack: {
|
||||
prod: webpackConfig,
|
||||
dev: webpackDevConfig
|
||||
},
|
||||
concat: {
|
||||
tinymce: {
|
||||
options: {
|
||||
@ -719,7 +713,11 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
config: {
|
||||
files: 'Gruntfile.js'
|
||||
files: [
|
||||
'Gruntfile.js',
|
||||
'webpack-dev.config.js',
|
||||
'webpack.config.js'
|
||||
]
|
||||
},
|
||||
colors: {
|
||||
files: [SOURCE_DIR + 'wp-admin/css/colors/**'],
|
||||
@ -757,6 +755,9 @@ module.exports = function(grunt) {
|
||||
|
||||
// Register tasks.
|
||||
|
||||
// Webpack task.
|
||||
grunt.loadNpmTasks( 'grunt-webpack' );
|
||||
|
||||
// RTL task.
|
||||
grunt.registerTask('rtl', ['rtlcss:core', 'rtlcss:colors']);
|
||||
|
||||
@ -780,15 +781,9 @@ module.exports = function(grunt) {
|
||||
grunt.renameTask( 'watch', '_watch' );
|
||||
|
||||
grunt.registerTask( 'watch', function() {
|
||||
if ( ! this.args.length || this.args.indexOf( 'browserify' ) > -1 ) {
|
||||
grunt.config( 'browserify.options', {
|
||||
browserifyOptions: {
|
||||
debug: true
|
||||
},
|
||||
watch: true
|
||||
} );
|
||||
if ( ! this.args.length || this.args.indexOf( 'webpack' ) > -1 ) {
|
||||
|
||||
grunt.task.run( 'browserify' );
|
||||
grunt.task.run( 'webpack:dev' );
|
||||
}
|
||||
|
||||
grunt.task.run( '_' + this.nameArgs );
|
||||
@ -799,7 +794,7 @@ module.exports = function(grunt) {
|
||||
] );
|
||||
|
||||
grunt.registerTask( 'precommit:js', [
|
||||
'browserify',
|
||||
'webpack:prod',
|
||||
'jshint:corejs',
|
||||
'uglify:masonry',
|
||||
'qunit:compiled'
|
||||
@ -978,7 +973,7 @@ module.exports = function(grunt) {
|
||||
grunt.event.on('watch', function( action, filepath, target ) {
|
||||
var src;
|
||||
|
||||
if ( [ 'all', 'rtl', 'browserify' ].indexOf( target ) === -1 ) {
|
||||
if ( [ 'all', 'rtl', 'webpack' ].indexOf( target ) === -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
"autoprefixer": "^6.5.1",
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-banner": "^0.6.0",
|
||||
"grunt-browserify": "~5.0.0",
|
||||
"grunt-contrib-clean": "~1.0.0",
|
||||
"grunt-contrib-compress": "~1.3.0",
|
||||
"grunt-contrib-concat": "~1.0.0",
|
||||
@ -36,6 +35,9 @@
|
||||
"grunt-rtlcss": "~2.0.1",
|
||||
"grunt-sass": "~1.2.1",
|
||||
"ink-docstrap": "^1.3.0",
|
||||
"matchdep": "~1.0.0"
|
||||
"grunt-webpack": "^3.0.2",
|
||||
"matchdep": "~1.0.0",
|
||||
"webpack": "^3.6.0",
|
||||
"webpack-dev-server": "^2.9.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,72 @@
|
||||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var media = wp.media,
|
||||
baseSettings = window._wpmejsSettings || {},
|
||||
l10n = window._wpMediaViewsL10n || {};
|
||||
@ -268,87 +336,21 @@ wp.media.video = {
|
||||
}
|
||||
};
|
||||
|
||||
media.model.PostMedia = require( './models/post-media.js' );
|
||||
media.controller.AudioDetails = require( './controllers/audio-details.js' );
|
||||
media.controller.VideoDetails = require( './controllers/video-details.js' );
|
||||
media.view.MediaFrame.MediaDetails = require( './views/frame/media-details.js' );
|
||||
media.view.MediaFrame.AudioDetails = require( './views/frame/audio-details.js' );
|
||||
media.view.MediaFrame.VideoDetails = require( './views/frame/video-details.js' );
|
||||
media.view.MediaDetails = require( './views/media-details.js' );
|
||||
media.view.AudioDetails = require( './views/audio-details.js' );
|
||||
media.view.VideoDetails = require( './views/video-details.js' );
|
||||
media.model.PostMedia = __webpack_require__( 1 );
|
||||
media.controller.AudioDetails = __webpack_require__( 2 );
|
||||
media.controller.VideoDetails = __webpack_require__( 3 );
|
||||
media.view.MediaFrame.MediaDetails = __webpack_require__( 4 );
|
||||
media.view.MediaFrame.AudioDetails = __webpack_require__( 5 );
|
||||
media.view.MediaFrame.VideoDetails = __webpack_require__( 6 );
|
||||
media.view.MediaDetails = __webpack_require__( 7 );
|
||||
media.view.AudioDetails = __webpack_require__( 8 );
|
||||
media.view.VideoDetails = __webpack_require__( 9 );
|
||||
|
||||
},{"./controllers/audio-details.js":2,"./controllers/video-details.js":3,"./models/post-media.js":4,"./views/audio-details.js":5,"./views/frame/audio-details.js":6,"./views/frame/media-details.js":7,"./views/frame/video-details.js":8,"./views/media-details.js":9,"./views/video-details.js":10}],2:[function(require,module,exports){
|
||||
var State = wp.media.controller.State,
|
||||
l10n = wp.media.view.l10n,
|
||||
AudioDetails;
|
||||
|
||||
/**
|
||||
* wp.media.controller.AudioDetails
|
||||
*
|
||||
* The controller for the Audio Details state
|
||||
*
|
||||
* @memberOf wp.media.controller
|
||||
*
|
||||
* @class
|
||||
* @augments wp.media.controller.State
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
AudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototype */{
|
||||
defaults: {
|
||||
id: 'audio-details',
|
||||
toolbar: 'audio-details',
|
||||
title: l10n.audioDetailsTitle,
|
||||
content: 'audio-details',
|
||||
menu: 'audio-details',
|
||||
router: false,
|
||||
priority: 60
|
||||
},
|
||||
/***/ }),
|
||||
/* 1 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
initialize: function( options ) {
|
||||
this.media = options.media;
|
||||
State.prototype.initialize.apply( this, arguments );
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AudioDetails;
|
||||
|
||||
},{}],3:[function(require,module,exports){
|
||||
/**
|
||||
* wp.media.controller.VideoDetails
|
||||
*
|
||||
* The controller for the Video Details state
|
||||
*
|
||||
* @memberOf wp.media.controller
|
||||
*
|
||||
* @class
|
||||
* @augments wp.media.controller.State
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
var State = wp.media.controller.State,
|
||||
l10n = wp.media.view.l10n,
|
||||
VideoDetails;
|
||||
|
||||
VideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototype */{
|
||||
defaults: {
|
||||
id: 'video-details',
|
||||
toolbar: 'video-details',
|
||||
title: l10n.videoDetailsTitle,
|
||||
content: 'video-details',
|
||||
menu: 'video-details',
|
||||
router: false,
|
||||
priority: 60
|
||||
},
|
||||
|
||||
initialize: function( options ) {
|
||||
this.media = options.media;
|
||||
State.prototype.initialize.apply( this, arguments );
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = VideoDetails;
|
||||
|
||||
},{}],4:[function(require,module,exports){
|
||||
/**
|
||||
* wp.media.model.PostMedia
|
||||
*
|
||||
@ -392,125 +394,89 @@ var PostMedia = Backbone.Model.extend(/** @lends wp.media.model.PostMedia.protot
|
||||
|
||||
module.exports = PostMedia;
|
||||
|
||||
},{}],5:[function(require,module,exports){
|
||||
var MediaDetails = wp.media.view.MediaDetails,
|
||||
AudioDetails;
|
||||
|
||||
/**
|
||||
* wp.media.view.AudioDetails
|
||||
*
|
||||
* @memberOf wp.media.view
|
||||
*
|
||||
* @class
|
||||
* @augments wp.media.view.MediaDetails
|
||||
* @augments wp.media.view.Settings.AttachmentDisplay
|
||||
* @augments wp.media.view.Settings
|
||||
* @augments wp.media.View
|
||||
* @augments wp.Backbone.View
|
||||
* @augments Backbone.View
|
||||
*/
|
||||
AudioDetails = MediaDetails.extend(/** @lends wp.media.view.AudioDetails.prototype */{
|
||||
className: 'audio-details',
|
||||
template: wp.template('audio-details'),
|
||||
|
||||
setMedia: function() {
|
||||
var audio = this.$('.wp-audio-shortcode');
|
||||
|
||||
if ( audio.find( 'source' ).length ) {
|
||||
if ( audio.is(':hidden') ) {
|
||||
audio.show();
|
||||
}
|
||||
this.media = MediaDetails.prepareSrc( audio.get(0) );
|
||||
} else {
|
||||
audio.hide();
|
||||
this.media = false;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AudioDetails;
|
||||
|
||||
},{}],6:[function(require,module,exports){
|
||||
var MediaDetails = wp.media.view.MediaFrame.MediaDetails,
|
||||
MediaLibrary = wp.media.controller.MediaLibrary,
|
||||
/***/ }),
|
||||
/* 2 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var State = wp.media.controller.State,
|
||||
l10n = wp.media.view.l10n,
|
||||
AudioDetails;
|
||||
|
||||
/**
|
||||
* wp.media.view.MediaFrame.AudioDetails
|
||||
* wp.media.controller.AudioDetails
|
||||
*
|
||||
* @memberOf wp.media.view.MediaFrame
|
||||
* The controller for the Audio Details state
|
||||
*
|
||||
* @memberOf wp.media.controller
|
||||
*
|
||||
* @class
|
||||
* @augments wp.media.view.MediaFrame.MediaDetails
|
||||
* @augments wp.media.view.MediaFrame.Select
|
||||
* @augments wp.media.view.MediaFrame
|
||||
* @augments wp.media.view.Frame
|
||||
* @augments wp.media.View
|
||||
* @augments wp.Backbone.View
|
||||
* @augments Backbone.View
|
||||
* @mixes wp.media.controller.StateMachine
|
||||
* @augments wp.media.controller.State
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
AudioDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.AudioDetails.prototype */{
|
||||
AudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototype */{
|
||||
defaults: {
|
||||
id: 'audio',
|
||||
url: '',
|
||||
menu: 'audio-details',
|
||||
content: 'audio-details',
|
||||
id: 'audio-details',
|
||||
toolbar: 'audio-details',
|
||||
type: 'link',
|
||||
title: l10n.audioDetailsTitle,
|
||||
priority: 120
|
||||
content: 'audio-details',
|
||||
menu: 'audio-details',
|
||||
router: false,
|
||||
priority: 60
|
||||
},
|
||||
|
||||
initialize: function( options ) {
|
||||
options.DetailsView = wp.media.view.AudioDetails;
|
||||
options.cancelText = l10n.audioDetailsCancel;
|
||||
options.addText = l10n.audioAddSourceTitle;
|
||||
|
||||
MediaDetails.prototype.initialize.call( this, options );
|
||||
},
|
||||
|
||||
bindHandlers: function() {
|
||||
MediaDetails.prototype.bindHandlers.apply( this, arguments );
|
||||
|
||||
this.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this );
|
||||
this.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this );
|
||||
},
|
||||
|
||||
createStates: function() {
|
||||
this.states.add([
|
||||
new wp.media.controller.AudioDetails( {
|
||||
media: this.media
|
||||
} ),
|
||||
|
||||
new MediaLibrary( {
|
||||
type: 'audio',
|
||||
id: 'replace-audio',
|
||||
title: l10n.audioReplaceTitle,
|
||||
toolbar: 'replace-audio',
|
||||
media: this.media,
|
||||
menu: 'audio-details'
|
||||
} ),
|
||||
|
||||
new MediaLibrary( {
|
||||
type: 'audio',
|
||||
id: 'add-audio-source',
|
||||
title: l10n.audioAddSourceTitle,
|
||||
toolbar: 'add-audio-source',
|
||||
media: this.media,
|
||||
menu: false
|
||||
} )
|
||||
]);
|
||||
this.media = options.media;
|
||||
State.prototype.initialize.apply( this, arguments );
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AudioDetails;
|
||||
|
||||
},{}],7:[function(require,module,exports){
|
||||
|
||||
/***/ }),
|
||||
/* 3 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* wp.media.controller.VideoDetails
|
||||
*
|
||||
* The controller for the Video Details state
|
||||
*
|
||||
* @memberOf wp.media.controller
|
||||
*
|
||||
* @class
|
||||
* @augments wp.media.controller.State
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
var State = wp.media.controller.State,
|
||||
l10n = wp.media.view.l10n,
|
||||
VideoDetails;
|
||||
|
||||
VideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototype */{
|
||||
defaults: {
|
||||
id: 'video-details',
|
||||
toolbar: 'video-details',
|
||||
title: l10n.videoDetailsTitle,
|
||||
content: 'video-details',
|
||||
menu: 'video-details',
|
||||
router: false,
|
||||
priority: 60
|
||||
},
|
||||
|
||||
initialize: function( options ) {
|
||||
this.media = options.media;
|
||||
State.prototype.initialize.apply( this, arguments );
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = VideoDetails;
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 4 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var Select = wp.media.view.MediaFrame.Select,
|
||||
l10n = wp.media.view.l10n,
|
||||
MediaDetails;
|
||||
@ -642,7 +608,93 @@ MediaDetails = Select.extend(/** @lends wp.media.view.MediaFrame.MediaDetails.pr
|
||||
|
||||
module.exports = MediaDetails;
|
||||
|
||||
},{}],8:[function(require,module,exports){
|
||||
|
||||
/***/ }),
|
||||
/* 5 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var MediaDetails = wp.media.view.MediaFrame.MediaDetails,
|
||||
MediaLibrary = wp.media.controller.MediaLibrary,
|
||||
|
||||
l10n = wp.media.view.l10n,
|
||||
AudioDetails;
|
||||
|
||||
/**
|
||||
* wp.media.view.MediaFrame.AudioDetails
|
||||
*
|
||||
* @memberOf wp.media.view.MediaFrame
|
||||
*
|
||||
* @class
|
||||
* @augments wp.media.view.MediaFrame.MediaDetails
|
||||
* @augments wp.media.view.MediaFrame.Select
|
||||
* @augments wp.media.view.MediaFrame
|
||||
* @augments wp.media.view.Frame
|
||||
* @augments wp.media.View
|
||||
* @augments wp.Backbone.View
|
||||
* @augments Backbone.View
|
||||
* @mixes wp.media.controller.StateMachine
|
||||
*/
|
||||
AudioDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.AudioDetails.prototype */{
|
||||
defaults: {
|
||||
id: 'audio',
|
||||
url: '',
|
||||
menu: 'audio-details',
|
||||
content: 'audio-details',
|
||||
toolbar: 'audio-details',
|
||||
type: 'link',
|
||||
title: l10n.audioDetailsTitle,
|
||||
priority: 120
|
||||
},
|
||||
|
||||
initialize: function( options ) {
|
||||
options.DetailsView = wp.media.view.AudioDetails;
|
||||
options.cancelText = l10n.audioDetailsCancel;
|
||||
options.addText = l10n.audioAddSourceTitle;
|
||||
|
||||
MediaDetails.prototype.initialize.call( this, options );
|
||||
},
|
||||
|
||||
bindHandlers: function() {
|
||||
MediaDetails.prototype.bindHandlers.apply( this, arguments );
|
||||
|
||||
this.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this );
|
||||
this.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this );
|
||||
},
|
||||
|
||||
createStates: function() {
|
||||
this.states.add([
|
||||
new wp.media.controller.AudioDetails( {
|
||||
media: this.media
|
||||
} ),
|
||||
|
||||
new MediaLibrary( {
|
||||
type: 'audio',
|
||||
id: 'replace-audio',
|
||||
title: l10n.audioReplaceTitle,
|
||||
toolbar: 'replace-audio',
|
||||
media: this.media,
|
||||
menu: 'audio-details'
|
||||
} ),
|
||||
|
||||
new MediaLibrary( {
|
||||
type: 'audio',
|
||||
id: 'add-audio-source',
|
||||
title: l10n.audioAddSourceTitle,
|
||||
toolbar: 'add-audio-source',
|
||||
media: this.media,
|
||||
menu: false
|
||||
} )
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AudioDetails;
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 6 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var MediaDetails = wp.media.view.MediaFrame.MediaDetails,
|
||||
MediaLibrary = wp.media.controller.MediaLibrary,
|
||||
l10n = wp.media.view.l10n,
|
||||
@ -779,7 +831,11 @@ VideoDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.VideoDeta
|
||||
|
||||
module.exports = VideoDetails;
|
||||
|
||||
},{}],9:[function(require,module,exports){
|
||||
|
||||
/***/ }),
|
||||
/* 7 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* global MediaElementPlayer */
|
||||
var AttachmentDisplay = wp.media.view.Settings.AttachmentDisplay,
|
||||
$ = jQuery,
|
||||
@ -949,7 +1005,55 @@ MediaDetails = AttachmentDisplay.extend(/** @lends wp.media.view.MediaDetails.pr
|
||||
|
||||
module.exports = MediaDetails;
|
||||
|
||||
},{}],10:[function(require,module,exports){
|
||||
|
||||
/***/ }),
|
||||
/* 8 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var MediaDetails = wp.media.view.MediaDetails,
|
||||
AudioDetails;
|
||||
|
||||
/**
|
||||
* wp.media.view.AudioDetails
|
||||
*
|
||||
* @memberOf wp.media.view
|
||||
*
|
||||
* @class
|
||||
* @augments wp.media.view.MediaDetails
|
||||
* @augments wp.media.view.Settings.AttachmentDisplay
|
||||
* @augments wp.media.view.Settings
|
||||
* @augments wp.media.View
|
||||
* @augments wp.Backbone.View
|
||||
* @augments Backbone.View
|
||||
*/
|
||||
AudioDetails = MediaDetails.extend(/** @lends wp.media.view.AudioDetails.prototype */{
|
||||
className: 'audio-details',
|
||||
template: wp.template('audio-details'),
|
||||
|
||||
setMedia: function() {
|
||||
var audio = this.$('.wp-audio-shortcode');
|
||||
|
||||
if ( audio.find( 'source' ).length ) {
|
||||
if ( audio.is(':hidden') ) {
|
||||
audio.show();
|
||||
}
|
||||
this.media = MediaDetails.prepareSrc( audio.get(0) );
|
||||
} else {
|
||||
audio.hide();
|
||||
this.media = false;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AudioDetails;
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 9 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var MediaDetails = wp.media.view.MediaDetails,
|
||||
VideoDetails;
|
||||
|
||||
@ -994,4 +1098,6 @@ VideoDetails = MediaDetails.extend(/** @lends wp.media.view.VideoDetails.prototy
|
||||
|
||||
module.exports = VideoDetails;
|
||||
|
||||
},{}]},{},[1]);
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,73 @@
|
||||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 20);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ 20:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var $ = jQuery,
|
||||
Attachment, Attachments, l10n, media;
|
||||
|
||||
@ -65,12 +134,12 @@ l10n = media.model.l10n = window._wpMediaModelsL10n || {};
|
||||
media.model.settings = l10n.settings || {};
|
||||
delete l10n.settings;
|
||||
|
||||
Attachment = media.model.Attachment = require( './models/attachment.js' );
|
||||
Attachments = media.model.Attachments = require( './models/attachments.js' );
|
||||
Attachment = media.model.Attachment = __webpack_require__( 21 );
|
||||
Attachments = media.model.Attachments = __webpack_require__( 22 );
|
||||
|
||||
media.model.Query = require( './models/query.js' );
|
||||
media.model.PostImage = require( './models/post-image.js' );
|
||||
media.model.Selection = require( './models/selection.js' );
|
||||
media.model.Query = __webpack_require__( 23 );
|
||||
media.model.PostImage = __webpack_require__( 24 );
|
||||
media.model.Selection = __webpack_require__( 25 );
|
||||
|
||||
/**
|
||||
* ========================================================================
|
||||
@ -238,7 +307,12 @@ $(window).on('unload', function(){
|
||||
window.wp = null;
|
||||
});
|
||||
|
||||
},{"./models/attachment.js":2,"./models/attachments.js":3,"./models/post-image.js":4,"./models/query.js":5,"./models/selection.js":6}],2:[function(require,module,exports){
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 21:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var $ = Backbone.$,
|
||||
Attachment;
|
||||
|
||||
@ -409,7 +483,12 @@ Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototyp
|
||||
|
||||
module.exports = Attachment;
|
||||
|
||||
},{}],3:[function(require,module,exports){
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 22:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* wp.media.model.Attachments
|
||||
*
|
||||
@ -954,163 +1033,12 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen
|
||||
|
||||
module.exports = Attachments;
|
||||
|
||||
},{}],4:[function(require,module,exports){
|
||||
/**
|
||||
* wp.media.model.PostImage
|
||||
*
|
||||
* An instance of an image that's been embedded into a post.
|
||||
*
|
||||
* Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.
|
||||
*
|
||||
* @memberOf wp.media.model
|
||||
*
|
||||
* @class
|
||||
* @augments Backbone.Model
|
||||
*
|
||||
* @param {int} [attributes] Initial model attributes.
|
||||
* @param {int} [attributes.attachment_id] ID of the attachment.
|
||||
**/
|
||||
var PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{
|
||||
|
||||
initialize: function( attributes ) {
|
||||
var Attachment = wp.media.model.Attachment;
|
||||
this.attachment = false;
|
||||
/***/ }),
|
||||
|
||||
if ( attributes.attachment_id ) {
|
||||
this.attachment = Attachment.get( attributes.attachment_id );
|
||||
if ( this.attachment.get( 'url' ) ) {
|
||||
this.dfd = jQuery.Deferred();
|
||||
this.dfd.resolve();
|
||||
} else {
|
||||
this.dfd = this.attachment.fetch();
|
||||
}
|
||||
this.bindAttachmentListeners();
|
||||
}
|
||||
/***/ 23:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
// keep url in sync with changes to the type of link
|
||||
this.on( 'change:link', this.updateLinkUrl, this );
|
||||
this.on( 'change:size', this.updateSize, this );
|
||||
|
||||
this.setLinkTypeFromUrl();
|
||||
this.setAspectRatio();
|
||||
|
||||
this.set( 'originalUrl', attributes.url );
|
||||
},
|
||||
|
||||
bindAttachmentListeners: function() {
|
||||
this.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl );
|
||||
this.listenTo( this.attachment, 'sync', this.setAspectRatio );
|
||||
this.listenTo( this.attachment, 'change', this.updateSize );
|
||||
},
|
||||
|
||||
changeAttachment: function( attachment, props ) {
|
||||
this.stopListening( this.attachment );
|
||||
this.attachment = attachment;
|
||||
this.bindAttachmentListeners();
|
||||
|
||||
this.set( 'attachment_id', this.attachment.get( 'id' ) );
|
||||
this.set( 'caption', this.attachment.get( 'caption' ) );
|
||||
this.set( 'alt', this.attachment.get( 'alt' ) );
|
||||
this.set( 'size', props.get( 'size' ) );
|
||||
this.set( 'align', props.get( 'align' ) );
|
||||
this.set( 'link', props.get( 'link' ) );
|
||||
this.updateLinkUrl();
|
||||
this.updateSize();
|
||||
},
|
||||
|
||||
setLinkTypeFromUrl: function() {
|
||||
var linkUrl = this.get( 'linkUrl' ),
|
||||
type;
|
||||
|
||||
if ( ! linkUrl ) {
|
||||
this.set( 'link', 'none' );
|
||||
return;
|
||||
}
|
||||
|
||||
// default to custom if there is a linkUrl
|
||||
type = 'custom';
|
||||
|
||||
if ( this.attachment ) {
|
||||
if ( this.attachment.get( 'url' ) === linkUrl ) {
|
||||
type = 'file';
|
||||
} else if ( this.attachment.get( 'link' ) === linkUrl ) {
|
||||
type = 'post';
|
||||
}
|
||||
} else {
|
||||
if ( this.get( 'url' ) === linkUrl ) {
|
||||
type = 'file';
|
||||
}
|
||||
}
|
||||
|
||||
this.set( 'link', type );
|
||||
},
|
||||
|
||||
updateLinkUrl: function() {
|
||||
var link = this.get( 'link' ),
|
||||
url;
|
||||
|
||||
switch( link ) {
|
||||
case 'file':
|
||||
if ( this.attachment ) {
|
||||
url = this.attachment.get( 'url' );
|
||||
} else {
|
||||
url = this.get( 'url' );
|
||||
}
|
||||
this.set( 'linkUrl', url );
|
||||
break;
|
||||
case 'post':
|
||||
this.set( 'linkUrl', this.attachment.get( 'link' ) );
|
||||
break;
|
||||
case 'none':
|
||||
this.set( 'linkUrl', '' );
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateSize: function() {
|
||||
var size;
|
||||
|
||||
if ( ! this.attachment ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.get( 'size' ) === 'custom' ) {
|
||||
this.set( 'width', this.get( 'customWidth' ) );
|
||||
this.set( 'height', this.get( 'customHeight' ) );
|
||||
this.set( 'url', this.get( 'originalUrl' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];
|
||||
|
||||
if ( ! size ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set( 'url', size.url );
|
||||
this.set( 'width', size.width );
|
||||
this.set( 'height', size.height );
|
||||
},
|
||||
|
||||
setAspectRatio: function() {
|
||||
var full;
|
||||
|
||||
if ( this.attachment && this.attachment.get( 'sizes' ) ) {
|
||||
full = this.attachment.get( 'sizes' ).full;
|
||||
|
||||
if ( full ) {
|
||||
this.set( 'aspectRatio', full.width / full.height );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) );
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = PostImage;
|
||||
|
||||
},{}],5:[function(require,module,exports){
|
||||
var Attachments = wp.media.model.Attachments,
|
||||
Query;
|
||||
|
||||
@ -1418,7 +1346,173 @@ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{
|
||||
|
||||
module.exports = Query;
|
||||
|
||||
},{}],6:[function(require,module,exports){
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 24:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* wp.media.model.PostImage
|
||||
*
|
||||
* An instance of an image that's been embedded into a post.
|
||||
*
|
||||
* Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.
|
||||
*
|
||||
* @memberOf wp.media.model
|
||||
*
|
||||
* @class
|
||||
* @augments Backbone.Model
|
||||
*
|
||||
* @param {int} [attributes] Initial model attributes.
|
||||
* @param {int} [attributes.attachment_id] ID of the attachment.
|
||||
**/
|
||||
var PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{
|
||||
|
||||
initialize: function( attributes ) {
|
||||
var Attachment = wp.media.model.Attachment;
|
||||
this.attachment = false;
|
||||
|
||||
if ( attributes.attachment_id ) {
|
||||
this.attachment = Attachment.get( attributes.attachment_id );
|
||||
if ( this.attachment.get( 'url' ) ) {
|
||||
this.dfd = jQuery.Deferred();
|
||||
this.dfd.resolve();
|
||||
} else {
|
||||
this.dfd = this.attachment.fetch();
|
||||
}
|
||||
this.bindAttachmentListeners();
|
||||
}
|
||||
|
||||
// keep url in sync with changes to the type of link
|
||||
this.on( 'change:link', this.updateLinkUrl, this );
|
||||
this.on( 'change:size', this.updateSize, this );
|
||||
|
||||
this.setLinkTypeFromUrl();
|
||||
this.setAspectRatio();
|
||||
|
||||
this.set( 'originalUrl', attributes.url );
|
||||
},
|
||||
|
||||
bindAttachmentListeners: function() {
|
||||
this.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl );
|
||||
this.listenTo( this.attachment, 'sync', this.setAspectRatio );
|
||||
this.listenTo( this.attachment, 'change', this.updateSize );
|
||||
},
|
||||
|
||||
changeAttachment: function( attachment, props ) {
|
||||
this.stopListening( this.attachment );
|
||||
this.attachment = attachment;
|
||||
this.bindAttachmentListeners();
|
||||
|
||||
this.set( 'attachment_id', this.attachment.get( 'id' ) );
|
||||
this.set( 'caption', this.attachment.get( 'caption' ) );
|
||||
this.set( 'alt', this.attachment.get( 'alt' ) );
|
||||
this.set( 'size', props.get( 'size' ) );
|
||||
this.set( 'align', props.get( 'align' ) );
|
||||
this.set( 'link', props.get( 'link' ) );
|
||||
this.updateLinkUrl();
|
||||
this.updateSize();
|
||||
},
|
||||
|
||||
setLinkTypeFromUrl: function() {
|
||||
var linkUrl = this.get( 'linkUrl' ),
|
||||
type;
|
||||
|
||||
if ( ! linkUrl ) {
|
||||
this.set( 'link', 'none' );
|
||||
return;
|
||||
}
|
||||
|
||||
// default to custom if there is a linkUrl
|
||||
type = 'custom';
|
||||
|
||||
if ( this.attachment ) {
|
||||
if ( this.attachment.get( 'url' ) === linkUrl ) {
|
||||
type = 'file';
|
||||
} else if ( this.attachment.get( 'link' ) === linkUrl ) {
|
||||
type = 'post';
|
||||
}
|
||||
} else {
|
||||
if ( this.get( 'url' ) === linkUrl ) {
|
||||
type = 'file';
|
||||
}
|
||||
}
|
||||
|
||||
this.set( 'link', type );
|
||||
},
|
||||
|
||||
updateLinkUrl: function() {
|
||||
var link = this.get( 'link' ),
|
||||
url;
|
||||
|
||||
switch( link ) {
|
||||
case 'file':
|
||||
if ( this.attachment ) {
|
||||
url = this.attachment.get( 'url' );
|
||||
} else {
|
||||
url = this.get( 'url' );
|
||||
}
|
||||
this.set( 'linkUrl', url );
|
||||
break;
|
||||
case 'post':
|
||||
this.set( 'linkUrl', this.attachment.get( 'link' ) );
|
||||
break;
|
||||
case 'none':
|
||||
this.set( 'linkUrl', '' );
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateSize: function() {
|
||||
var size;
|
||||
|
||||
if ( ! this.attachment ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.get( 'size' ) === 'custom' ) {
|
||||
this.set( 'width', this.get( 'customWidth' ) );
|
||||
this.set( 'height', this.get( 'customHeight' ) );
|
||||
this.set( 'url', this.get( 'originalUrl' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];
|
||||
|
||||
if ( ! size ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set( 'url', size.url );
|
||||
this.set( 'width', size.width );
|
||||
this.set( 'height', size.height );
|
||||
},
|
||||
|
||||
setAspectRatio: function() {
|
||||
var full;
|
||||
|
||||
if ( this.attachment && this.attachment.get( 'sizes' ) ) {
|
||||
full = this.attachment.get( 'sizes' ).full;
|
||||
|
||||
if ( full ) {
|
||||
this.set( 'aspectRatio', full.width / full.height );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) );
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = PostImage;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 25:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var Attachments = wp.media.model.Attachments,
|
||||
Selection;
|
||||
|
||||
@ -1517,4 +1611,7 @@ Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{
|
||||
|
||||
module.exports = Selection;
|
||||
|
||||
},{}]},{},[1]);
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
File diff suppressed because it is too large
Load Diff
21
webpack.config.dev.js
Normal file
21
webpack.config.dev.js
Normal file
@ -0,0 +1,21 @@
|
||||
var path = require( 'path' ),
|
||||
SOURCE_DIR = 'src/',
|
||||
mediaConfig = {},
|
||||
mediaBuilds = [ 'audiovideo', 'grid', 'models', 'views' ],
|
||||
webpack = require( 'webpack' );
|
||||
|
||||
|
||||
mediaBuilds.forEach( function ( build ) {
|
||||
var path = SOURCE_DIR + 'wp-includes/js/media';
|
||||
mediaConfig[ build ] = './' + path + '/' + build + '.manifest.js';
|
||||
} );
|
||||
|
||||
module.exports = {
|
||||
cache: true,
|
||||
watch: true,
|
||||
entry: mediaConfig,
|
||||
output: {
|
||||
path: path.join( __dirname, 'src/wp-includes/js' ),
|
||||
filename: 'media-[name].js'
|
||||
}
|
||||
};
|
23
webpack.config.prod.js
Normal file
23
webpack.config.prod.js
Normal file
@ -0,0 +1,23 @@
|
||||
var path = require( 'path' ),
|
||||
SOURCE_DIR = 'src/',
|
||||
mediaConfig = {},
|
||||
mediaBuilds = [ 'audiovideo', 'grid', 'models', 'views' ],
|
||||
webpack = require( 'webpack' );
|
||||
|
||||
|
||||
mediaBuilds.forEach( function ( build ) {
|
||||
var path = SOURCE_DIR + 'wp-includes/js/media';
|
||||
mediaConfig[ build ] = './' + path + '/' + build + '.manifest.js';
|
||||
} );
|
||||
|
||||
module.exports = {
|
||||
cache: true,
|
||||
entry: mediaConfig,
|
||||
output: {
|
||||
path: path.join( __dirname, 'src/wp-includes/js' ),
|
||||
filename: 'media-[name].js'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.ModuleConcatenationPlugin()
|
||||
]
|
||||
};
|
Loading…
Reference in New Issue
Block a user