Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable ckeditor5 builds to work with RequireJS #385

Merged
merged 8 commits into from
Mar 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,13 @@ module.exports = class MultipleLanguageTranslationService extends EventEmitter {
}

const mainAssetName = compilationAssetNames[ 0 ];
const mainCompilationAsset = compilationAssets[ mainAssetName ];

const mainTranslationAsset = this._getTranslationAssets( outputDirectory, [ this._mainLanguage ] )[ 0 ];

const mergedCompilationAsset = {
outputBody: mainCompilationAsset.source() + '\n;' + mainTranslationAsset.outputBody,
outputPath: mainAssetName
outputBody: mainTranslationAsset.outputBody,
outputPath: mainAssetName,
shouldConcat: true
};

const otherLanguages = Array.from( this._languages )
Expand Down Expand Up @@ -211,7 +211,16 @@ module.exports = class MultipleLanguageTranslationService extends EventEmitter {
const stringifiedTranslations = JSON.stringify( translatedStrings )
.replace( /"([a-z]+)":/g, '$1:' );

const outputBody = `CKEDITOR_TRANSLATIONS.add('${ language }',${ stringifiedTranslations })`;
const outputBody = (
// We need to ensure that the CKEDITOR_TRANSLATIONS variable exists and if it exists, we need to extend it.
// Use ES5 because this bit will not be transpiled!
'(function(d){' +
`d['${ language }']=Object.assign(` +
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still an ES6 code. We can change it to for in loop to be fully ES5 compatible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.assign() needs to be provided by a polyfill for the rest of the code anyway. This doesn't get transpiled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be tricky for someone, as we add that code at the top of the bundle.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now we don't support any non-ES6 env anyway, so it's even hard to test. Let's keep it in our minds. But I don't see a problem in injecting the ES6 polyfill before our scripts.

`d['${ language }']||{},` +
`${ stringifiedTranslations }` +
')' +
'})(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this kind of access to the global object (through window) is going to hurt in some odd envs, but let's keep it for now.

);

return { outputBody, outputPath };
} );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,14 @@ describe( 'translations', () => {
expect( assets ).to.deep.equal( [
{
outputPath: 'ckeditor.js',
outputBody: 'source\n;CKEDITOR_TRANSLATIONS.add(\'pl\',{a:"Anuluj",b:"Zapisz"})'
outputBody: '(function(d){d[\'pl\']=Object.assign(d[\'pl\']||{},{a:"Anuluj",b:"Zapisz"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));',
shouldConcat: true
},
{
outputPath: path.join( 'lang', 'en.js' ),
outputBody: 'CKEDITOR_TRANSLATIONS.add(\'en\',{a:"Cancel",b:"Save"})'
outputBody: '(function(d){d[\'en\']=Object.assign(d[\'en\']||{},{a:"Cancel",b:"Save"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));'
}
] );
} );
Expand Down Expand Up @@ -283,11 +286,14 @@ describe( 'translations', () => {
expect( assets ).to.deep.equal( [
{
outputPath: 'ckeditor.js',
outputBody: 'source\n;CKEDITOR_TRANSLATIONS.add(\'pl\',{a:"Anuluj",b:"Zapisz"})'
outputBody: '(function(d){d[\'pl\']=Object.assign(d[\'pl\']||{},{a:"Anuluj",b:"Zapisz"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));',
shouldConcat: true
},
{
outputPath: path.join( 'lang', 'xxx.js' ),
outputBody: 'CKEDITOR_TRANSLATIONS.add(\'xxx\',{a:"Cancel",b:"Save"})'
outputBody: '(function(d){d[\'xxx\']=Object.assign(d[\'xxx\']||{},{a:"Cancel",b:"Save"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));'
}
] );
} );
Expand Down Expand Up @@ -381,7 +387,9 @@ describe( 'translations', () => {
expect( assets ).to.deep.equal( [
{
outputPath: 'ckeditor.js',
outputBody: 'source\n;CKEDITOR_TRANSLATIONS.add(\'pl\',{a:"Anuluj",b:"Zapisz"})'
outputBody: '(function(d){d[\'pl\']=Object.assign(d[\'pl\']||{},{a:"Anuluj",b:"Zapisz"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));',
shouldConcat: true
}
] );
} );
Expand Down Expand Up @@ -421,7 +429,8 @@ describe( 'translations', () => {
expect( assets ).to.deep.equal( [
{
outputPath: path.join( 'lang', 'pl.js' ),
outputBody: 'CKEDITOR_TRANSLATIONS.add(\'pl\',{a:"Anuluj",b:"Zapisz"})'
outputBody: '(function(d){d[\'pl\']=Object.assign(d[\'pl\']||{},{a:"Anuluj",b:"Zapisz"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));'
}
] );
} );
Expand Down Expand Up @@ -457,11 +466,14 @@ describe( 'translations', () => {
expect( assets ).to.deep.equal( [
{
outputPath: 'ckeditor.js',
outputBody: 'source\n;CKEDITOR_TRANSLATIONS.add(\'pl\',{a:"Anuluj"})'
outputBody: '(function(d){d[\'pl\']=Object.assign(d[\'pl\']||{},{a:"Anuluj"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));',
shouldConcat: true
},
{
outputPath: path.join( 'custom-lang-path', 'en.js' ),
outputBody: 'CKEDITOR_TRANSLATIONS.add(\'en\',{a:"Cancel"})'
outputBody: '(function(d){d[\'en\']=Object.assign(d[\'en\']||{},{a:"Cancel"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));'
}
] );
} );
Expand Down Expand Up @@ -538,11 +550,14 @@ describe( 'translations', () => {
expect( assets ).to.deep.equal( [
{
outputPath: 'ckeditor.js',
outputBody: 'source\n;CKEDITOR_TRANSLATIONS.add(\'pl\',{a:"Zapisz"})'
outputBody: '(function(d){d[\'pl\']=Object.assign(d[\'pl\']||{},{a:"Zapisz"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));',
shouldConcat: true
},
{
outputPath: path.join( 'lang', 'de.js' ),
outputBody: 'CKEDITOR_TRANSLATIONS.add(\'de\',{a:"Speichern"})'
outputBody: '(function(d){d[\'de\']=Object.assign(d[\'de\']||{},{a:"Speichern"})})' +
'(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));'
}
] );
} );
Expand Down
44 changes: 31 additions & 13 deletions packages/ckeditor5-dev-webpack-plugin/lib/servetranslations.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const chalk = require( 'chalk' );
const rimraf = require( 'rimraf' );
const fs = require( 'fs' );
const path = require( 'path' );
const { RawSource, ConcatSource } = require( 'webpack-sources' );

/**
* Serve translations depending on the used translation service and passed options.
Expand Down Expand Up @@ -77,20 +78,37 @@ module.exports = function serveTranslations( compiler, options, translationServi
} );

// At the end of the compilation add assets generated from the PO files.
compiler.plugin( 'emit', ( compilation, done ) => {
const generatedAssets = translationService.getAssets( {
outputDirectory: options.outputDirectory,
compilationAssets: compilation.assets
} );

for ( const asset of generatedAssets ) {
compilation.assets[ asset.outputPath ] = {
source: () => asset.outputBody,
size: () => asset.outputBody.length,
};
}
// Use `optimize-chunk-assets` instead of `emit` to emit assets before the `webpack.BannerPlugin`.
compiler.plugin( 'compilation', compilation => {
compilation.plugin( 'optimize-chunk-assets', ( chunks, done ) => {
const generatedAssets = translationService.getAssets( {
outputDirectory: options.outputDirectory,
compilationAssets: compilation.assets
} );

const allFiles = chunks.reduce( ( acc, chunk ) => [ ...acc, ...chunk.files ], [] );

for ( const asset of generatedAssets ) {
if ( asset.shouldConcat ) {
// We need to concat sources here to support source maps for CKE5 code.
const originalAsset = compilation.assets[ asset.outputPath ];
compilation.assets[ asset.outputPath ] = new ConcatSource( asset.outputBody, '\n', originalAsset );
} else {
const chunkExists = allFiles.includes( asset.outputPath );

if ( !chunkExists ) {
// RawSource is used when corresponding chunk does not exist.
compilation.assets[ asset.outputPath ] = new RawSource( asset.outputBody );
} else {
// String is used when corresponding chunk exists and maintain proper sourcemaps.
// Changing to RawSource would drop source maps.
compilation.assets[ asset.outputPath ] = asset.outputBody;
}
}
}

done();
done();
} );
} );

function emitError( error ) {
Expand Down