Skip to content
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

Refactor dataTable plugin to decouple from Vue #2626

Merged
merged 6 commits into from
Mar 10, 2025

Conversation

gerteck
Copy link
Contributor

@gerteck gerteck commented Mar 8, 2025

What is the purpose of this pull request?

  • Documentation update
  • Bug fix
  • Feature addition or enhancement
  • Code maintenance
  • DevOps
  • Improve developer experience
  • Others, please explain:

Overview of changes:

Decouple dataTable from Vue by using MutationObserver instead of relying on Vue Directives to process dynamically loaded content.

Previously, dataTable is processed through Vue by adding it as a vue directive. However, this approach was not entirely correct, as the Vue directive could only be registered after mounting (as it is added as a script). This approach was used to account for dynamically added content such as includes, and panels (which are dynamically added through defined Vue components). This would also result in a Vue warning as so:

image

This is because when the content is hydrated, the vue directive would not have been registered yet, and Vue would not recognise v-datatable as a registered directive. (note that this Vue warning only shows in developmental mode, i.e. markbind serve -d, and does not show up on production vue, i.e. markbind website, or markbind serve.)

This becomes a further issue when migrating Vue, as Vue is no longer a global object where we can register the vue directive. Instead, this PR proposes the use of MutationObservers which observes changes to the DOM (e.g., added/removed nodes, attribute changes) and executes a callback when a change is detected (i.e. run datatable or any other external js plugin file).

My only concern is that shifting from Vue Directives to MutationObserver could introduce some overhead or inefficiency as Vue directives could possibly be more optimized for vue components, as it has access to Vue's reactivity system and can trigger updates directly when data changes. Not sure. Perhap MutationObserver might be more efficient as well.

However, I think that using MutationObserver will make it easier to reason about the logic of how the plugins are applied.

Other changes:
Also updated tests as <span> was wrapping <table> causing hydration issues.

Snapshots tests updated. Additionally, unit test testing datatable has been updated (conditional checking for vue directive attribute removed) .

Partially addresses #2627

Anything you'd like to highlight/discuss:

Note: this approach will also be adopted by the mermaid plugin, and I will make a separate PR utilizing a similar approach for the plugin.

Testing instructions:

  • cd .\packages\cli\test\functional\test_site_table_plugin\
  • markbind serve -d

Proposed commit message: (wrap lines at 72 characters)

Refactor dataTable plugin

Decouple dataTable from Vue by using MutationObserver instead
of relying on Vue Directives to process dynamically loaded content.


Checklist: ☑️

  • Updated the documentation for feature additions and enhancements
  • Added tests for bug fixes or features
  • Linked all related issues
  • No unrelated changes

Reviewer checklist:

Indicate the SEMVER impact of the PR:

  • Major (when you make incompatible API changes)
  • Minor (when you add functionality in a backward compatible manner)
  • Patch (when you make backward compatible bug fixes)

At the end of the review, please label the PR with the appropriate label: r.Major, r.Minor, r.Patch.

Breaking change release note preparation (if applicable):

  • To be included in the release note for any feature that is made obsolete/breaking

Give a brief explanation note about:

  • what was the old feature that was made obsolete
  • any replacement feature (if any), and
  • how the author should modify his website to migrate from the old feature to the replacement feature (if possible).

Decouple dataTable from Vue by using MutationObserver
instead of relying on Vue Directives to process dynamically
loaded content.
@gerteck gerteck requested a review from Tim-Siu March 8, 2025 09:45
@Tim-Siu
Copy link
Contributor

Tim-Siu commented Mar 8, 2025

Thank you for spotting the vue hydration issue. It indeed resolved the "[Vue warn]"

I can't really remember why I put there a haha. I now see that this creates a mismatch between server and client templates?

Copy link
Contributor

@Tim-Siu Tim-Siu left a comment

Choose a reason for hiding this comment

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

This PR decouples the dataTable plugin from Vue by replacing Vue directives with MutationObserver to detect and process dynamically loaded tables.

The change addresses:

  • Vue warnings caused by directives not being registered before content hydration
  • Future compatibility issues with Vue migration (where Vue is no longer global)
  • Proper initialization of tables in dynamically added content (includes, panels, modals)

The implementation uses MutationObserver to watch DOM changes and initialize tables as they're added, applying appropriate DataTable processing and marking them with a .dt-processed class.

Test fixes correctly remove unnecessary <span> wrappers around <include> tags.

This looks like a solid improvement that will make the plugin more maintainable and fix the current hydration warnings.

LGTM 👍

gerteck added 2 commits March 8, 2025 22:06
Remove v-dataTable as Vue directive is no longer used.
@gerteck
Copy link
Contributor Author

gerteck commented Mar 8, 2025

Thank you for spotting the vue hydration issue. It indeed resolved the "[Vue warn]"

I can't really remember why I put there a haha. I now see that this creates a mismatch between server and client templates?

yep! I think the issue is that the <span> can only contain permitted phrasing content (text and markup only), so when the web browser receives the rendered HTML it does some reordering of some sort to reorder the invalid HTML into something valid which in turn causes the mismatch between rendered DOM and received HTML.

I also just pushed the update to the snapshot files (to account for <span> removal) and the unit test (removed check for v-dataTable Vue directive) for the DataTables. Testing for dt-processed in the unit tests and rendering of dataTables might be more complex as that requires integration testing with the dataTable js file.

Thanks @Tim-Siu for your speedy reply!!

@Tim-Siu
Copy link
Contributor

Tim-Siu commented Mar 9, 2025

I'm comfortable omitting the dataTables rendering checks from unit tests since they weren't previously included. For testing the dt-processed class, if it is too complex to implement, we can skip it. The integration tests in the PR (might) already validate this functionality.

Copy link

codecov bot commented Mar 10, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 51.86%. Comparing base (8c9de42) to head (8ad740f).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2626   +/-   ##
=======================================
  Coverage   51.86%   51.86%           
=======================================
  Files         127      127           
  Lines        5474     5474           
  Branches     1201     1201           
=======================================
  Hits         2839     2839           
  Misses       2340     2340           
  Partials      295      295           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@lhw-1 lhw-1 left a comment

Choose a reason for hiding this comment

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

I've read through the review history and comments; LGTM. Thanks @gerteck!

@lhw-1 lhw-1 merged commit 3aa59b5 into MarkBind:master Mar 10, 2025
8 checks passed
Copy link

@lhw-1 Each PR must have a SEMVER impact label, please remember to label the PR properly.

@lhw-1 lhw-1 added the r.Minor Version resolver: increment by 0.1.0 label Mar 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
r.Minor Version resolver: increment by 0.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants