Git Product home page Git Product logo

boustro's People

Contributors

jjagg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

boustro's Issues

Markdown components

This tracks the components we need to implement to support markdown (CommonMark, except for HTML):

  • Links (conf. gesture + text style)
  • Blockquotes (conf. decoration + text style)
  • Inline code (conf. Text style with bg and monospace font by default)
  • Block code (I think this should be an embed with a custom controller for syntax highlighting, not a line) #14
  • Numbered lists (use tabular FontFeature + should pass copy of paragraph iterator to LineParagraphModifier.modify) #12
  • Bullet lists

Additionally it'd be nice to support GitHub Flavored Markdown:

  • Tables
  • Task lists
  • Strikethrough

And we should have an easy system for auto-applying formatting as well (autodetect links, tags, mentions, etc.) -> #16. We might be able to use this autodetection system for syntax highlighting in code blocks if there's no comprehensive lib for it.

Tests

Desperately need to write some tests for this :)
Highest priority is DocumentController.

Serialization

Need to finish Quill delta serialization.

I'd also like a custom serialization format that maps closely to a boustro document. Should at least support a json format. Binary would be nice too, but low priority.

Should also support markdown conversion with boustro_starter components.

Doc site

In depth docs in docs/ should be hosted.

  • Text attributes
  • Line modifiers
  • Embeds
  • boustro_starter components
  • Theming boustro
  • Theming custom components
  • Serialization

Numbered list

It'd be nice to have a bidirectional iterator that can iterate paragraphs of both a BoustroDocument and a DocumentController. A copy of the iterator can then be passed when building a paragraph.

I think that'd be the cleanest way to add numbered list support. This system would mean every numbered list paragraph would have to count all items before it (O(N^2)). Though that's fine considering the low number of lines we're dealing with.

Alternatively we could have some state object that we pass through to every line for them to track state during the build step. This is less flexible, but more efficient.

Either way we really don't want to bake the line counting into boustro's core systems. It should be handled by the component itself.

Support multiple gestures/WidgetSpan

Attributes do not currently support multiple gestures (e.g. tap + long press).
One way to get support in would be to wrap segment TextSpans in a GestureRecognizer with a WidgetSpan, but there's a blocking issue for selectable text.
The specific case of tap + long press can be hacked with a custom GestureRecognizer.

Support WidgetSpan in SelectableText: flutter/flutter#38474

twitter-text conformance tests

I ported the twitter-text regular expression for the autoformatter (#16). We could add the conformance tests to make sure there no bugs in the port. It's probably valuable to split the port into a separate library and put it in another repo.

Theming custom components

We need a system or at least guidelines for theming custom components. I think there's broadly 2 paths we can take.

  1. Custom InheritedStyle per widget with some guidelines for design.
  2. Extension point inside boustro theme.

I'm leaning strongly towards 2 because it prevents deeply nested widgets when users theme a lot of different components and it lets us define an interface for themeable properties so we can have them be lerpable.

Maybe something like the following (example for max image height):

class BoustroThemeData {
  // ...
  final BuiltMap<String, Lerpable<dynamic>> customProperties;
}

abstract class Lerpable<T> {
  // used for nullable lerping
  T get defaultValue;
  T lerp(T other, double t);
}

class LerpableDouble implements Lerpable<double> {
  LerpableDouble(this.value);
  final double value;
  @override
  dynamic get defaultValue => 0;
  @override
  dynamic lerp(dynamic other, double t);
}

extension ImageEmbedTheme on BoustroThemeData {
  double get maxHeight => customProperties['embed_image_maxHeight']?.value as double;
}

extension ImageEmbedThemeBuilder on BoustroThemeDataBuilder {
  set maxHeight(double value) {
      customProperties['embed_image_maxHeight'] = LerpableDouble(value);
  }
}

Something else to consider is that currently it's not possible to depend on a theme or other scoped widgets from TextAttribute because it's just a value class. I would prefer having them support theming. This does complicate equality of attributes, but maybe type or identity equality works for this case.

Localization

There's some English text hardcoded in the starter components. Ideally these would be localizable.

Ordering and conflicts

It might be nice to have a system to determine the order in which to apply line modifiers or text attributes, and have some components disallow the presence of others.

This can be done with some checks in user code and I've only come across a few use cases in boustro_starter, so priority for this is low.

AttributeTheme should be consumed as InheritedWidget

DocumentController creates the SpannedTextEditingControllers and they in turn apply TextAttribute to build the text spans. SpannedTextEditingController can't access the BuildContext when building spans to pass it to TextAttribute, so right now, instead, DocumentController takes the theme in its constructor and passes it to each text editing controller it creates through their constructors. Because of this users won't be able to just put an AttributeTheme in the widget tree.

In the example project:

late final controller = DocumentController(
scrollController: scrollController,
attributeTheme:
(AttributeThemeBuilder()..boldFontWeight = FontWeight.w900).build());

Where it's a lot more intuitive to and in line with Flutter's theme to put it in the widget tree. See the other themes in the example project:

return AnimatedBoustroTheme(
data: BoustroTheme.of(context), // Use the default theme
child: AnimatedBoustroComponentTheme(
data: Theme.of(context).brightness == Brightness.light
? (ComponentThemeBuilder()
..imageMaxHeight = 400
..imageSideColor = Colors.brown.withOpacity(0.2))
.build()
: (ComponentThemeBuilder()
..imageMaxHeight = 350
..imageSideColor =
Colors.deepPurple.shade900.withOpacity(0.2))
.build(),
child: Scaffold(

I don't think we can improve this without a change in Flutter, so I opened an issue in the Flutter repo: flutter/flutter#72343.

Note that this is only an issue for the BoustroEditor and not for the readonly BoustroView which calls buildTextSpan itself and so can pass the AttributeTheme from its context.

Customized gesture handling for embeds

Related to #7, but we'll want a separate system to customize gesture handling for embeds. Perhaps some InheritedWidget that holds the GestureDetector information? It's overkill for styles, but there won't be as many embeds as overall components and with good default gesture handling behavior users won't have to customize the gesture handling often.

Autoformatting

We need a system to automatically apply formatting to patterns, probably based on regex matches.

Proper readmes

  • Root readme
    • screenshots
    • goals
    • In depth docs go in docs/.
    • explain name
    • logo
  • flutter_spanned_controller readme
  • boustro readme
  • boustro_starter readme

UI feedback for link toolbar item

The link toolbar item from boustro_starter does not change based on whether or not the user can actually apply a link (i.e. text is selected). That can cause confusion. It should be greyed out when there is no selection.

Builders for easy document and spanned text construction

Need some a builder for BoustroDocument and SpannedText so we can have some nice DSL to construct them. Tentative API:

class SpanTemplate {
  TextAttribute attribute;
  InsertBehavior startBehavior;
  InsertBehavior endBehavior;
}

class DocumentBuilder {
  DocumentBuilder([Iterable<BoustroParagraph> initialParagraphs]);

  void line(void Function(SpannedTextBuilder) build, Iterable<LineModifier> modifiers);

  void embed(BoustroParagraphEmbed embed);
}

class SpannedTextBuilder {
  SpannedTextBuilder({SpannedText initial, bool continueInitialSpans});

  void start(SpanTemplate style);
  void end(SpanTemplate style);
  void text(String text)
  void textf(String text, SpanTemplate style);
  void lineStyle(TextAttribute);
}

Examples

Example in root should be showcase with multiple pages (let's use Navigator 2.0); some ideas:

  • editor
  • readonly
  • readonly selectable
  • single line
  • theming (attributes, other components, boustro widgets)
  • custom toolbar
  • text selection controls instead of toolbar (maybe this is a nice feature for boustro itself)
  • serialization

We should add short single-file examples to each package too and put a comment at the top that links to the showcase.

Undo/redo

Would be nice to have, especially for non-mobile platforms.
Fairly straightforward to implement, but a bit of a chore.

Use characters

Right now we just use UTF-16 indexing for strings. That sucks because it allows invalid state like spans starting in the middle of a grapheme cluster.

We should use characters to index with grapheme clusters. This will guarantee a valid state where formatting is applied in units of grapheme clusters.

We can keep this representation when serializing because it's what makes the most sense for the data we're modelling. I initially planned to convert to UTF-8 because it's the standard encoding for web, but grapheme clusters fit the data better and there's great support for it in most programming languages nowadays.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.