@@ -5,7 +5,14 @@ import jQuery from "jquery";
55import html2canvas from "html2canvas" ;
66import { Canvg } from "canvg" ;
77import "leaflet" ;
8- import "codemirror/lib/codemirror.js" ;
8+ import { EditorView , basicSetup } from "codemirror" ;
9+ import { EditorState } from "@codemirror/state" ;
10+ import { StreamLanguage } from "@codemirror/language" ;
11+ import { javascript } from "@codemirror/lang-javascript" ;
12+ import { xml } from "@codemirror/lang-xml" ;
13+ import { css } from "@codemirror/lang-css" ;
14+ import { clike } from "@codemirror/legacy-modes/mode/clike" ;
15+
916import tokml from "tokml" ;
1017import togpx from "togpx" ;
1118import configs from "./configs" ;
@@ -24,8 +31,6 @@ import {Base64, htmlentities, lzw_encode, lzw_decode} from "./misc";
2431import sync from "./sync-with-osm" ;
2532import shortcuts from "./shortcuts" ;
2633
27- declare const CodeMirror ;
28-
2934// Handler to allow copying in various MIME formats
3035// @see https://developer.mozilla.org/en-US/docs/Web/Events/copy
3136// @see https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
@@ -141,6 +146,24 @@ function showDialog(title, content, buttons) {
141146 element . appendTo ( "body" ) ;
142147}
143148
149+ export const overpassQL = clike ( {
150+ name : "overpassQL" ,
151+ keywords : ( function ( str ) {
152+ const r = { } ;
153+ const a = str . split ( " " ) ;
154+ for ( const ai of a ) r [ ai ] = true ;
155+ return r ;
156+ } ) (
157+ "out json xml custom popup timeout maxsize bbox" + // initial declarations
158+ " date diff adiff" + //attic declarations
159+ " foreach" + // block statements
160+ " relation rel way node is_in area around user uid newer changed poly pivot nwr nw nr wr derived" + // queries
161+ " out meta body skel tags ids count qt asc" + // actions
162+ " center bb geom" // geometry types
163+ //+"r w n br bw" // recursors
164+ )
165+ } ) ;
166+
144167class IDE {
145168 // == private members ==
146169 private attribControl = null ;
@@ -327,122 +350,113 @@ class IDE {
327350 $ ( "#editor textarea" ) [ 0 ] . value = settings . code [ "overpass" ] ;
328351 if ( settings . use_rich_editor ) {
329352 let pending = 0 ;
330- CodeMirror . defineMIME ( "text/x-overpassQL" , {
331- name : "clike" ,
332- keywords : ( function ( str ) {
333- const r = { } ;
334- const a = str . split ( " " ) ;
335- for ( const ai of a ) r [ ai ] = true ;
336- return r ;
337- } ) (
338- "out json xml custom popup timeout maxsize bbox" + // initial declarations
339- " date diff adiff" + //attic declarations
340- " foreach" + // block statements
341- " relation rel way node is_in area around user uid newer changed poly pivot nwr nw nr wr derived" + // queries
342- " out meta body skel tags ids count qt asc" + // actions
343- " center bb geom" // geometry types
344- //+"r w n br bw" // recursors
345- )
346- } ) ;
347- CodeMirror . defineMIME ( "text/x-overpassXML" , "xml" ) ;
348- CodeMirror . defineMode ( "xml+mustache" , ( config ) =>
349- CodeMirror . multiplexingMode (
350- CodeMirror . multiplexingMode ( CodeMirror . getMode ( config , "xml" ) , {
351- open : "{{" ,
352- close : "}}" ,
353- mode : CodeMirror . getMode ( config , "text/plain" ) ,
354- delimStyle : "mustache"
355- } ) ,
356- {
357- open : "{{style:" ,
358- close : "}}" ,
359- mode : CodeMirror . getMode ( config , "text/css" ) ,
360- delimStyle : "mustache"
361- }
362- )
363- ) ;
364- CodeMirror . defineMode ( "ql+mustache" , ( config ) =>
365- CodeMirror . multiplexingMode (
366- CodeMirror . multiplexingMode (
367- CodeMirror . getMode ( config , "text/x-overpassQL" ) ,
368- {
369- open : "{{" ,
370- close : "}}" ,
371- mode : CodeMirror . getMode ( config , "text/plain" ) ,
372- delimStyle : "mustache"
373- }
374- ) ,
375- {
376- open : "{{style:" ,
377- close : "}}" ,
378- mode : CodeMirror . getMode ( config , "text/css" ) ,
379- delimStyle : "mustache"
380- }
381- )
382- ) ;
383- ide . codeEditor = CodeMirror . fromTextArea ( $ ( "#editor textarea" ) [ 0 ] , {
384- //value: settings.code["overpass"],
385- lineNumbers : true ,
386- lineWrapping : true ,
387- mode : "text/plain" ,
388- onChange ( e ) {
389- clearTimeout ( pending ) ;
390- pending = setTimeout ( ( ) => {
391- // update syntax highlighting mode
392- if ( ide . getQueryLang ( ) == "xml" ) {
393- if ( e . getOption ( "mode" ) != "xml+mustache" ) {
394- e . closeTagEnabled = true ;
395- e . setOption ( "matchBrackets" , false ) ;
396- e . setOption ( "mode" , "xml+mustache" ) ;
397- }
398- } else {
399- if ( e . getOption ( "mode" ) != "ql+mustache" ) {
400- e . closeTagEnabled = false ;
401- e . setOption ( "matchBrackets" , true ) ;
402- e . setOption ( "mode" , "ql+mustache" ) ;
403- }
404- }
405- // check for inactive ui elements
406- const bbox_filter = $ ( ".leaflet-control-buttons-bboxfilter" ) ;
407- if ( ide . getRawQuery ( ) . match ( / \{ \{ b b o x \} \} / ) ) {
408- if ( bbox_filter . hasClass ( "disabled" ) ) {
409- bbox_filter . removeClass ( "disabled" ) ;
410- bbox_filter . attr ( "data-t" , "[title]map_controlls.select_bbox" ) ;
411- i18n . translate_ui ( bbox_filter [ 0 ] ) ;
412- }
413- } else {
414- if ( ! bbox_filter . hasClass ( "disabled" ) ) {
415- bbox_filter . addClass ( "disabled" ) ;
416- bbox_filter . attr (
417- "data-t" ,
418- "[title]map_controlls.select_bbox_disabled"
419- ) ;
420- i18n . translate_ui ( bbox_filter [ 0 ] ) ;
421- }
422- }
423- } , 500 ) ;
424- settings . code [ "overpass" ] = e . getValue ( ) ;
425- settings . save ( ) ;
426- } ,
427- closeTagEnabled : true ,
428- closeTagIndent : [
429- "osm-script" ,
430- "query" ,
431- "union" ,
432- "foreach" ,
433- "difference"
434- ] ,
435- extraKeys : {
436- "'>'" ( cm ) {
437- cm . closeTag ( cm , ">" ) ;
438- } ,
439- "'/'" ( cm ) {
440- cm . closeTag ( cm , "/" ) ;
441- }
442- }
353+ // CodeMirror.defineMIME("text/x-overpassXML", "xml");
354+ // CodeMirror.defineMode("xml+mustache", (config) =>
355+ // CodeMirror.multiplexingMode(
356+ // CodeMirror.multiplexingMode(CodeMirror.getMode(config, "xml"), {
357+ // open: "{{",
358+ // close: " }}",
359+ // mode: CodeMirror.getMode(config, "text/plain"),
360+ // delimStyle: "mustache"
361+ // }),
362+ // {
363+ // open: "{{style:",
364+ // close: " }}",
365+ // mode: CodeMirror.getMode(config, "text/css"),
366+ // delimStyle: "mustache"
367+ // }
368+ // )
369+ // );
370+ // CodeMirror.defineMode("ql+mustache", (config) =>
371+ // CodeMirror.multiplexingMode(
372+ // CodeMirror.multiplexingMode(
373+ // CodeMirror.getMode(config, "text/x-overpassQL"),
374+ // {
375+ // open: "{{",
376+ // close: " }}",
377+ // mode: CodeMirror.getMode(config, "text/plain"),
378+ // delimStyle: "mustache"
379+ // }
380+ // ),
381+ // {
382+ // open: "{{style:",
383+ // close: " }}",
384+ // mode: CodeMirror.getMode(config, "text/css"),
385+ // delimStyle: "mustache"
386+ // }
387+ // )
388+ // );
389+ const textarea = $ ( "#editor textarea" ) [ 0 ] as HTMLInputElement ;
390+ const view = new EditorView ( {
391+ doc : settings . code [ "overpass" ] ,
392+ extensions : [ basicSetup , StreamLanguage . define ( overpassQL ) ]
393+ // onChange(e) {
394+ // clearTimeout(pending);
395+ // pending = setTimeout(() => {
396+ // // update syntax highlighting mode
397+ // if (ide.getQueryLang() == "xml") {
398+ // if (e.getOption("mode") != "xml+mustache") {
399+ // e.closeTagEnabled = true;
400+ // e.setOption("matchBrackets", false);
401+ // e.setOption("mode", "xml+mustache");
402+ // }
403+ // } else {
404+ // if (e.getOption("mode") != "ql+mustache") {
405+ // e.closeTagEnabled = false;
406+ // e.setOption("matchBrackets", true);
407+ // e.setOption("mode", "ql+mustache");
408+ // }
409+ // }
410+ // // check for inactive ui elements
411+ // const bbox_filter = $(".leaflet-control-buttons-bboxfilter");
412+ // if (ide.getRawQuery().match(/\{\{bbox\}\}/)) {
413+ // if (bbox_filter.hasClass("disabled")) {
414+ // bbox_filter.removeClass("disabled");
415+ // bbox_filter.attr("data-t", "[title]map_controlls.select_bbox");
416+ // i18n.translate_ui(bbox_filter[0]);
417+ // }
418+ // } else {
419+ // if (!bbox_filter.hasClass("disabled")) {
420+ // bbox_filter.addClass("disabled");
421+ // bbox_filter.attr(
422+ // "data-t",
423+ // "[title]map_controlls.select_bbox_disabled"
424+ // );
425+ // i18n.translate_ui(bbox_filter[0]);
426+ // }
427+ // }
428+ // }, 500);
429+ // settings.code["overpass"] = e.getValue();
430+ // settings.save();
431+ // },
432+ // closeTagEnabled: true,
433+ // closeTagIndent: [
434+ // "osm-script",
435+ // "query",
436+ // "union",
437+ // "foreach",
438+ // "difference"
439+ // ],
440+ // extraKeys: {
441+ // "'>'"(cm) {
442+ // cm.closeTag(cm, ">");
443+ // },
444+ // "'/'"(cm) {
445+ // cm.closeTag(cm, "/");
446+ // }
447+ // }
443448 } ) ;
449+
450+ textarea . parentNode . insertBefore ( view . dom , textarea ) ;
451+ textarea . style . display = "none" ;
452+ // TODO: is there a form?
453+ if ( textarea . form )
454+ textarea . form . addEventListener ( "submit" , ( ) => {
455+ textarea . value = view . state . doc . toString ( ) ;
456+ } ) ;
457+ ide . codeEditor = view ;
444458 // fire onChange after initialization
445- ide . codeEditor . getOption ( "onChange" ) ( ide . codeEditor ) ;
459+ // ide.codeEditor.getOption("onChange")(ide.codeEditor);
446460 } else {
447461 // use non-rich editor
448462 ide . codeEditor = $ ( "#editor textarea" ) [ 0 ] ;
@@ -467,11 +481,10 @@ class IDE {
467481 ide . codeEditor . setValue ( args . query ) ;
468482 }
469483 // init dataviewer
470- ide . dataViewer = CodeMirror ( $ ( "#data" ) [ 0 ] , {
471- value : "no data loaded yet" ,
472- lineNumbers : true ,
473- readOnly : true ,
474- mode : "javascript"
484+ ide . dataViewer = new EditorView ( {
485+ parent : $ ( "#data" ) [ 0 ] ,
486+ doc : "no data loaded yet" ,
487+ extensions : [ basicSetup , javascript ( ) , EditorState . readOnly . of ( true ) ]
475488 } ) ;
476489
477490 // init leaflet
0 commit comments