1
1
/*
2
- Trix 2.0.7
3
- Copyright © 2023 37signals, LLC
2
+ Trix 2.1.1
3
+ Copyright © 2024 37signals, LLC
4
4
*/
5
5
( function ( global , factory ) {
6
6
typeof exports === 'object' && typeof module !== 'undefined' ? module . exports = factory ( ) :
@@ -9,14 +9,15 @@ Copyright © 2023 37signals, LLC
9
9
} ) ( this , ( function ( ) { 'use strict' ;
10
10
11
11
var name = "trix" ;
12
- var version = "2.0.7 " ;
12
+ var version = "2.1.1 " ;
13
13
var description = "A rich text editor for everyday writing" ;
14
14
var main = "dist/trix.umd.min.js" ;
15
15
var module = "dist/trix.esm.min.js" ;
16
16
var style = "dist/trix.css" ;
17
17
var files = [
18
18
"dist/*.css" ,
19
19
"dist/*.js" ,
20
+ "dist/*.map" ,
20
21
"src/{inspector,trix}/*.js"
21
22
] ;
22
23
var repository = {
@@ -130,6 +131,7 @@ Copyright © 2023 37signals, LLC
130
131
code : {
131
132
tagName : "pre" ,
132
133
terminal : true ,
134
+ htmlAttributes : [ "language" ] ,
133
135
text : {
134
136
plaintext : true
135
137
}
1215
1217
no-useless-escape,
1216
1218
*/
1217
1219
const normalizeSpaces = string => string . replace ( new RegExp ( "" . concat ( ZERO_WIDTH_SPACE ) , "g" ) , "" ) . replace ( new RegExp ( "" . concat ( NON_BREAKING_SPACE ) , "g" ) , " " ) ;
1218
- const normalizeNewlines = string => string . replace ( / \r \n / g, "\n" ) ;
1220
+ const normalizeNewlines = string => string . replace ( / \r \n ? / g, "\n" ) ;
1219
1221
const breakableWhitespacePattern = new RegExp ( "[^\\S" . concat ( NON_BREAKING_SPACE , "]" ) ) ;
1220
1222
const squishBreakableWhitespace = string => string
1221
1223
// Replace all breakable whitespace characters with a space
@@ -2144,20 +2146,28 @@ $\
2144
2146
}
2145
2147
}
2146
2148
createContainerElement ( depth ) {
2147
- let attributes , className ;
2149
+ const attributes = { } ;
2150
+ let className ;
2148
2151
const attributeName = this . attributes [ depth ] ;
2149
2152
const {
2150
- tagName
2153
+ tagName,
2154
+ htmlAttributes = [ ]
2151
2155
} = getBlockConfig ( attributeName ) ;
2152
2156
if ( depth === 0 && this . block . isRTL ( ) ) {
2153
- attributes = {
2157
+ Object . assign ( attributes , {
2154
2158
dir : "rtl"
2155
- } ;
2159
+ } ) ;
2156
2160
}
2157
2161
if ( attributeName === "attachmentGallery" ) {
2158
2162
const size = this . block . getBlockBreakPosition ( ) ;
2159
2163
className = "" . concat ( css$1 . attachmentGallery , " " ) . concat ( css$1 . attachmentGallery , "--" ) . concat ( size ) ;
2160
2164
}
2165
+ Object . entries ( this . block . htmlAttributes ) . forEach ( _ref => {
2166
+ let [ name , value ] = _ref ;
2167
+ if ( htmlAttributes . includes ( name ) ) {
2168
+ attributes [ name ] = value ;
2169
+ }
2170
+ } ) ;
2161
2171
return makeElement ( {
2162
2172
tagName,
2163
2173
className,
@@ -5828,28 +5838,29 @@ $\
5828
5838
class Block extends TrixObject {
5829
5839
static fromJSON ( blockJSON ) {
5830
5840
const text = Text . fromJSON ( blockJSON . text ) ;
5831
- return new this ( text , blockJSON . attributes ) ;
5841
+ return new this ( text , blockJSON . attributes , blockJSON . htmlAttributes ) ;
5832
5842
}
5833
- constructor ( text , attributes ) {
5843
+ constructor ( text , attributes , htmlAttributes ) {
5834
5844
super ( ...arguments ) ;
5835
5845
this . text = applyBlockBreakToText ( text || new Text ( ) ) ;
5836
5846
this . attributes = attributes || [ ] ;
5847
+ this . htmlAttributes = htmlAttributes || { } ;
5837
5848
}
5838
5849
isEmpty ( ) {
5839
5850
return this . text . isBlockBreak ( ) ;
5840
5851
}
5841
5852
isEqualTo ( block ) {
5842
5853
if ( super . isEqualTo ( block ) ) return true ;
5843
- return this . text . isEqualTo ( block === null || block === void 0 ? void 0 : block . text ) && arraysAreEqual ( this . attributes , block === null || block === void 0 ? void 0 : block . attributes ) ;
5854
+ return this . text . isEqualTo ( block === null || block === void 0 ? void 0 : block . text ) && arraysAreEqual ( this . attributes , block === null || block === void 0 ? void 0 : block . attributes ) && objectsAreEqual ( this . htmlAttributes , block === null || block === void 0 ? void 0 : block . htmlAttributes ) ;
5844
5855
}
5845
5856
copyWithText ( text ) {
5846
- return new Block ( text , this . attributes ) ;
5857
+ return new Block ( text , this . attributes , this . htmlAttributes ) ;
5847
5858
}
5848
5859
copyWithoutText ( ) {
5849
5860
return this . copyWithText ( null ) ;
5850
5861
}
5851
5862
copyWithAttributes ( attributes ) {
5852
- return new Block ( this . text , attributes ) ;
5863
+ return new Block ( this . text , attributes , this . htmlAttributes ) ;
5853
5864
}
5854
5865
copyWithoutAttributes ( ) {
5855
5866
return this . copyWithAttributes ( null ) ;
@@ -5866,6 +5877,12 @@ $\
5866
5877
const attributes = this . attributes . concat ( expandAttribute ( attribute ) ) ;
5867
5878
return this . copyWithAttributes ( attributes ) ;
5868
5879
}
5880
+ addHTMLAttribute ( attribute , value ) {
5881
+ const htmlAttributes = Object . assign ( { } , this . htmlAttributes , {
5882
+ [ attribute ] : value
5883
+ } ) ;
5884
+ return new Block ( this . text , this . attributes , htmlAttributes ) ;
5885
+ }
5869
5886
removeAttribute ( attribute ) {
5870
5887
const {
5871
5888
listAttribute
5962
5979
toJSON ( ) {
5963
5980
return {
5964
5981
text : this . text ,
5965
- attributes : this . attributes
5982
+ attributes : this . attributes ,
5983
+ htmlAttributes : this . htmlAttributes
5966
5984
} ;
5967
5985
}
5968
5986
@@ -6325,6 +6343,11 @@ $\
6325
6343
const range = this . getRangeOfAttachment ( attachment ) ;
6326
6344
return this . removeAttributeAtRange ( attribute , range ) ;
6327
6345
}
6346
+ setHTMLAttributeAtPosition ( position , name , value ) {
6347
+ const block = this . getBlockAtPosition ( position ) ;
6348
+ const updatedBlock = block . addHTMLAttribute ( name , value ) ;
6349
+ return this . replaceBlock ( block , updatedBlock ) ;
6350
+ }
6328
6351
insertBlockBreakAtRange ( range ) {
6329
6352
let blocks ;
6330
6353
range = normalizeRange ( range ) ;
6793
6816
return attributes ;
6794
6817
} ;
6795
6818
6796
- const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height class" . split ( " " ) ;
6819
+ const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class" . split ( " " ) ;
6797
6820
const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:" . split ( " " ) ;
6798
- const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form" . split ( " " ) ;
6821
+ const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript " . split ( " " ) ;
6799
6822
class HTMLSanitizer extends BasicObject {
6800
6823
static sanitize ( html , options ) {
6801
6824
const sanitizer = new this ( html , options ) ;
@@ -6923,15 +6946,21 @@ $\
6923
6946
} ;
6924
6947
const blockForAttributes = function ( ) {
6925
6948
let attributes = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : { } ;
6949
+ let htmlAttributes = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : { } ;
6926
6950
const text = [ ] ;
6927
6951
return {
6928
6952
text,
6929
- attributes
6953
+ attributes,
6954
+ htmlAttributes
6930
6955
} ;
6931
6956
} ;
6932
6957
const parseTrixDataAttribute = ( element , name ) => {
6933
6958
try {
6934
- return JSON . parse ( element . getAttribute ( "data-trix-" . concat ( name ) ) ) ;
6959
+ const data = JSON . parse ( element . getAttribute ( "data-trix-" . concat ( name ) ) ) ;
6960
+ if ( data . contentType === "text/html" && data . content ) {
6961
+ data . content = HTMLSanitizer . sanitize ( data . content ) . getHTML ( ) ;
6962
+ }
6963
+ return data ;
6935
6964
} catch ( error ) {
6936
6965
return { } ;
6937
6966
}
7027
7056
} else if ( element === this . containerElement || this . isBlockElement ( element ) ) {
7028
7057
var _this$currentBlock ;
7029
7058
const attributes = this . getBlockAttributes ( element ) ;
7059
+ const htmlAttributes = this . getBlockHTMLAttributes ( element ) ;
7030
7060
if ( ! arraysAreEqual ( attributes , ( _this$currentBlock = this . currentBlock ) === null || _this$currentBlock === void 0 ? void 0 : _this$currentBlock . attributes ) ) {
7031
- this . currentBlock = this . appendBlockForAttributesWithElement ( attributes , element ) ;
7061
+ this . currentBlock = this . appendBlockForAttributesWithElement ( attributes , element , htmlAttributes ) ;
7032
7062
this . currentBlockElement = element ;
7033
7063
}
7034
7064
}
@@ -7039,9 +7069,10 @@ $\
7039
7069
if ( elementIsBlockElement && ! this . isBlockElement ( element . firstChild ) ) {
7040
7070
if ( ! this . isInsignificantTextNode ( element . firstChild ) || ! this . isBlockElement ( element . firstElementChild ) ) {
7041
7071
const attributes = this . getBlockAttributes ( element ) ;
7072
+ const htmlAttributes = this . getBlockHTMLAttributes ( element ) ;
7042
7073
if ( element . firstChild ) {
7043
7074
if ( ! ( currentBlockContainsElement && arraysAreEqual ( attributes , this . currentBlock . attributes ) ) ) {
7044
- this . currentBlock = this . appendBlockForAttributesWithElement ( attributes , element ) ;
7075
+ this . currentBlock = this . appendBlockForAttributesWithElement ( attributes , element , htmlAttributes ) ;
7045
7076
this . currentBlockElement = element ;
7046
7077
} else {
7047
7078
return this . appendStringWithAttributes ( "\n" ) ;
7129
7160
// Document construction
7130
7161
7131
7162
appendBlockForAttributesWithElement ( attributes , element ) {
7163
+ let htmlAttributes = arguments . length > 2 && arguments [ 2 ] !== undefined ? arguments [ 2 ] : { } ;
7132
7164
this . blockElements . push ( element ) ;
7133
- const block = blockForAttributes ( attributes ) ;
7165
+ const block = blockForAttributes ( attributes , htmlAttributes ) ;
7134
7166
this . blocks . push ( block ) ;
7135
7167
return block ;
7136
7168
}
@@ -7235,6 +7267,17 @@ $\
7235
7267
}
7236
7268
return attributes$1 . reverse ( ) ;
7237
7269
}
7270
+ getBlockHTMLAttributes ( element ) {
7271
+ const attributes$1 = { } ;
7272
+ const blockConfig = Object . values ( attributes ) . find ( settings => settings . tagName === tagName ( element ) ) ;
7273
+ const allowedAttributes = ( blockConfig === null || blockConfig === void 0 ? void 0 : blockConfig . htmlAttributes ) || [ ] ;
7274
+ allowedAttributes . forEach ( attribute => {
7275
+ if ( element . hasAttribute ( attribute ) ) {
7276
+ attributes$1 [ attribute ] = element . getAttribute ( attribute ) ;
7277
+ }
7278
+ } ) ;
7279
+ return attributes$1 ;
7280
+ }
7238
7281
findBlockElementAncestors ( element ) {
7239
7282
const ancestors = [ ] ;
7240
7283
while ( element && element !== this . containerElement ) {
@@ -7830,6 +7873,15 @@ $\
7830
7873
return this . notifyDelegateOfCurrentAttributesChange ( ) ;
7831
7874
}
7832
7875
}
7876
+ setHTMLAtributeAtPosition ( position , attributeName , value ) {
7877
+ var _getBlockConfig ;
7878
+ const block = this . document . getBlockAtPosition ( position ) ;
7879
+ const allowedHTMLAttributes = ( _getBlockConfig = getBlockConfig ( block . getLastAttribute ( ) ) ) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig . htmlAttributes ;
7880
+ if ( block && allowedHTMLAttributes !== null && allowedHTMLAttributes !== void 0 && allowedHTMLAttributes . includes ( attributeName ) ) {
7881
+ const newDocument = this . document . setHTMLAttributeAtPosition ( position , attributeName , value ) ;
7882
+ this . setDocument ( newDocument ) ;
7883
+ }
7884
+ }
7833
7885
setTextAttribute ( attributeName , value ) {
7834
7886
const selectedRange = this . getSelectedRange ( ) ;
7835
7887
if ( ! selectedRange ) return ;
@@ -7877,10 +7929,10 @@ $\
7877
7929
return ( ( _this$getBlock = this . getBlock ( ) ) === null || _this$getBlock === void 0 ? void 0 : _this$getBlock . getNestingLevel ( ) ) > 0 ;
7878
7930
}
7879
7931
canIncreaseNestingLevel ( ) {
7880
- var _getBlockConfig ;
7932
+ var _getBlockConfig2 ;
7881
7933
const block = this . getBlock ( ) ;
7882
7934
if ( ! block ) return ;
7883
- if ( ( _getBlockConfig = getBlockConfig ( block . getLastNestableAttribute ( ) ) ) !== null && _getBlockConfig !== void 0 && _getBlockConfig . listAttribute ) {
7935
+ if ( ( _getBlockConfig2 = getBlockConfig ( block . getLastNestableAttribute ( ) ) ) !== null && _getBlockConfig2 !== void 0 && _getBlockConfig2 . listAttribute ) {
7884
7936
const previousBlock = this . getPreviousBlock ( ) ;
7885
7937
if ( previousBlock ) {
7886
7938
return arrayStartsWith ( previousBlock . getListItemAttributes ( ) , block . getListItemAttributes ( ) ) ;
@@ -8521,6 +8573,11 @@ $\
8521
8573
return this . composition . removeCurrentAttribute ( name ) ;
8522
8574
}
8523
8575
8576
+ // HTML attributes
8577
+ setHTMLAtributeAtPosition ( position , name , value ) {
8578
+ this . composition . setHTMLAtributeAtPosition ( position , name , value ) ;
8579
+ }
8580
+
8524
8581
// Nesting level
8525
8582
8526
8583
canDecreaseNestingLevel ( ) {
@@ -10941,8 +10998,12 @@ $\
10941
10998
} ) ;
10942
10999
} ,
10943
11000
insertReplacementText ( ) {
10944
- return this . insertString ( this . event . dataTransfer . getData ( "text/plain" ) , {
10945
- updatePosition : false
11001
+ const replacement = this . event . dataTransfer . getData ( "text/plain" ) ;
11002
+ const domRange = this . event . getTargetRanges ( ) [ 0 ] ;
11003
+ this . withTargetDOMRange ( domRange , ( ) => {
11004
+ this . insertString ( replacement , {
11005
+ updatePosition : false
11006
+ } ) ;
10946
11007
} ) ;
10947
11008
} ,
10948
11009
insertText ( ) {
@@ -11064,7 +11125,7 @@ $\
11064
11125
return this . toggleDialog ( actionName ) ;
11065
11126
} else {
11066
11127
var _this$delegate2 ;
11067
- return ( _this$delegate2 = this . delegate ) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2 . toolbarDidInvokeAction ( actionName ) ;
11128
+ return ( _this$delegate2 = this . delegate ) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2 . toolbarDidInvokeAction ( actionName , element ) ;
11068
11129
}
11069
11130
}
11070
11131
didClickAttributeButton ( event , element ) {
@@ -11509,8 +11570,8 @@ $\
11509
11570
} ) ;
11510
11571
}
11511
11572
}
11512
- toolbarDidInvokeAction ( actionName ) {
11513
- return this . invokeAction ( actionName ) ;
11573
+ toolbarDidInvokeAction ( actionName , invokingElement ) {
11574
+ return this . invokeAction ( actionName , invokingElement ) ;
11514
11575
}
11515
11576
toolbarDidToggleAttribute ( attributeName ) {
11516
11577
this . recordFormattingUndoEntry ( attributeName ) ;
@@ -11579,10 +11640,11 @@ $\
11579
11640
return ! ! ( ( _this$actions$actionN = this . actions [ actionName ] ) !== null && _this$actions$actionN !== void 0 && ( _this$actions$actionN = _this$actions$actionN . test ) !== null && _this$actions$actionN !== void 0 && _this$actions$actionN . call ( this ) ) ;
11580
11641
}
11581
11642
}
11582
- invokeAction ( actionName ) {
11643
+ invokeAction ( actionName , invokingElement ) {
11583
11644
if ( this . actionIsExternal ( actionName ) ) {
11584
11645
return this . notifyEditorElement ( "action-invoke" , {
11585
- actionName
11646
+ actionName,
11647
+ invokingElement
11586
11648
} ) ;
11587
11649
} else {
11588
11650
var _this$actions$actionN2 ;
0 commit comments