OrchardCMS / OrchardCore

Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
https://orchardcore.net
BSD 3-Clause "New" or "Revised" License
7.39k stars 2.39k forks source link

Monaco editor suggestions #12766

Open hyzx86 opened 1 year ago

hyzx86 commented 1 year ago

Is your feature request related to a problem? Please describe.

Many custom js function extensions are implemented in OC, but you need to query the document to determine the usage of these functions each time

Describe the solution you'd like

Functions and objects registered by Jint can be prompted using the suggestions function of Monaco editor

In my project , this method works well

  1. Use typescript syntax to describe all OC custom javascript functions , and save them to string variables

(Partial code)

const ocTypes = `

//OrchardCore\src\OrchardCore.Modules\OrchardCore.Scripting\Providers\LogProvider.cs
//LogProvider
/**
 * 日志级别 
 **/
declare enum LogLevel {
  Trace = 'Trace',
  Debug = 'Debug',
  Information = 'Information',
  Warning = 'Warning',
  Error = 'Error',
  Critical = 'Critical',
  None = 'None'
}
/**
 * 记录日志
 * @param {LogLevel} level 日志级别
 * @param text 日志内容
 * @param param 内容参数,{parm1,parm2}
 */
declare function log(level: 'Trace' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Critical' | 'None',
  text: string, param: object): void

//OrchardCore\src\OrchardCore\OrchardCore.Infrastructure\Scripting\CommonGeneratorMethods.cs
//CommonGeneratorMethods
declare function base64(encoded: string): string
declare function html(encoded: string): string
declare function gzip(encoded: string): string

//OrchardCore\src\OrchardCore.Modules\OrchardCore.Layers\Services\DefaultLayersMethodProvider.cs
//DefaultLayersMethodProvider
declare function isHomepage(): boolean
declare function isAnonymous(): boolean
declare function isAuthenticated(): boolean
declare function isInRole(role: string): boolean
declare function url(urlString: string): boolean
declare function culture(cultureString: string): boolean

//OrchardCore\src\OrchardCore.Modules\OrchardCore.Queries\QueryGlobalMethodProvider.cs
//QueryGlobalMethodProvider
declare function executeQuery(name: string, parameters: object): object
........
`

function bindEditor(monaco) {
    monaco.languages.typescript.javascriptDefaults.addExtraLib(ocTypes);
}
  1. Register these function prompts on the monaco editor
    $(document).ready(function () {
        require(['vs/editor/editor.main'], function () {

            var html = document.getElementsByTagName("html")[0];
            const mutationObserver = new MutationObserver(setTheme);
            mutationObserver.observe(html, { attributes: true });

            function setTheme() {
                var theme = html.dataset.theme;
                if (theme === "darkmode") {
                    monaco.editor.setTheme('vs-dark')
                } else {
                    monaco.editor.setTheme('vs')
                }
            }
            setTheme();

            var editor = monaco.editor.create(document.getElementById('@Html.IdFor(m => m.Schema)_editor'), {
                automaticLayout: true,
                language: "json",
                lineNumbers: true,
                minimap: { enabled: false }
            });
+          bindEditor(monaco)

            var textArea = document.getElementById('@Html.IdFor(m => m.Schema)');
            editor.getModel().setValue(textArea.value);
            window.addEventListener("submit", function () {
                textArea.value = editor.getValue();
            });
        });
    });

Describe alternatives you've considered

  1. Whether these registered functions can be automatically discovered by the program through reflection or other methods, such as the return value of function name parameters
  2. For the creation of dynamic types or field references, Jint cannot fully support TypeScript. Therefore, this scheme cannot be realized temporarily:

var blogPost:BlogPost =newContentItem() ;

var blogPost =newContentItem() as BlogPost;

blogPost.BlogPost.ContentBody.Text="My BlogContent"

hyzx86 commented 1 year ago

image

hyzx86 commented 1 year ago

https://user-images.githubusercontent.com/15613121/200239020-0b99a318-9d4c-41ab-854e-81c5fcaf4b40.mp4

sebastienros commented 1 year ago

Since there is already a service to register custom JS methods, can't this be used too to dynamically inject the definitions? Or maybe create another event for any module to do this, which would replace ocTypes in your example. Maybe this would be just passing some script to the event, with enums and function declarations.

hyzx86 commented 1 year ago

Done,

I have regested all of parts to ContentItem in typescript

type ContentItem = {
    ContentItemId: string;
    ContentItemVersionId: string;
    ContentType: string
    DisplayText: string
    Latest: boolean
    Published: boolean
    ModifiedUtc: string
    PublishedUtc: string
    Owner: string
    Author: string 
    //后台替换
    //Don't Change any thing
    /*Content: $CONTENTPARTS$*/
}

and then use all of contentPart Schema to replace /*Content: $CONTENTPARTS$*/

hyzx86 commented 5 months ago

Here's a little try : https://github.com/OrchardCMS/OrchardCore/pull/12845#issuecomment-2076774058