Skip to content

feat: configurable injection of js and css - #174

Open
m-abs wants to merge 8 commits into
mainfrom
feat/injectable-js-css
Open

feat: configurable injection of js and css#174
m-abs wants to merge 8 commits into
mainfrom
feat/injectable-js-css

Conversation

@m-abs

@m-abs m-abs commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Restored dev branch from before rewritting history

@m-abs
m-abs marked this pull request as ready for review August 25, 2026 13:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a cross-platform API for registering additional JavaScript and CSS assets to be injected into EPUB HTML resources, extending the existing built-in flutterReadiumTools.js / flutterReadiumTools.css helper injection. It introduces a new shared InjectionAsset model and wires the method-channel plumbing, with Android implementing the injection into HTML resources and iOS adding storage + method handlers.

Changes:

  • Added InjectionAsset (JSON-serializable) and new platform-interface methods: setCssInjections / setJavaScriptInjections.
  • Android: implemented configurable injection by composing built-in helpers with extra injection assets and making injection idempotent via marker replacement.
  • iOS: added method-channel handlers and state for injection lists; updated docs/changelog and extended tooling scripts.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
flutter_readium/test/flutter_readium_test.dart Updates mock platform to satisfy new platform interface methods.
flutter_readium/lib/flutter_readium.dart Exposes new public API methods on FlutterReadium.
flutter_readium/ios/flutter_readium/Sources/flutter_readium/FlutterReadiumPlugin.swift Adds iOS-side injection asset parsing and method-channel handlers; stores injection lists.
flutter_readium/CHANGELOG.md Documents the new injection feature and platform support.
flutter_readium/android/src/main/kotlin/dk/nota/flutterreadium/ReadiumReader.kt Passes configured injections into the HTML injection pipeline.
flutter_readium/android/src/main/kotlin/dk/nota/flutterreadium/ReadiumExtensions.kt Implements injection asset URL building and marker-based replace/insert logic.
flutter_readium/android/src/main/kotlin/dk/nota/flutterreadium/PublicationChannel.kt Adds method-channel handlers to set injections from Dart.
flutter_readium_platform_interface/lib/src/shared/injection_asset.dart Introduces the shared Dart InjectionAsset model and JSON serialization.
flutter_readium_platform_interface/lib/src/shared/index.dart Exports InjectionAsset from the shared model index.
flutter_readium_platform_interface/lib/method_channel_flutter_readium.dart Implements method-channel calls for the new injection setters.
flutter_readium_platform_interface/lib/flutter_readium_platform_interface.dart Adds the new injection methods to the platform interface contract.
CLAUDE.md Updates documented repo toolchain facts and Flutter version update guidance.
bin/format Extends formatting script behavior (formatting scope + added analysis calls).
.vscode/settings.json Adjusts tool auto-approve configuration entries.
Suppressed comments (2)

flutter_readium/ios/flutter_readium/Sources/flutter_readium/FlutterReadiumPlugin.swift:233

  • The arguments coming from Dart are bridged as [[String: Any]] (with NSNull for nulls). Casting to [[String: Any?]] will often fail and silently fall back to [], making injection registration a no-op on iOS. Also, mapping via the force-casting initializer can crash; use a compactMap with the failable initializer.
    case "setCssInjections":
      let items = call.arguments as? [[String: Any?]] ?? []
      self.cssInjections = items.map { InjectionAsset(from: $0) }
      result(nil)
    case "setJavaScriptInjections":

flutter_readium/ios/flutter_readium/Sources/flutter_readium/FlutterReadiumPlugin.swift:43

  • These new injection lists are stored and can be set over the method channel, but they are never read when building the WKWebView user scripts. As a result, the iOS implementation appears to accept injections without actually injecting them into EPUB resources.
  /// Extra CSS assets injected alongside the built-in helpers.
  var cssInjections: [InjectionAsset] = []

  /// Extra JavaScript assets injected alongside the built-in helpers.
  var javaScriptInjections: [InjectionAsset] = []

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +69 to +78
/// Registers extra CSS assets to inject into every EPUB HTML resource,
/// in addition to the built-in `flutterReadiumTools.css`.
/// Call before opening a publication so the injections are active when the reader view is created.
Future<void> setCssInjections(List<InjectionAsset> injections) => _platform.setCssInjections(injections);

/// Registers extra JavaScript assets to inject into every EPUB HTML resource,
/// in addition to the built-in `flutterReadiumTools.js`.
/// Call before opening a publication so the injections are active when the reader view is created.
Future<void> setJavaScriptInjections(List<InjectionAsset> injections) =>
_platform.setJavaScriptInjections(injections);
}
}

PluginLog.d(TAG, "Injecting files into: $filename")
Comment on lines +18 to +21
init(from map: [String: Any?]) {
assetPath = map["assetPath"] as! String
packageName = map["package"] as? String
}
Comment on lines +5 to +17
/// Identifies a Flutter asset (JS or CSS file) to inject into EPUB HTML resources.
///
/// [assetPath] is the asset path as declared in `pubspec.yaml`, e.g. `assets/custom.js`.
/// [package] is the pub package that owns the asset, or `null` for app-level assets.
/// The file type is inferred from the path extension (`.js` or `.css`).
@immutable
class InjectionAsset implements JSONable {
const InjectionAsset({required this.assetPath, this.package});

factory InjectionAsset.fromJson(Map<String, dynamic> json) => InjectionAsset(
assetPath: json['assetPath'] as String,
package: json['package'] as String?,
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants