Host integration
Documentation index · Web quick start · WinForms quick start
Shared host contract
All hosts need a way to load serialized text, execute commands, retrieve a validated snapshot, and acknowledge a successful save. The same document/command engine runs in each host. The host-specific layer supplies transport, storage, dialogs, navigation decisions, and image imports.
Use JSON serializers for bridge messages. Do not construct executable JavaScript by interpolating document text into a script string. A document can legitimately contain quotes, backticks, newlines, HTML and Unicode; these must remain data.
Ordinary web applications
Serve the runtime files as static assets and instantiate CODEEditor.create. Your toolbar calls its API directly. Your load/save endpoints can use your existing authentication and document service. No MVC/Razor component, TagHelper, database schema, or automatic persistence layer is imposed.
Keep document storage and asset storage coordinated. An image URL that works on the editor origin must also work wherever the content is later rendered. If final publication is on another site, choose an absolute asset URL or translate references in your publishing pipeline. The preview hook can make output look like the final site without modifying the editing document.
Use a constrained host layout. If a hidden tab or dialog becomes visible and its measurements were unavailable, call resize(). Do not create a separate editor instance for every toolbar click or render the component's inner DOM through an application framework while the editor owns it.
ASP.NET sample
The samples/CODE.Editor.Sample.AspNetCore/ sample targets .NET 10. Generate shared browser assets first, then run from the repository root:
node build/assets.cjs
dotnet run --project samples/CODE.Editor.Sample.AspNetCore
The sample uses the shared framework and static-file hosting. Development serves artifacts/browser/; builds and publishing copy that same generated distribution into wwwroot. There is no additional Markdown NuGet dependency in this sample.
Its evaluation image storage is under App_Data/EditorAssets. POST /editor-assets accepts supported image MIME types with a bounded body and basic signature checks, stores a generated filename, and returns { src, assetId }. GET /editor-assets/{id} restricts file names to the generated shape. The POST includes a same-origin header check, but that is not user authentication or document authorization.
For an application deployment, attach your existing authentication/authorization, ownership, quotas, cleanup, and normal content-validation policy. The sample does not create authenticated document load/save endpoints. Do not assume the Node static server exposes the same upload API.
Reusable WinForms control
TextEditor owns WebView2 and automatically loads https://code-editor.example/control.html from embedded resources. Requests for the control's assets are served by the class library with appropriate MIME types. This is a private virtual host, not an internet endpoint you need to deploy.
The bridge accepts only its allowed editor operations. Native requests include ID, method, and arguments; responses return the correlated ID, value/error, and current state. Requests are queued to preserve property/method order. Selection is flattened for the .NET API. The control prevents arbitrary page navigation, handles new-window/link requests through the host, and denies unexpected permission requests.
Custom preview and image storage are reverse requests from JavaScript to .NET. They have their own correlation and cancellation. The typed events are the supported integration point; hosts should not independently attach a competing message protocol to the internal WebView2.
The control does not expose its browser as a public property. This helps preserve its loading and message assumptions. For application behavior, prefer the typed API/events. If a future use case needs a new capability, add an explicit method/event rather than exposing unrestricted script evaluation.
Photino
The full project includes samples/CODE.Editor.Sample.Photino/README.md and ImageMessageHandler.cs. This is an integration example, not a compiled/running Photino sample solution. No Photino runtime/package is bundled or validated in this delivery.
The browser demo's optional app.js adapter detects window.external.receiveMessage and sends responses through window.external.sendMessage. Register the native receiver before navigation and wait for the editor ready event before issuing requests.
{"id":"load-1","method":"setValue","args":["# Hello",{"format":"markdown","mode":"rich","language":"markdown"}]}
{"id":"save-1","method":"getSnapshot","args":[]}
Replies use type: "response", the same ID, and either value or error. Events are separate. The demo bridge allowlist includes getValue, setValue, getSnapshot, getSelection, setSelection, execute, markSaved, setMode, rebuild, focus, setReadOnly, setPreviewVisible, configure, getSelectedText, replaceRange and applyTransaction. It is not identical to the newer reusable WinForms control protocol.
For a single embedded component rather than the demo page, instantiate the JavaScript editor and bridge only the necessary methods. A custom async preview callback needs an appropriate host request/reply implementation; the WinForms PreviewRequested event is not automatically available in Photino.
The image adapter is constructed explicitly with an asset directory and a filename-to-URL callback. Route only trusted editor messages to it, return its reply to the page, and dispose it with the window. It does not establish trusted origin/window identity for you. Signature validation is basic; apply your normal application validation. Confirm bridge naming and behavior against the Photino version your application uses.
Mobile browsers and layout
The JavaScript component is intended for mobile browser use. Its preview stacks at narrower widths, and the browser supplies touch selection and keyboard input. This delivery does not establish completed acceptance on iOS Safari, Android Chrome, or every embedded WebKit environment.
Test the actual device keyboard, composition, scroll interaction, viewport resizing when the keyboard opens, long-press clipboard behavior, drag/drop availability, and focus movement. A desktop browser resized to phone width verifies responsive layout but cannot establish mobile input correctness. Keep minimum pane sizes practical and allow the host to hide preview on constrained screens.
Document and asset portability
Store the serialized text together with the application's format/policy metadata as appropriate. Editor session IDs and revisions are local editing mechanics, not stable application record IDs. Persist stable asset IDs in your asset service rather than relying only on temporary browser URLs. If applications render saved content outside this editor, they must use the same intended Markdown extensions or their own compatible publishing pipeline.