Skip to content

Commit

Permalink
Merge pull request #5003 from ckeditor/t/4761-2
Browse files Browse the repository at this point in the history
  • Loading branch information
Comandeer authored Jan 12, 2022
2 parents f0e691b + 492b855 commit f8caf0b
Show file tree
Hide file tree
Showing 11 changed files with 384 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ Fixed issues:
* [#4875](https://github.com/ckeditor/ckeditor4/issues/4875): Fixed: Not possible to delete multiple selected lists.
* [#4873](https://github.com/ckeditor/ckeditor4/issues/4873): Fixed: Pasting content from MS Word and Outlook with horizontal lines prevents images from being uploaded.
* [#4952](https://github.com/ckeditor/ckeditor4/issues/4952): Fixed: Dragging and dropping images within a table cells appends additional elements.
* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): Fixed: not all resources loaded by the editor respect the cache key.

API changes:

* [#4918](https://github.com/ckeditor/ckeditor4/issues/4918): Explicitly set [`config.useComputedState`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-useComputedState) default value to `true`. Thanks to [Shabab Karim](https://github.com/shabab477)!
* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): [`CKEDITOR.appendTimestamp()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-appendTimestamp) function was added.
* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): [`CKEDITOR.dom.document#appendStyleSheet()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_document.html#method-appendStyleSheet) and [`CKEDITOR.tools.buildStyleHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-buildStyleHtml) now use newly added [`CKEDITOR.appendTimestamp()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-appendTimestamp) function to correctly handle caching of CSS files.

Other changes:

Expand Down
2 changes: 1 addition & 1 deletion ckeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/* jshint ignore:start */
/* jscs:disable */
// replace_start
window.CKEDITOR||(window.CKEDITOR=function(){var o,d=/(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i,e={timestamp:"",version:"%VERSION%",revision:"%REV%",rnd:Math.floor(900*Math.random())+100,_:{pending:[],basePathSrcPattern:d},status:"unloaded",basePath:function(){var t=window.CKEDITOR_BASEPATH||"";if(!t)for(var e=document.getElementsByTagName("script"),n=0;n<e.length;n++){var a=e[n].src.match(d);if(a){t=a[1];break}}if(-1==t.indexOf(":/")&&"//"!=t.slice(0,2)&&(t=0===t.indexOf("/")?location.href.match(/^.*?:\/\/[^\/]*/)[0]+t:location.href.match(/^[^\?]*\/(?:)/)[0]+t),!t)throw'The CKEditor installation path could not be automatically detected. Please set the global variable "CKEDITOR_BASEPATH" before creating editor instances.';return t}(),getUrl:function(t){return-1==t.indexOf(":/")&&0!==t.indexOf("/")&&(t=this.basePath+t),this.timestamp&&"/"!=t.charAt(t.length-1)&&!/[&?]t=/.test(t)&&(t+=(0<=t.indexOf("?")?"&":"?")+"t="+this.timestamp),t},domReady:(o=[],function(t){if(o.push(t),"complete"===document.readyState&&setTimeout(i,1),1==o.length)if(document.addEventListener)document.addEventListener("DOMContentLoaded",i,!1),window.addEventListener("load",i,!1);else if(document.attachEvent){document.attachEvent("onreadystatechange",i),window.attachEvent("onload",i);var e=!1;try{e=!window.frameElement}catch(n){}document.documentElement.doScroll&&e&&!function a(){try{document.documentElement.doScroll("left")}catch(n){return void setTimeout(a,1)}i()}()}})};function i(){try{document.addEventListener?(document.removeEventListener("DOMContentLoaded",i,!1),window.removeEventListener("load",i,!1),n()):document.attachEvent&&"complete"===document.readyState&&(document.detachEvent("onreadystatechange",i),window.detachEvent("onload",i),n())}catch(t){}}function n(){for(var t;t=o.shift();)t()}var a,r=window.CKEDITOR_GETURL;return r&&(a=e.getUrl,e.getUrl=function(t){return r.call(e,t)||a.call(e,t)}),e}());
window.CKEDITOR||(window.CKEDITOR=function(){var o,d=/(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i,e={timestamp:"",version:"%VERSION%",revision:"%REV%",rnd:Math.floor(900*Math.random())+100,_:{pending:[],basePathSrcPattern:d},status:"unloaded",basePath:function(){var t=window.CKEDITOR_BASEPATH||"";if(!t)for(var e=document.getElementsByTagName("script"),n=0;n<e.length;n++){var a=e[n].src.match(d);if(a){t=a[1];break}}if(-1==t.indexOf(":/")&&"//"!=t.slice(0,2)&&(t=0===t.indexOf("/")?location.href.match(/^.*?:\/\/[^\/]*/)[0]+t:location.href.match(/^[^\?]*\/(?:)/)[0]+t),!t)throw'The CKEditor installation path could not be automatically detected. Please set the global variable "CKEDITOR_BASEPATH" before creating editor instances.';return t}(),getUrl:function(t){return-1==t.indexOf(":/")&&0!==t.indexOf("/")&&(t=this.basePath+t),t=this.appendTimestamp(t)},appendTimestamp:function(t){if(!this.timestamp||"/"===t.charAt(t.length-1)||/[&?]t=/.test(t))return t;var e=0<=t.indexOf("?")?"&":"?";return t+e+"t="+this.timestamp},domReady:(o=[],function(t){if(o.push(t),"complete"===document.readyState&&setTimeout(i,1),1==o.length)if(document.addEventListener)document.addEventListener("DOMContentLoaded",i,!1),window.addEventListener("load",i,!1);else if(document.attachEvent){document.attachEvent("onreadystatechange",i),window.attachEvent("onload",i);var e=!1;try{e=!window.frameElement}catch(n){}document.documentElement.doScroll&&e&&!function a(){try{document.documentElement.doScroll("left")}catch(n){return void setTimeout(a,1)}i()}()}})};function i(){try{document.addEventListener?(document.removeEventListener("DOMContentLoaded",i,!1),window.removeEventListener("load",i,!1),n()):document.attachEvent&&"complete"===document.readyState&&(document.detachEvent("onreadystatechange",i),window.detachEvent("onload",i),n())}catch(t){}}function n(){for(var t;t=o.shift();)t()}var a,r=window.CKEDITOR_GETURL;return r&&(a=e.getUrl,e.getUrl=function(t){return r.call(e,t)||a.call(e,t)}),e}());
// replace_end
/* jscs:enable */
/* jshint ignore:end */
Expand Down
25 changes: 22 additions & 3 deletions core/ckeditor_base.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,32 @@ if ( !window.CKEDITOR ) {
if ( resource.indexOf( ':/' ) == -1 && resource.indexOf( '/' ) !== 0 )
resource = this.basePath + resource;

// Add the timestamp, except for directories.
if ( this.timestamp && resource.charAt( resource.length - 1 ) != '/' && !( /[&?]t=/ ).test( resource ) )
resource += ( resource.indexOf( '?' ) >= 0 ? '&' : '?' ) + 't=' + this.timestamp;
resource = this.appendTimestamp( resource );

return resource;
},

/**
* Appends {@link CKEDITOR#timestamp} to the provided URL as querystring parameter ("t").
*
* Leaves the URL unchanged if it is a directory URL or it already contains querystring parameter.
*
* @since 4.17.2
* @param {String} resource The resource URL to which the timestamp should be appended.
* @returns {String} The resource URL with cache key appended whenever possible.
*/
appendTimestamp: function( resource ) {
if ( !this.timestamp ||
resource.charAt( resource.length - 1 ) === '/' ||
( /[&?]t=/ ).test( resource )
) {
return resource;
}

var concatenateSign = resource.indexOf( '?' ) >= 0 ? '&' : '?';
return resource + concatenateSign + 't=' + this.timestamp;
},

/**
* Specify a function to execute when the DOM is fully loaded.
*
Expand Down
2 changes: 2 additions & 0 deletions core/dom/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ CKEDITOR.tools.extend( CKEDITOR.dom.document.prototype, {
* @param {String} cssFileUrl The CSS file URL.
*/
appendStyleSheet: function( cssFileUrl ) {
cssFileUrl = CKEDITOR.appendTimestamp( cssFileUrl );

if ( this.$.createStyleSheet )
this.$.createStyleSheet( cssFileUrl );
else {
Expand Down
6 changes: 4 additions & 2 deletions core/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,12 @@
for ( var i = 0; i < css.length; i++ ) {
if ( ( item = css[ i ] ) ) {
// Is CSS style text ?
if ( /@import|[{}]/.test( item ) )
if ( /@import|[{}]/.test( item ) ) {
retval.push( '<style>' + item + '</style>' );
else
} else {
item = CKEDITOR.appendTimestamp( item );
retval.push( '<link type="text/css" rel=stylesheet href="' + item + '">' );
}
}
}
return retval.join( '' );
Expand Down
61 changes: 61 additions & 0 deletions tests/core/ckeditor/appendtimestamp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* bender-tags: editor */

( function() {
'use strict';

bender.test( {
'test append timestamp returns the same resource path if there is no CKEDITOR.timestamp': performTimestampTest(
'',
'style.css',
'style.css',
'Resource path was modified without timestamp in CKEDITOR'
),

'test append timestamp returns resource path with timestamp if there is CKEDITOR.timestamp': performTimestampTest(
'cke4',
'style.css',
'style.css?t=cke4',
'Resource path was modified without timestamp in CKEDITOR'
),

'test append timestamp returns the same resource path if it is a directory path': performTimestampTest(
'cke4',
'style/',
'style/',
'Resource path to directory should not be changed'
),

'test append timestamp to resource path, with timestamp as single URL param, does not change it': performTimestampTest(
'cke4',
'style.css?t=qaz1',
'style.css?t=qaz1',
'Resource path with timestamp was affected with new timestamp'
),

'test append timestamp to resource path with chained timestamp does not change it': performTimestampTest(
'cke4',
'style.css?q=abc&t=qaz1',
'style.css?q=abc&t=qaz1',
'Resource path with chained timestamp was affected with new timestamp'
),

'test append timestamp to resource path with URL params adds timestamp as another param': performTimestampTest(
'cke4',
'style.css?q=abc',
'style.css?q=abc&t=cke4',
'Resource path with single param has not been affected by timestamp'
)
} );

function performTimestampTest( timestamp, resourcePath, expected, message ) {
return function() {
var originalTimestamp = CKEDITOR.timestamp;
CKEDITOR.timestamp = timestamp;

var result = CKEDITOR.appendTimestamp( resourcePath );

CKEDITOR.timestamp = originalTimestamp;
assert.areSame( expected, result, message );
};
}
} )();
157 changes: 157 additions & 0 deletions tests/core/ckeditor/geturl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/* bender-tags: editor */

( function() {
'use strict';

var FAKE_BASE_PATH = 'http://some.example:1030/subdir/ckeditor/',
testCases = [
{
url: 'just.js',
expected: FAKE_BASE_PATH + 'just.js',
timestamp: ''
},

{
url: 'just.js',
expected: FAKE_BASE_PATH + 'just.js?t=347',
timestamp: '347'
},

{
url: './test.css',
expected: FAKE_BASE_PATH + './test.css',
timestamp: ''
},

{
url: './test.css',
expected: FAKE_BASE_PATH + './test.css?t=tr4',
timestamp: 'tr4'
},

{
url: '../whatever.js',
expected: FAKE_BASE_PATH + '../whatever.js',
timestamp: ''
},

{
url: '../whatever.js',
expected: FAKE_BASE_PATH + '../whatever.js?t=qwerty',
timestamp: 'qwerty'
},

{
url: '/file',
expected: '/file',
timestamp: ''
},

{
url: '/file',
expected: '/file?t=cke4',
timestamp: 'cke4'
},

{
url: 'http://some.site:47/file.js',
expected: 'http://some.site:47/file.js',
timestamp: ''
},

{
url: 'http://some.site:47/file.js',
expected: 'http://some.site:47/file.js?t=cv3',
timestamp: 'cv3'
},

{
url: 'https://whatever/file',
expected: 'https://whatever/file',
timestamp: ''
},

{
url: 'https://whatever/file',
expected: 'https://whatever/file?t=1er',
timestamp: '1er'
},

{
url: '//cksource.com/file.css',
expected: '//cksource.com/file.css',
timestamp: ''
},

{
url: '//cksource.com/file.css',
expected: '//cksource.com/file.css?t=try6',
timestamp: 'try6'
},

{
url: 'file.t?something=here',
expected: FAKE_BASE_PATH + 'file.t?something=here&t=wer',
timestamp: 'wer'
},

{
url: '/file.t?something=here',
expected: '/file.t?something=here&t=wer',
timestamp: 'wer'
},

{
url: 'http://dot.example/file.t?something=here',
expected: 'http://dot.example/file.t?something=here&t=wer',
timestamp: 'wer'
},

{
url: 'https://dot.example/file.t?something=here',
expected: 'https://dot.example/file.t?something=here&t=wer',
timestamp: 'wer'
},

{
url: '//dot.example/file.t?something=here',
expected: '//dot.example/file.t?something=here&t=wer',
timestamp: 'wer'
}
],
tests = createGetUrlTests( testCases );

bender.test( tests );

function createGetUrlTests( testCases ) {
return CKEDITOR.tools.array.reduce( testCases, function( tests, testCase ) {
var test = {},
testName = 'test CKEDITOR.getUrl( \'' + testCase.url + '\' ) with timestamp \'' +
testCase.timestamp + '\'';

test[ testName ] = createTest( testCase );

return CKEDITOR.tools.object.merge( tests, test );
}, {} );

function createTest( options ) {
var url = options.url,
expected = options.expected,
timestamp = options.timestamp;

return function() {
var originalBasePath = CKEDITOR.basePath,
originalTimestamp = CKEDITOR.timestamp,
actualResult;

CKEDITOR.basePath = FAKE_BASE_PATH;
CKEDITOR.timestamp = timestamp;
actualResult = CKEDITOR.getUrl( url );
CKEDITOR.basePath = originalBasePath;
CKEDITOR.timestamp = originalTimestamp;

assert.areSame( expected, actualResult, 'Invalid URL generated from the ' + url );
};
}
}
} )();
13 changes: 13 additions & 0 deletions tests/core/ckeditor/manual/assetscachekey.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div id="editor">
<p>Lorem ipsum dolor sit amet</p>
</div>

<script>
( function() {
if ( bender.tools.env.mobile || !CKEDITOR.timestamp ) {
return bender.ignore();
}

CKEDITOR.replace( 'editor' );
} )();
</script>
10 changes: 10 additions & 0 deletions tests/core/ckeditor/manual/assetscachekey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@bender-tags: bug, 4.17.2, 4761
@bender-ui: collapsed
@bender-ckeditor-plugins: wysiwygarea, toolbar, undo, emoji, copyformatting, easyimage, tableselection

**Note**: This test requires CKEDITOR with set `CKEDITOR.timestamp` (e.g. built one).

1. Open developer tools and switch to "Network" tab.
2. Refresh the page.

**Expected** CKEditor 4's resources are loaded with the cache key (`?t=<some alphanum characters>` at the end of URL).
44 changes: 32 additions & 12 deletions tests/core/dom/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,41 @@ bender.test( appendDomObjectTests(
assert.areSame( document, doc.$ );
},

test_appendStyleSheet: function() {
var cssUrl = CKEDITOR.basePath + 'tests/_assets/sample.css';
// (#4761)
'test appendStyleSheet without timestamp': function() {
var originalTimestamp = CKEDITOR.timestamp,
cssUrl = CKEDITOR.basePath + 'tests/_assets/sample.css';

CKEDITOR.timestamp = '';
var doc = new CKEDITOR.dom.document( document );
doc.appendStyleSheet( cssUrl );

var links = document.getElementsByTagName( 'link' );
var succeed = false;
for ( var i = 0 ; i < links.length ; i++ ) {
if ( links[ i ].href == cssUrl ) {
succeed = true;
break;
}
}
doc.appendStyleSheet( cssUrl );// this makes absolute URL no matter what is passed

var links = document.getElementsByTagName( 'link' ),
succeed = CKEDITOR.tools.array.some( links, function( link ) {
return link.href === cssUrl;
} );

CKEDITOR.timestamp = originalTimestamp;
assert.isTrue( succeed, 'The link element was not found' );
},

// (#4761)
'test appendStyleSheet with timestamp': function() {
var originalTimestamp = CKEDITOR.timestamp,
fakeTimestamp = 'cke4',
cssUrl = CKEDITOR.basePath + 'tests/_assets/sample.css',
expectedCssUrl = cssUrl + '?t=' + fakeTimestamp;

CKEDITOR.timestamp = fakeTimestamp;
var doc = new CKEDITOR.dom.document( document );
doc.appendStyleSheet( cssUrl );// this makes absolute URL no matter what is passed

var links = document.getElementsByTagName( 'link' ),
succeed = CKEDITOR.tools.array.some( links, function( link ) {
return link.href === expectedCssUrl;
} );

CKEDITOR.timestamp = originalTimestamp;
assert.isTrue( succeed, 'The link element was not found' );
},

Expand Down
Loading

0 comments on commit f8caf0b

Please sign in to comment.