99
1010import { Plugin } from "@ckeditor/ckeditor5-core" ;
1111import { Image , ImageUtils } from "@ckeditor/ckeditor5-image" ;
12- import type {
13- WoltlabMetacode ,
14- WoltlabMetacodeUpcast ,
15- } from "../../ckeditor5-woltlab-metacode/" ;
1612
1713export class WoltlabAttachment extends Plugin {
1814 static get pluginName ( ) {
@@ -34,14 +30,25 @@ export class WoltlabAttachment extends Plugin {
3430 const imageTypes = [ "imageBlock" , "imageInline" ] ;
3531 imageTypes . forEach ( ( imageType ) => {
3632 schema . extend ( imageType , {
37- allowAttributes : [ "attachmentId" , "data-width" ] ,
33+ allowAttributes : [ "attachmentId" ] ,
34+ } ) ;
35+
36+ conversion . attributeToAttribute ( {
37+ model : {
38+ key : "classList" ,
39+ values : [ "woltlabAttachment" ] ,
40+ } ,
41+ view : {
42+ woltlabAttachment : {
43+ name : imageType === "imageBlock" ? "figure" : "img" ,
44+ key : "class" ,
45+ value : "woltlabAttachment" ,
46+ } ,
47+ } ,
3848 } ) ;
3949 } ) ;
4050
41- const attributeMapping = new Map ( [
42- [ "attachmentId" , "data-attachment-id" ] ,
43- [ "data-width" , "data-width" ] ,
44- ] ) ;
51+ const attributeMapping = new Map ( [ [ "attachmentId" , "data-attachment-id" ] ] ) ;
4552 const imageUtils = this . editor . plugins . get ( "ImageUtils" ) ;
4653
4754 Array . from ( attributeMapping . entries ( ) ) . forEach ( ( [ model , view ] ) => {
@@ -87,153 +94,7 @@ export class WoltlabAttachment extends Plugin {
8794 ) ;
8895 } ) ;
8996 } ) ;
90-
91- this . #setupAttachUpcast( ) ;
92- }
93-
94- #setupAttachUpcast( ) : void {
95- const options = this . editor . config . get (
96- "woltlabAttachment" ,
97- ) as WoltlabAttachmentConfig ;
98-
99- const woltlabMetacode = this . editor . plugins . get (
100- "WoltlabMetacode" ,
101- ) as WoltlabMetacode ;
102- woltlabMetacode . on (
103- "upcast" ,
104- ( eventInfo , eventData : WoltlabMetacodeUpcast ) => {
105- if ( eventData . name !== "attach" ) {
106- return ;
107- }
108-
109- const attachmentId = parseInt ( eventData . attributes [ 0 ] . toString ( ) ) ;
110- if ( Number . isNaN ( attachmentId ) ) {
111- return ;
112- }
113-
114- if ( ! options . inlineImageIds . includes ( attachmentId ) ) {
115- return ;
116- }
117-
118- let floatBehavior = eventData . attributes [ 1 ]
119- ? eventData . attributes [ 1 ] . toString ( )
120- : "none" ;
121- if (
122- floatBehavior !== "left" &&
123- floatBehavior !== "right" &&
124- floatBehavior !== "center" &&
125- floatBehavior !== "none"
126- ) {
127- floatBehavior = "none" ;
128- }
129-
130- let isThumbnail = eventData . attributes [ 2 ] as unknown ;
131- let width = "auto" ;
132- if ( typeof isThumbnail !== "boolean" ) {
133- if (
134- typeof isThumbnail === "string" ||
135- typeof isThumbnail === "number"
136- ) {
137- if ( isThumbnail === "true" ) {
138- isThumbnail = true ;
139- } else if ( isThumbnail === "false" ) {
140- isThumbnail = false ;
141- } else {
142- isThumbnail = parseInt ( isThumbnail . toString ( ) ) ;
143- if ( Number . isNaN ( isThumbnail ) ) {
144- isThumbnail = false ;
145- } else {
146- if ( isThumbnail === 0 ) {
147- isThumbnail = false ;
148- } else {
149- width = `${ isThumbnail } px` ;
150- isThumbnail = false ;
151- }
152- }
153- }
154- } else {
155- isThumbnail = false ;
156- }
157- }
158-
159- if (
160- this . #upcastAttachment(
161- eventData ,
162- options . resolveAttachmentUrl ,
163- attachmentId ,
164- floatBehavior as FloatBehavior ,
165- isThumbnail as boolean ,
166- width ,
167- )
168- ) {
169- eventInfo . stop ( ) ;
170- }
171- } ,
172- ) ;
173- }
174-
175- #upcastAttachment(
176- eventData : WoltlabMetacodeUpcast ,
177- resolveAttachUrl : ResolveAttachmentUrl ,
178- attachmentId : number ,
179- floatBehavior : FloatBehavior ,
180- isThumbnail : boolean ,
181- width : string ,
182- ) : boolean {
183- const { conversionApi, data } = eventData ;
184- const { consumable, writer } = conversionApi ;
185- const { viewItem } = data ;
186-
187- let model = "imageInline" ;
188- let attributes : Record < string , unknown > = {
189- attachmentId,
190- src : resolveAttachUrl ( attachmentId , isThumbnail ) ,
191- "data-width" : width ,
192- width,
193- } ;
194-
195- if ( floatBehavior === "left" ) {
196- model = "imageBlock" ;
197- attributes . imageStyle = "sideLeft" ;
198- } else if ( floatBehavior === "right" ) {
199- model = "imageBlock" ;
200- attributes . imageStyle = "side" ;
201- } else if ( floatBehavior === "center" ) {
202- model = "imageBlock" ;
203- }
204-
205- const image = writer . createElement ( model ) ;
206- writer . setAttributes ( attributes , image ) ;
207-
208- conversionApi . convertChildren ( viewItem , image ) ;
209-
210- if ( ! conversionApi . safeInsert ( image , data . modelCursor ) ) {
211- return false ;
212- }
213-
214- consumable . consume ( viewItem , { name : true } ) ;
215- conversionApi . updateConversionResult ( image , data ) ;
216-
217- return true ;
21897 }
21998}
22099
221100export default WoltlabAttachment ;
222-
223- type FloatBehavior = "left" | "none" | "right" | "center" ;
224-
225- type ResolveAttachmentUrl = (
226- attachmentId : number ,
227- isThumbnail : boolean ,
228- ) => string ;
229-
230- type WoltlabAttachmentConfig = {
231- inlineImageIds : number [ ] ;
232- resolveAttachmentUrl : ResolveAttachmentUrl ;
233- } ;
234-
235- declare module "@ckeditor/ckeditor5-core" {
236- interface EditorConfig {
237- woltlabAttachment ?: WoltlabAttachmentConfig ;
238- }
239- }
0 commit comments