///|
type RichTextFormatter = (String) -> RichTextDocument
///|
pub(all) struct RichTextInputTransform {
text : String
caret : Int
selection : @core.TextRange?
// Char range in the previous source replaced by this transform. None means
// the range is unknown (from_input_transform then falls back to the O(doc)
// common-prefix diff in from_sources).
edit_range : MarkdownSourceRange?
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextInputTransform with Debug::{to_repr}
///|
pub extend RichTextInputTransform with Eq::{not_equal, equal}
///|
pub extend RichTextInputTransform with ToJson::{to_json}
///|
pub(all) struct RichTextSourceRange {
start : Int
end : Int
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextSourceRange with Debug::{to_repr}
///|
pub extend RichTextSourceRange with Eq::{not_equal, equal}
///|
pub extend RichTextSourceRange with ToJson::{to_json}
///|
pub(all) enum RichTextDecoration {
Strikethrough
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextDecoration with Debug::{to_repr}
///|
pub extend RichTextDecoration with Eq::{not_equal, equal}
///|
pub extend RichTextDecoration with ToJson::{to_json}
///|
/// Shape-and-state marker drawn in a block's prefix lane instead of a glyph.
///
/// Task list items render a real rounded box with a vector checkmark; a font
/// glyph (`☑`/`☐`) depends on which installed face happens to cover U+2610,
/// so its shape, weight, and color drift per machine. The block keeps a
/// text-shaped `prefix` so caret, selection, and hit-test arithmetic stay
/// character-indexed; only the painted lane swaps the glyph for the marker.
pub(all) enum RichTextMarker {
TaskCheckbox(Bool)
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextMarker with Debug::{to_repr}
///|
pub extend RichTextMarker with Eq::{not_equal, equal}
///|
pub extend RichTextMarker with ToJson::{to_json}
///|
pub(all) struct RichTextRun {
text : String
visual_text : String?
image_source : String?
image_size : @core.Size?
image_width_fraction : Double?
image_fit : @core.ImageFit
font : @core.FontSpec?
color : @core.Color?
background : @core.Brush?
background_radius : Double
decoration : RichTextDecoration?
source_range : RichTextSourceRange?
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextRun with Debug::{to_repr}
///|
pub extend RichTextRun with Eq::{not_equal, equal}
///|
pub extend RichTextRun with ToJson::{to_json}
///|
/// One table cell. `text` is the cell's raw source (markers included);
/// `runs` is the styled projection (markers hidden, one run per inline
/// span) used by paint/geometry. Empty `runs` means "render `text` plain",
/// which keeps viewer-side tables and any legacy construction unstyled but
/// correct.
pub(all) struct RichTextTableCell {
text : String
runs : Array[RichTextRun]
header : Bool
align : @core.TextAlign?
source_range : RichTextSourceRange?
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextTableCell with Debug::{to_repr}
///|
pub extend RichTextTableCell with Eq::{not_equal, equal}
///|
pub extend RichTextTableCell with ToJson::{to_json}
///|
pub(all) struct RichTextTable {
rows : Array[Array[RichTextTableCell]]
row_height : Double
cell_padding : @core.Insets
border : @core.Color
header_background : @core.Brush?
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextTable with Debug::{to_repr}
///|
pub extend RichTextTable with Eq::{not_equal, equal}
///|
pub extend RichTextTable with ToJson::{to_json}
///|
pub(all) struct RichTextBlock {
runs : Array[RichTextRun]
table : RichTextTable?
prefix : String
marker : RichTextMarker?
font : @core.FontSpec?
color : @core.Color?
background : @core.Brush?
border_left : @core.BorderStyle?
inset : @core.Insets
line_height : Double?
corner_radius : Double
rule : Bool
line_align : @core.TextAlign?
source_range : RichTextSourceRange?
content_range : RichTextSourceRange?
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextBlock with Debug::{to_repr}
///|
pub extend RichTextBlock with Eq::{not_equal, equal}
///|
pub extend RichTextBlock with ToJson::{to_json}
///|
pub(all) struct RichTextDocument {
blocks : Array[RichTextBlock]
} derive(Eq, Debug, ToJson)
///|
pub extend RichTextDocument with Debug::{to_repr}
///|
pub extend RichTextDocument with Eq::{not_equal, equal}
///|
pub extend RichTextDocument with ToJson::{to_json}
///|
pub fn RichTextRun::new(
text~ : String,
visual_text? : String? = None,
image_source? : String? = None,
image_size? : @core.Size? = None,
image_fit? : @core.ImageFit = Contain,
font? : @core.FontSpec? = None,
color? : @core.Color? = None,
background? : @core.Brush? = None,
background_radius? : Double = 4.0,
decoration? : RichTextDecoration? = None,
source_range? : RichTextSourceRange? = None,
image_width_fraction? : Double? = None,
) -> RichTextRun {
{
text,
visual_text,
image_source,
image_size,
image_width_fraction,
image_fit,
font,
color,
background,
background_radius,
decoration,
source_range,
}
}
///|
pub fn RichTextInputTransform::new(
text~ : String,
caret~ : Int,
selection? : @core.TextRange? = None,
edit_range? : MarkdownSourceRange? = None,
) -> RichTextInputTransform {
{ text, caret, selection, edit_range, }
}
///|
pub fn RichTextBlock::new(
runs~ : Array[RichTextRun],
table? : RichTextTable? = None,
prefix? : String = "",
marker? : RichTextMarker? = None,
font? : @core.FontSpec? = None,
color? : @core.Color? = None,
background? : @core.Brush? = None,
border_left? : @core.BorderStyle? = None,
inset? : @core.Insets = @core.Insets::symmetric(),
line_height? : Double? = None,
corner_radius? : Double = 0.0,
rule? : Bool = false,
source_range? : RichTextSourceRange? = None,
content_range? : RichTextSourceRange? = None,
line_align? : @core.TextAlign? = None,
) -> RichTextBlock {
{
runs,
table,
prefix,
marker,
font,
color,
background,
border_left,
inset,
line_height,
corner_radius,
rule,
line_align,
source_range,
content_range,
}
}
///|
pub fn RichTextDocument::new(
blocks~ : Array[RichTextBlock],
) -> RichTextDocument {
{ blocks, }
}
///|
pub fn RichTextDocument::plain(text : String) -> RichTextDocument {
let blocks : Array[RichTextBlock] = []
let current : Array[Char] = []
for ch in text {
if ch == '\n' {
blocks.push(
RichTextBlock::new(runs=[
RichTextRun::new(text=String::from_array(current)),
]),
)
current.clear()
} else {
current.push(ch)
}
}
blocks.push(
RichTextBlock::new(runs=[RichTextRun::new(text=String::from_array(current))]),
)
RichTextDocument::new(blocks~)
}