@@ -32,7 +32,7 @@ import {
3232import { tags } from "@lezer/highlight" ;
3333import interact from "@replit/codemirror-interact" ;
3434import { blockComponentWidget } from "./block-component-widget" ;
35- import { copy , markdownKeymap } from "./copy-widget" ;
35+ import { copy , markdownKeymap , pasteKeymap } from "./copy-widget" ;
3636import { images } from "./image-widget" ;
3737import "./style.css" ;
3838import { theme } from "./theme" ;
@@ -96,6 +96,7 @@ export function makeExtensions({
9696 } ,
9797 } ,
9898 ] ) ,
99+
99100 EditorView . updateListener . of ( ( v ) => {
100101 if ( ! v . docChanged ) return ;
101102 onUpdateContent ( v . state . doc . sliceString ( 0 ) ) ;
@@ -108,6 +109,7 @@ export function makeExtensions({
108109 const text = v . state . doc . sliceString ( 0 , cursorPosition ) ;
109110 const activeLine = text . split ( "\n" ) . slice ( - 1 ) [ 0 ] ;
110111 const startOfLinePosition = cursorPosition - activeLine . length ;
112+
111113 const isAutocompleting =
112114 activeLine . startsWith ( "/" ) && ! activeLine . includes ( "/>" ) ;
113115 if ( ! isAutocompleting ) {
@@ -124,6 +126,54 @@ export function makeExtensions({
124126 }
125127 } ) ,
126128
129+ EditorView . domEventHandlers ( {
130+ paste ( e , view ) {
131+ const value = e . clipboardData ?. items [ 0 ] ;
132+ const MAX_URL_SIZE = 5000000 ;
133+ // handle images pasted from the web
134+ if ( value && value . type === "text/html" ) {
135+ value . getAsString ( ( str ) => {
136+ const htmlImgRegex = / < i m g [ ^ > ] * s r c = " (?< src > [ ^ " ] * ) " [ ^ > ] * > / gim;
137+ const matches = [ ...str . matchAll ( htmlImgRegex ) ] ;
138+ const images = matches . map ( ( match ) => match . groups ?. src ) ;
139+ if ( images ) {
140+ view . dispatch ( {
141+ changes : {
142+ from : view . state . selection . main . from ,
143+ to : view . state . selection . main . to ,
144+ insert : images
145+ . filter ( ( image ) => image && image . length < MAX_URL_SIZE )
146+ . map ( ( image ) => `` )
147+ . join ( "\n" ) ,
148+ } ,
149+ } ) ;
150+ }
151+ } ) ;
152+ } else if (
153+ value &&
154+ [ "image/png" , "image/jpeg" ] . includes ( value . type || "" )
155+ ) {
156+ const file = value . getAsFile ( ) ;
157+ if ( file ) {
158+ const reader = new FileReader ( ) ;
159+ reader . onload = ( e ) => {
160+ const image = e . target ?. result as string ;
161+ if ( image && image . length < MAX_URL_SIZE ) {
162+ view . dispatch ( {
163+ changes : {
164+ from : view . state . selection . main . from ,
165+ to : view . state . selection . main . to ,
166+ insert : `` ,
167+ } ,
168+ } ) ;
169+ }
170+ } ;
171+ reader . readAsDataURL ( file ) ;
172+ }
173+ }
174+ } ,
175+ } ) ,
176+
127177 // lineNumbers(),
128178 highlightActiveLineGutter ( ) ,
129179 highlightSpecialChars ( ) ,
0 commit comments