Skip to content

Commit

Permalink
Merge pull request #202 from gaelj/release
Browse files Browse the repository at this point in the history
🔖 Release 0.8.14
  • Loading branch information
gaelj authored Nov 14, 2024
2 parents 6a1a25e + 76b4df1 commit 1cc3a71
Show file tree
Hide file tree
Showing 23 changed files with 323 additions and 26 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

## 0.8.14 - 2024-11-14

### ⚡️ Improve performance

- Persist style tag created by CM6 after reloads, without needing any HeadOutlet in Blazor Server interactive (#187), as described in https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/static-server-rendering?view=aspnetcore-8.0
- Dispose the JS object if the parent div does not exist ; robustify dispose method

### 🐛 Fix a bug

- Fix example 3 in server interactive mode
- Fix null refs

### 💥 Introduce breaking changes

- Make parameter IsWASM obsolete: it can be automatically inferred from `OperatingSystem.IsBrowser()`

### 📝 Add or update documentation

- Add missing example3 page

## 0.8.13 - 2024-11-13

### ✨ Introduce new features
Expand Down
3 changes: 2 additions & 1 deletion CodeMirror6/CodeMirror6.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<AssemblyName>GaelJ.BlazorCodeMirror6</AssemblyName>
<IsPackable>true</IsPackable>
<PackageId>GaelJ.BlazorCodeMirror6</PackageId>
<Version>0.8.13</Version>
<Version>0.8.14</Version>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down Expand Up @@ -43,6 +43,7 @@
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.8" Condition="'$(TargetFramework)'=='net8.0'" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
<PackageReference Include="Microsoft.SourceLink.Github" Version="8.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand Down
1 change: 0 additions & 1 deletion CodeMirror6/CodeMirror6Wrapper.razor
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
FocusChanged="@FocusChanged"
GetMentionCompletions="@GetMentionCompletions"
IndentationUnit="@IndentationUnit"
IsWASM="@IsWASM"
Language="@Language"
LineWrapping="@LineWrapping"
LintDocument="@LintDocument"
Expand Down
1 change: 1 addition & 0 deletions CodeMirror6/CodeMirror6Wrapper.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public partial class CodeMirror6Wrapper : ComponentBase
/// <summary>
/// Define whether the component is used in a WASM or Server app. In a WASM app, JS interop can start sooner
/// </summary>
[Obsolete("This parameter is now automatically set, and will be removed in a future version")]
[Parameter] public bool IsWASM { get; set; }
/// <summary>
/// The unified merge view configuration
Expand Down
4 changes: 3 additions & 1 deletion CodeMirror6/CodeMirror6WrapperInternal.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<div class=@ContainerClass style=@ContainerStyle id=@ContainerId>
<page-script src=@($"{CodeMirrorJsInterop.JsEntryPoint}")></page-script>

<div class=@ContainerClass style=@ContainerStyle id=@ContainerId>

<div id=@TopBarId>
@if (Visible && ContentBefore is not null && CmJsInterop is not null && Config is not null && CommandDispatcher is not null) {
Expand Down
5 changes: 4 additions & 1 deletion CodeMirror6/CodeMirror6WrapperInternal.razor.JsInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ CodeMirror6WrapperInternal cm6WrapperComponent
) : IAsyncDisposable
{
private static string LibraryName => typeof(CodeMirrorJsInterop).Assembly.GetName().Name!;
public static string JsEntryPoint => $"./_content/{LibraryName}/index.js";
private readonly Lazy<Task<IJSObjectReference>> _moduleTask =
new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
"import", $"./_content/{LibraryName}/index.js").AsTask()
"import",
JsEntryPoint
).AsTask()
);
private readonly DotNetObjectReference<CodeMirror6WrapperInternal> _dotnetHelperRef = DotNetObjectReference.Create(cm6WrapperComponent);
private CMSetters _setters = null!;
Expand Down
5 changes: 1 addition & 4 deletions CodeMirror6/CodeMirror6WrapperInternal.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,6 @@ public partial class CodeMirror6WrapperInternal : ComponentBase, IAsyncDisposabl
/// </summary>
[Parameter] public bool EmbedUploadsAsDataUrls { get; set; }
/// <summary>
/// Define whether the component is used in a WASM or Server app. In a WASM app, JS interop can start sooner
/// </summary>
[Parameter] public bool IsWASM { get; set; }
/// <summary>
/// The unified merge view configuration
/// </summary>
[Parameter] public UnifiedMergeConfig? MergeViewConfiguration { get; set; }
Expand Down Expand Up @@ -267,6 +263,7 @@ public partial class CodeMirror6WrapperInternal : ComponentBase, IAsyncDisposabl
private string MaxWidthStyle => FullScreen || (string.IsNullOrEmpty(MaxWidth) && string.IsNullOrEmpty(Width)) ? string.Empty : $"max-width: {MaxWidth ?? Width};";
private string MaxHeightStyle => FullScreen || (string.IsNullOrEmpty(MaxHeight) && string.IsNullOrEmpty(Height)) ? string.Empty : $"max-height: {MaxHeight ?? Height};";
private string EditorStyle => $"{WidthStyle} {HeightStyle} {MaxWidthStyle} {MaxHeightStyle}";
private static bool IsWASM => OperatingSystem.IsBrowser();
/// <summary>
/// JavaScript interop instance
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion CodeMirror6/NodeLib/src/CmHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const hasOverlap = (x1: number, x2: number, y1: number, y2: number) => {

export const isCursorInRange = (state: EditorState, from: number, to: number) => {
const id = getIdFromState(state)
if (!CMInstances[id].config?.showMarkdownControlCharactersAroundCursor) return false
if (!CMInstances[id]?.config?.showMarkdownControlCharactersAroundCursor) return false
return state.selection.ranges.some((range) => {
return hasOverlap(from, to, range.from, range.to)
})
Expand Down
48 changes: 47 additions & 1 deletion CodeMirror6/NodeLib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,35 @@ import { hyperLink } from './CmHyperlink'
export { getCmInstance }
export { requestLinterRefresh }

let StyleTag: HTMLStyleElement | null = null

export async function onUpdate() {
await loadCss("_content/GaelJ.BlazorCodeMirror6/GaelJ.BlazorCodeMirror6.bundle.scp.css")
if (StyleTag) {
const style = document.createElement('style');
style.textContent = StyleTag.textContent
document.head.appendChild(style);
}
}

export function onDispose() {
for (const id in CMInstances) {
dispose(id)
}
}

function findCodeMirrorStyleTag() {
const tags = document.querySelectorAll('style')
for (let i = 0; i < tags.length; i++) {
const tag = tags[i]
if (tag.innerHTML.includes('.ͼ1.cm-focused')) {
return tag
}
}
return null
}


/**
* Initialize a new CodeMirror instance
* @param dotnetHelper
Expand All @@ -82,6 +111,7 @@ export async function initCodeMirror(
const parentDiv = document.getElementById(id)
if (!parentDiv) {
console.error(`Parent div with id ${id} not found`)
dispose(id)
return
}

Expand Down Expand Up @@ -245,6 +275,21 @@ export async function initCodeMirror(
adjustEditorHeight(id)

forceRedraw(id)

const tag = findCodeMirrorStyleTag()
if (tag) {
consoleLog(id, `Found CodeMirror style tag`)
StyleTag = tag
}
else if (StyleTag) {
consoleLog(id, `CodeMirror style tag not found, retrieving from CodeMirror instance`)
const style = document.createElement('style');
style.textContent = StyleTag.textContent
document.head.appendChild(style);
}
else {
console.error(`CodeMirror style tag not found and no previous style tag found to retrieve`)
}
}
catch (error) {
console.error(`Error in initializing CodeMirror`, error)
Expand Down Expand Up @@ -417,7 +462,7 @@ export async function setConfiguration(id: string, newConfig: CmConfiguration) {
view.dispatch({
effects: effects,
changes: changes,
})
})
if (redrawNeeded)
forceRedraw(id)
}
Expand Down Expand Up @@ -601,6 +646,7 @@ const getCmInstance = (id: string) => CMInstances[id]
* @param id
*/
export function dispose(id: string) {
if (!CMInstances || !CMInstances[id]) return
consoleLog(id, `Disposing of CodeMirror instance ${id}`)
if (CMInstances[id].dotNetHelper !== undefined) {
CMInstances[id].dotNetHelper.dispose()
Expand Down
82 changes: 82 additions & 0 deletions CodeMirror6/Resources/GaelJ.BlazorCodeMirror6.lib.module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const pageScriptInfoBySrc = new Map();

function registerPageScriptElement(src) {
if (!src) {
throw new Error('Must provide a non-empty value for the "src" attribute.');
}

let pageScriptInfo = pageScriptInfoBySrc.get(src);

if (pageScriptInfo) {
pageScriptInfo.referenceCount++;
} else {
pageScriptInfo = { referenceCount: 1, module: null };
pageScriptInfoBySrc.set(src, pageScriptInfo);
initializePageScriptModule(src, pageScriptInfo);
}
}

function unregisterPageScriptElement(src) {
if (!src) {
return;
}

const pageScriptInfo = pageScriptInfoBySrc.get(src);

if (!pageScriptInfo) {
return;
}

pageScriptInfo.referenceCount--;
}

async function initializePageScriptModule(src, pageScriptInfo) {
if (src.startsWith("./")) {
src = new URL(src.substr(2), document.baseURI).toString();
}

const module = await import(src);

if (pageScriptInfo.referenceCount <= 0) {
return;
}

pageScriptInfo.module = module;
module.onLoad?.();
module.onUpdate?.();
}

function onEnhancedLoad() {
for (const [src, { module, referenceCount }] of pageScriptInfoBySrc) {
if (referenceCount <= 0) {
module?.onDispose?.();
pageScriptInfoBySrc.delete(src);
}
}

for (const { module } of pageScriptInfoBySrc.values()) {
module?.onUpdate?.();
}
}

export function afterWebStarted(blazor) {
customElements.define('page-script', class extends HTMLElement {
static observedAttributes = ['src'];

attributeChangedCallback(name, oldValue, newValue) {
if (name !== 'src') {
return;
}

this.src = newValue;
unregisterPageScriptElement(oldValue);
registerPageScriptElement(newValue);
}

disconnectedCallback() {
unregisterPageScriptElement(this.src);
}
});

blazor.addEventListener('enhancedload', onEnhancedLoad);
}
13 changes: 13 additions & 0 deletions CodeMirror6/bundleconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
{
"outputFileName": "wwwroot/GaelJ.BlazorCodeMirror6.lib.module.js",
"inputFiles": [
"Resources/GaelJ.BlazorCodeMirror6.lib.module.js"
],
"minify": {
"enabled": false,
"renameLocals": false
},
"sourceMap": true
}
]
2 changes: 1 addition & 1 deletion Examples.BlazorServer/Examples.BlazorServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>0.8.13</Version>
<Version>0.8.14</Version>
</PropertyGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
Expand Down
3 changes: 1 addition & 2 deletions Examples.BlazorServerInteractive/Components/App.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">

<head>
Expand All @@ -10,7 +10,6 @@
<link rel="stylesheet" href="Examples.BlazorServerInteractive.styles.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>

<body>
Expand Down
Loading

0 comments on commit 1cc3a71

Please sign in to comment.