webpack.config.js
var path = require('path');
var webpack = require('webpack');
var lodash = require('lodash');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
var {getModuleDir} = require('./tasks/get-module-directory');
function countOccurences(_string, substring) {
return _string.split(substring).length - 1;
}
// makeConfig creates a new configuration file based on the passed options.
module.exports = function makeConfig(grunt) {
var appConfigPath = path.join(process.cwd(), 'superdesk.config.js');
if (process.env.SUPERDESK_CONFIG) {
appConfigPath = path.join(process.cwd(), process.env.SUPERDESK_CONFIG);
}
if (grunt.option('config')) {
appConfigPath = path.join(process.cwd(), grunt.option('config'));
}
const sdConfig = lodash.defaultsDeep(require(appConfigPath)(grunt), getDefaults(grunt));
const apps = sdConfig.importApps || sdConfig.apps || [];
// include only 'superdesk-core' and valid modules inside node_modules
let validModules = [
'superdesk-core',
'planning', // on fireq we store superdesk-planning in linked `planning` folder
].concat(apps);
const jQueryModule = getModuleDir('jquery');
return {
entry: {
app: [path.join(__dirname, 'scripts', 'index')],
},
output: {
path: path.join(process.cwd(), 'dist'),
filename: '[name].bundle.js',
chunkFilename: '[id].bundle.js',
},
plugins: [
new webpack.ProvidePlugin({
$: jQueryModule,
'window.$': jQueryModule,
jQuery: jQueryModule,
'window.jQuery': jQueryModule,
moment: 'moment',
}),
new webpack.DefinePlugin({
__SUPERDESK_CONFIG__: JSON.stringify(sdConfig),
}),
new ExtractTextPlugin({
filename: '[name].bundle.css',
}),
],
resolve: {
modules: [
__dirname,
path.join(__dirname, 'scripts'),
path.join(__dirname, 'styles', 'sass'),
'node_modules',
],
alias: {
'moment-timezone': 'moment-timezone/builds/moment-timezone-with-data-10-year-range',
'rangy-saverestore': 'rangy/lib/rangy-selectionsaverestore',
'angular-embedly': 'angular-embedly/em-minified/angular-embedly.min',
'jquery-gridster': 'gridster/dist/jquery.gridster.min',
'external-apps': path.join(process.cwd(), 'dist', 'app-importer.generated.js'),
/**
* Ensure that react is loaded only once.
* external apps(planning, analytics, ui-framework) may try loading their own react,
* especially when linked with npm in development mode.
*/
react: getModuleDir('react'),
'react-dom': getModuleDir('react-dom'),
},
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
module: {
rules: [
{
test: /\.(ts|tsx|js|jsx)$/,
exclude: function(absolutePath) {
// Exclude files inside `WEBPACK_IGNORE` folder.
// This is only relevant in development.
// It was added to enable linking ui-framework.
if (absolutePath.includes('WEBPACK_IGNORE')) {
return true;
}
// don't exclude anything outside node_modules
if (absolutePath.indexOf('node_modules') === -1) {
return false;
}
// exclude everything else, unless it's a part of a superdesk app like superdesk-planning
// but is not its dependency.
// For example, `superdesk-planning/node_modules/**/*` will be excluded.
const exclude = !validModules.some(
(app) =>
absolutePath.includes(app) && countOccurences(absolutePath, '/node_modules/') === 1
);
return exclude;
},
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
{
test: /\.html$/,
loader: 'html-loader',
},
{
test: /\.(css|scss)$/i,
use: ExtractTextPlugin.extract({
fallback: [{
loader: 'style-loader',
options: {
sourceMap: true,
},
}],
use: [
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
}),
},
{
test: /\.json$/,
use: ['json-loader'],
},
{
test: /\.(png|gif|jpeg|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)/,
loader: 'file-loader',
},
],
},
};
};
// getDefaults returns the default configuration for the app
function getDefaults(grunt) {
var version;
try {
version = require('git-rev-sync').short('..');
} catch (err) {
// pass
}
return {
// application version
version: version || grunt.file.readJSON(path.join(__dirname, 'package.json')).version,
// raven settings
raven: {
dsn: process.env.SUPERDESK_RAVEN_DSN || '',
},
// backend server URLs configuration
server: {
url: grunt.option('server') || process.env.SUPERDESK_URL || 'http://localhost:5000/api',
ws: grunt.option('ws') || process.env.SUPERDESK_WS_URL || 'ws://0.0.0.0:5100',
},
// iframely settings
iframely: {
key: process.env.IFRAMELY_KEY || '',
},
// google settings
google: {
key: process.env.GOOGLE_KEY || '',
},
// settings for various analytics
analytics: {
piwik: {
url: process.env.PIWIK_URL || '',
id: process.env.PIWIK_SITE_ID || '',
},
ga: {
id: process.env.TRACKING_ID || '',
},
},
// editor configuration
editor: {
// if true, the editor will not have a toolbar
disableEditorToolbar: grunt.option('disableEditorToolbar'),
},
editor3: {
browserSpellCheck: false,
},
// model date and time formats
model: {
dateformat: 'DD/MM/YYYY',
timeformat: 'HH:mm:ss',
},
// view formats for datepickers/timepickers
view: {
dateformat: process.env.VIEW_DATE_FORMAT || 'DD/MM/YYYY',
timeformat: process.env.VIEW_TIME_FORMAT || 'HH:mm',
},
// if environment name is not set
isTestEnvironment: !!grunt.option('environmentName') || !!process.env.SUPERDESK_ENVIRONMENT,
// environment name
environmentName: grunt.option('environmentName') || process.env.SUPERDESK_ENVIRONMENT,
// route to be redirected to from '/'
defaultRoute: '/workspace',
// override language translations
langOverride: {},
// app features
features: {
// tansa spellchecker
useTansaProofing: false,
},
// workspace defaults
workspace: {
ingest: false,
content: false,
tasks: false,
analytics: false,
},
// ingest defaults
ingest: {
PROVIDER_DASHBOARD_DEFAULTS: {
show_log_messages: true,
show_ingest_count: true,
show_time: true,
log_messages: 'error',
show_status: true,
},
DEFAULT_SCHEDULE: {minutes: 5, seconds: 0},
DEFAULT_IDLE_TIME: {hours: 0, minutes: 0},
},
// list of languages available in user profile
profileLanguages: [
'en',
'el',
'en_GB',
'fr_CA',
'es',
'da',
'ar',
'de_DE',
'ru_RU',
'nb',
'uk_UA',
'pt_BR',
'pl',
],
userOnlineMinutes: 15,
};
}