Skip to content

Apply application's theme to MarkdownEditor component #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.flowingcode.vaadin.addons</groupId>
<artifactId>markdown-editor-addon</artifactId>
<version>1.1.1-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
<name>Markdown Editor Add-on</name>
<description>Markdown Editor for Vaadin Flow</description>
<url>https://www.flowingcode.com/en/open-source/</url>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@
*/
package com.flowingcode.vaadin.addons.markdown;

import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.DetachEvent;
import com.vaadin.flow.component.HasSize;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dependency.JavaScript;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.react.ReactAdapterComponent;
import com.vaadin.flow.function.SerializableConsumer;
Expand All @@ -33,29 +37,9 @@
@NpmPackage(value = "mermaid", version = "11.2.1")
@NpmPackage(value = "@uiw/react-md-editor", version = "4.0.4")
@NpmPackage(value = "dompurify", version = "3.1.6")
@JavaScript("./connector.js")
public class BaseMarkdownComponent extends ReactAdapterComponent implements HasSize {

/**
* Defines the color schemes for the Markdown component.
*
* The color mode can be set using the {@link #setDataColorMode(DataColorMode)} method.
*
* <ul>
* <li>{@link #DARK}: Dark color scheme.
* <li>{@link #LIGHT}: Light color scheme.
* <li>{@link #AUTO}: Automatically detects the color scheme based on the user's system settings.
* </ul>
*/
public enum DataColorMode {
DARK,
LIGHT,
/**
* @deprecated Use LIGHT instead
*/
@Deprecated
LIGTH,
AUTO};

private String content;

/**
Expand Down Expand Up @@ -96,24 +80,27 @@ public void addContentChangeListener(SerializableConsumer<String> listener) {
addStateChangeListener("content", String.class, listener);
}

/**
* Sets the color mode of the Markdown component.
*
* @param mode the color mode of the component
*/
public void setDataColorMode(DataColorMode mode) {
switch (mode) {
case DARK:
getElement().setAttribute("data-color-mode", "dark");
break;
case LIGTH:
case LIGHT:
getElement().setAttribute("data-color-mode", "light");
break;
case AUTO:
getElement().removeAttribute("data-color-mode");
break;
}
private void runBeforeClientResponse(SerializableConsumer<UI> command) {
getElement().getNode().runWhenAttached(ui -> ui
.beforeClientResponse(this, context -> command.accept(ui)));
}


@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);

runBeforeClientResponse(ui -> ui.getPage().executeJs(
"window.Vaadin.Flow.fcMarkdownEditorConnector.observeThemeChange($0)",
getElement()));
}

Comment on lines +89 to +96
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Guard against missing connector on first paint

ui.getPage().executeJs("window.Vaadin.Flow.fcMarkdownEditorConnector.observeThemeChange($0)", …) will throw a client-side error if the connector script has not yet been executed (e.g., if the bundle is still downloading).

Consider adding a defensive check:

- "window.Vaadin.Flow.fcMarkdownEditorConnector.observeThemeChange($0)"
+ "window.Vaadin && Vaadin.Flow && Vaadin.Flow.fcMarkdownEditorConnector "
+ + "? Vaadin.Flow.fcMarkdownEditorConnector.observeThemeChange($0) : undefined"

or wrap the call in the JS connector itself.

Committable suggestion skipped: line range outside the PR's diff.

@Override
protected void onDetach(DetachEvent detachEvent) {
super.onDetach(detachEvent);

getUI().ifPresent(ui -> ui.getPage().executeJs(
"window.Vaadin.Flow.fcMarkdownEditorConnector.unobserveThemeChange($0)",
this.getElement()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.react.ReactAdapterComponent;

/**
* Component for displaying Markdown text
Expand Down
79 changes: 79 additions & 0 deletions src/main/resources/META-INF/resources/frontend/connector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*-
* #%L
* Markdown Editor Add-on
* %%
* Copyright (C) 2024 Flowing Code
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
(function() {

window.Vaadin.Flow.fcMarkdownEditorConnector = {
observeThemeChange: markDownEditor => {
// Check whether the connector was already initialized for markDownEditor
if (markDownEditor.$connector) {
return;
}

markDownEditor.$connector = {};

const supportedTheme = theme => ['light', 'dark'].includes(theme);

const setDataColorMode = theme => {
if (supportedTheme(theme)) {
markDownEditor.setAttribute('data-color-mode', theme);
} else {
markDownEditor.removeAttribute('data-color-mode');
}
};

// Get theme from html element when using Vaadin's @Theme annotation
const mainTheme = document.documentElement.getAttribute('theme');
if (supportedTheme(mainTheme)) {
setDataColorMode(mainTheme);
} else {
// Listen for theme changes in body element otherwise

// options for the observer (which mutations to observe)
const config = { attributes: true };

// callback function to execute when mutations are observed
const callback = (mutationList, observer) => {
for (const mutation of mutationList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'theme') {
const themeName = mutation.target.getAttribute(mutation.attributeName);
setDataColorMode(themeName);
}
}
};

// create an observer instance linked to the callback function
markDownEditor.$connector.themeChangeObserver = new MutationObserver(callback);

// start observing html tag for configured mutations
markDownEditor.$connector.themeChangeObserver.observe(document.documentElement, config);

// start observing body tag for configured mutations
markDownEditor.$connector.themeChangeObserver.observe(document.body, config);
}
},
unobserveThemeChange: markDownEditor => {
// stop observing the target node for configured mutations
if (markDownEditor.$connector.themeChangeObserver) {
markDownEditor.$connector.themeChangeObserver.disconnect();
markDownEditor.$connector.themeChangeObserver = null;
}
}
}
})();
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@
package com.flowingcode.vaadin.addons.markdown;

import com.flowingcode.vaadin.addons.demo.DemoSource;
import com.flowingcode.vaadin.addons.markdown.BaseMarkdownComponent.DataColorMode;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.Lumo;
import java.util.List;

@DemoSource
@PageTitle("Markdown Editor Demo")
Expand All @@ -41,26 +43,6 @@ public MarkdownEditorDemo() {
mde.setSizeFull();
mde.setPlaceholder("Enter Markdown here");
mde.setMaxLength(500);
mde.setDataColorMode(DataColorMode.LIGTH);
ComboBox<String> cb = new ComboBox<String>();
cb.setItems("Dark","Light","Automatic");
cb.setLabel("Color mode");
cb.setValue("Light");
cb.addValueChangeListener(ev->{
switch(ev.getValue()) {
case "Dark":
mde.setDataColorMode(DataColorMode.DARK);
break;
case "Light":
mde.setDataColorMode(DataColorMode.LIGHT);
break;
case "Automatic":
mde.setDataColorMode(DataColorMode.AUTO);
break;
default:
break;
}
});
Button getContentButton = new Button("Show content",ev->Notification.show(mde.getContent()));
Button setSampleContent = new Button("Set sample content",ev->{
mde.setContent("""
Expand Down Expand Up @@ -90,6 +72,6 @@ public static void main(String[] args) {
~~This is strikethrough text~~
""");
});
add(mde,cb,new HorizontalLayout(getContentButton,setSampleContent));
add(mde,new HorizontalLayout(getContentButton,setSampleContent));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
package com.flowingcode.vaadin.addons.markdown;

import com.flowingcode.vaadin.addons.demo.DemoSource;
import com.flowingcode.vaadin.addons.markdown.BaseMarkdownComponent.DataColorMode;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
Expand All @@ -36,7 +34,6 @@ public MarkdownViewerDemo() {
setSizeFull();
MarkdownViewer mdv = new MarkdownViewer();
mdv.setSizeFull();
mdv.setDataColorMode(DataColorMode.LIGTH);
mdv.setContent("""

# h1 Heading
Expand Down Expand Up @@ -202,25 +199,6 @@ public MarkdownViewerDemo() {
[^second]: Footnote text.

""");
ComboBox<String> cb = new ComboBox<String>();
cb.setItems("Dark","Light","Automatic");
cb.setLabel("Color mode");
cb.setValue("Light");
cb.addValueChangeListener(ev->{
switch(ev.getValue()) {
case "Dark":
mdv.setDataColorMode(DataColorMode.DARK);
break;
case "Light":
mdv.setDataColorMode(DataColorMode.LIGHT);
break;
case "Automatic":
mdv.setDataColorMode(DataColorMode.AUTO);
break;
default:
break;
}
});
add(mdv,cb);
add(mdv);
}
}