diff --git a/packages/ckeditor5-engine/src/view/styles/utils.js b/packages/ckeditor5-engine/src/view/styles/utils.js
index eb2a123661c..2dc5d4ec531 100644
--- a/packages/ckeditor5-engine/src/view/styles/utils.js
+++ b/packages/ckeditor5-engine/src/view/styles/utils.js
@@ -86,7 +86,7 @@ export function isLineStyle( string ) {
return lineStyleValues.includes( string );
}
-const lengthRegExp = /^([+-]?[0-9]*[.]?[0-9]+(px|cm|mm|in|pc|pt|ch|em|ex|rem|vh|vw|vmin|vmax)|0)$/;
+const lengthRegExp = /^([+-]?[0-9]*([.][0-9]+)?(px|cm|mm|in|pc|pt|ch|em|ex|rem|vh|vw|vmin|vmax)|0)$/;
/**
* Checks if string contains [length](https://developer.mozilla.org/en-US/docs/Web/CSS/length) CSS value.
@@ -98,7 +98,7 @@ export function isLength( string ) {
return lengthRegExp.test( string );
}
-const PERCENTAGE_VALUE_REGEXP = /^[+-]?[0-9]*[.]?[0-9]+%$/;
+const PERCENTAGE_VALUE_REGEXP = /^[+-]?[0-9]*([.][0-9]+)?%$/;
/**
* Checks if string contains [percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/percentage) CSS value.
diff --git a/packages/ckeditor5-engine/tests/view/styles/utils.js b/packages/ckeditor5-engine/tests/view/styles/utils.js
index 7fd7ec579ac..66c229507a7 100644
--- a/packages/ckeditor5-engine/tests/view/styles/utils.js
+++ b/packages/ckeditor5-engine/tests/view/styles/utils.js
@@ -181,6 +181,11 @@ describe( 'Styles utils', () => {
isLength
);
} );
+
+ // s/ckeditor5/3
+ it( 'should handle invalid values with repeated characters', () => {
+ expect( isLength( '9'.repeat( 1000000 ) ) ).to.be.false;
+ } );
} );
describe( 'isPercentage()', () => {
@@ -191,6 +196,11 @@ describe( 'Styles utils', () => {
it( 'returns false for not a percentage values', () => {
testValues( [ '0', '1px', '1000px', '1.1px', '345.457px', '.457px' ], value => !isPercentage( value ) );
} );
+
+ // s/ckeditor5/3
+ it( 'should handle invalid values with repeated characters', () => {
+ expect( isPercentage( '9'.repeat( 1000000 ) ) ).to.be.false;
+ } );
} );
describe( 'getBoxSidesShorthandValue()', () => {
diff --git a/packages/ckeditor5-font/src/fontsize/fontsizeediting.js b/packages/ckeditor5-font/src/fontsize/fontsizeediting.js
index fab82d822dc..7ca6da26e6e 100644
--- a/packages/ckeditor5-font/src/fontsize/fontsizeediting.js
+++ b/packages/ckeditor5-font/src/fontsize/fontsizeediting.js
@@ -109,7 +109,7 @@ export default class FontSizeEditing extends Plugin {
const editor = this.editor;
// If `fontSize.supportAllValues=true`, we do not allow to use named presets in the plugin's configuration.
- const presets = definition.model.values.filter( value => !String( value ).match( /[\d.]+[\w%]+/ ) );
+ const presets = definition.model.values.filter( value => !String( value ).match( /^[\d.]+[a-zA-Z%]+$/ ) );
if ( presets.length ) {
/**
diff --git a/packages/ckeditor5-image/src/autoimage.js b/packages/ckeditor5-image/src/autoimage.js
index 51b48d300b6..b5c16894b68 100644
--- a/packages/ckeditor5-image/src/autoimage.js
+++ b/packages/ckeditor5-image/src/autoimage.js
@@ -16,8 +16,8 @@ import { global } from 'ckeditor5/src/utils';
import { insertImage } from './image/utils';
// Implements the pattern: http(s)://(www.)example.com/path/to/resource.ext?query=params&maybe=too.
-const IMAGE_URL_REGEXP = new RegExp( String( /^(http(s)?:\/\/)?[\w-]+(\.[\w-]+)+[\w._~:/?#[\]@!$&'()*+,;=%-]+/.source +
- /\.(jpg|jpeg|png|gif|ico|webp|JPG|JPEG|PNG|GIF|ICO|WEBP)\??[\w._~:/#[\]@!$&'()*+,;=%-]*$/.source ) );
+const IMAGE_URL_REGEXP = new RegExp( String( /^(http(s)?:\/\/)?[\w-]+\.[\w._~:/?#[\]@!$&'()*+,;=%-]+/.source +
+ /\.(jpg|jpeg|png|gif|ico|webp|JPG|JPEG|PNG|GIF|ICO|WEBP)(\?[\w._~:/#[\]@!$&'()*+,;=%-]*)?$/.source ) );
/**
* The auto-image plugin. It recognizes image links in the pasted content and embeds
diff --git a/packages/ckeditor5-image/tests/autoimage.js b/packages/ckeditor5-image/tests/autoimage.js
index 01cbe12ebe2..3ebabf53a14 100644
--- a/packages/ckeditor5-image/tests/autoimage.js
+++ b/packages/ckeditor5-image/tests/autoimage.js
@@ -153,6 +153,20 @@ describe( 'AutoImage - integration', () => {
);
} );
}
+
+ // s/ckeditor5/3
+ it( 'should handle invalid URL with repeated characters', () => {
+ const invalidURL = 'a.' + 'a'.repeat( 1000000 );
+
+ setData( editor.model, '[]' );
+ pasteHtml( editor, invalidURL );
+
+ clock.tick( 100 );
+
+ expect( getData( editor.model ) ).to.equal(
+ `${ invalidURL }[]`
+ );
+ } );
} );
it( 'works for URL that was pasted as a link', () => {
diff --git a/packages/ckeditor5-list/src/converters.js b/packages/ckeditor5-list/src/converters.js
index 4722f5553fa..404e193faf5 100644
--- a/packages/ckeditor5-list/src/converters.js
+++ b/packages/ckeditor5-list/src/converters.js
@@ -445,12 +445,12 @@ export function cleanListItem( evt, data, conversionApi ) {
if ( child.is( '$text' ) ) {
// If this is the first node and it's a text node, left-trim it.
if ( firstNode ) {
- child._data = child.data.replace( /^\s+/, '' );
+ child._data = child.data.trimStart();
}
// If this is the last text node before
or , right-trim it.
if ( !child.nextSibling || isList( child.nextSibling ) ) {
- child._data = child.data.replace( /\s+$/, '' );
+ child._data = child.data.trimEnd();
}
} else if ( isList( child ) ) {
// If this is a or , do not process it, just mark that we already visited list element.
diff --git a/packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js b/packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js
index 7d7bf403f76..6df18b9b71a 100644
--- a/packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js
+++ b/packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js
@@ -95,7 +95,7 @@ const regex = new RegExp(
/\b(?:(?:https?|ftp):\/\/|www\.)/.source +
// Domain name.
- /(?![-_])(?:[-\w\u00a1-\uffff]{0,63}[^-_]\.)+(?:[a-z\u00a1-\uffff]{2,})/.source +
+ /(?![-_])(?:[-_a-z0-9\u00a1-\uffff]{1,63}[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,})/.source +
// The rest.
/(?:[^\s<>]*)/.source,
diff --git a/packages/ckeditor5-media-embed/src/automediaembed.js b/packages/ckeditor5-media-embed/src/automediaembed.js
index 536b759879c..d8e330db3f0 100644
--- a/packages/ckeditor5-media-embed/src/automediaembed.js
+++ b/packages/ckeditor5-media-embed/src/automediaembed.js
@@ -16,7 +16,7 @@ import { global } from 'ckeditor5/src/utils';
import MediaEmbedEditing from './mediaembedediting';
import { insertMedia } from './utils';
-const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=%]+$/;
+const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w.-][\w\-._~:/?#[\]@!$&'()*+,;=%]+$/;
/**
* The auto-media embed plugin. It recognizes media links in the pasted content and embeds
diff --git a/packages/ckeditor5-media-embed/tests/automediaembed.js b/packages/ckeditor5-media-embed/tests/automediaembed.js
index 4345949a9f9..aaeed2dda75 100644
--- a/packages/ckeditor5-media-embed/tests/automediaembed.js
+++ b/packages/ckeditor5-media-embed/tests/automediaembed.js
@@ -327,6 +327,20 @@ describe( 'AutoMediaEmbed - integration', () => {
);
} );
+ // s/ckeditor5/3
+ it( 'should handle invalid URL with repeated characters', () => {
+ const invalidURL = 'a.' + 'a'.repeat( 1000000 ) + '^';
+
+ setData( editor.model, '[]' );
+ pasteHtml( editor, invalidURL );
+
+ clock.tick( 100 );
+
+ expect( getData( editor.model ) ).to.equal(
+ `${ invalidURL }[]`
+ );
+ } );
+
// #47
it( 'does not transform a valid URL into a media if the element cannot be placed in the current position', () => {
setData( editor.model, 'Foo.[]' );
diff --git a/packages/ckeditor5-paste-from-office/src/filters/list.js b/packages/ckeditor5-paste-from-office/src/filters/list.js
index 62293fd2242..f52bd034370 100644
--- a/packages/ckeditor5-paste-from-office/src/filters/list.js
+++ b/packages/ckeditor5-paste-from-office/src/filters/list.js
@@ -160,7 +160,7 @@ function findAllItemLikeElements( documentFragment, writer ) {
// If it cannot be adjusted, the `null` value is returned.
function detectListStyle( listLikeItem, stylesString ) {
const listStyleRegexp = new RegExp( `@list l${ listLikeItem.id }:level${ listLikeItem.indent }\\s*({[^}]*)`, 'gi' );
- const listStyleTypeRegex = /mso-level-number-format:([^;]*);/gi;
+ const listStyleTypeRegex = /mso-level-number-format:((?!mso-level-number-format:)[^;]*);/gi;
const listStyleMatch = listStyleRegexp.exec( stylesString );
diff --git a/packages/ckeditor5-paste-from-office/src/filters/space.js b/packages/ckeditor5-paste-from-office/src/filters/space.js
index bdebe4ea604..87fcb28b074 100644
--- a/packages/ckeditor5-paste-from-office/src/filters/space.js
+++ b/packages/ckeditor5-paste-from-office/src/filters/space.js
@@ -20,14 +20,14 @@ export function normalizeSpacing( htmlString ) {
// Run normalizeSafariSpaceSpans() two times to cover nested spans.
return normalizeSafariSpaceSpans( normalizeSafariSpaceSpans( htmlString ) )
// Remove all \r\n from "spacerun spans" so the last replace line doesn't strip all whitespaces.
- .replace( /([\s]*?)[\r\n]+(\s*<\/span>)/g, '$1$2' )
+ .replace( /([^\S\r\n]*?)[\r\n]+([^\S\r\n]*<\/span>)/g, '$1$2' )
.replace( /<\/span>/g, '' )
.replace( / <\//g, '\u00A0' )
.replace( / <\/o:p>/g, '\u00A0' )
// Remove block filler from empty paragraph. Safari uses \u00A0 instead of .
.replace( /( |\u00A0)<\/o:p>/g, '' )
// Remove all whitespaces when they contain any \r or \n.
- .replace( />(\s*[\r\n]\s*)<' );
+ .replace( />([^\S\r\n]*[\r\n]\s*)<' );
}
/**
diff --git a/packages/ckeditor5-paste-from-office/tests/filters/list.js b/packages/ckeditor5-paste-from-office/tests/filters/list.js
index 3d3815cb38d..757e100f603 100644
--- a/packages/ckeditor5-paste-from-office/tests/filters/list.js
+++ b/packages/ckeditor5-paste-from-office/tests/filters/list.js
@@ -271,6 +271,21 @@ describe( 'PasteFromOffice - filters', () => {
);
} );
+ // s/ckeditor5/3
+ it( 'should handle invalid style with repeated characters', () => {
+ const styles = '@list l0:level1\n' +
+ '{' + 'mso-level-number-format:'.repeat( 100000 ) + '}';
+
+ const html = `Foo
`;
+ const view = htmlDataProcessor.toView( html );
+
+ transformListItemLikeElementsIntoLists( view, styles );
+
+ expect( stringify( view ) ).to.equal(
+ `- Foo
`
+ );
+ } );
+
it( 'converts "arabic-leading-zero" style to proper CSS attribute', () => {
const styles = '@list l0:level1\n' +
'{mso-level-number-format:arabic-leading-zero;}';
diff --git a/packages/ckeditor5-widget/src/widgetresize/resizerstate.js b/packages/ckeditor5-widget/src/widgetresize/resizerstate.js
index 3b47c44891c..b65ce864e9c 100644
--- a/packages/ckeditor5-widget/src/widgetresize/resizerstate.js
+++ b/packages/ckeditor5-widget/src/widgetresize/resizerstate.js
@@ -126,7 +126,7 @@ export default class ResizeState {
const widthStyle = domResizeHost.style.width;
- if ( widthStyle && widthStyle.match( /^\d+\.?\d*%$/ ) ) {
+ if ( widthStyle && widthStyle.match( /^\d+(\.\d*)?%$/ ) ) {
this.originalWidthPercents = parseFloat( widthStyle );
} else {
this.originalWidthPercents = calculateHostPercentageWidth( domResizeHost, clientRect );