Skip to content

Commit 281e8db

Browse files
committed
Initial ruby changes to Style.dart
1 parent 2a6e768 commit 281e8db

File tree

3 files changed

+202
-4
lines changed

3 files changed

+202
-4
lines changed

example/lib/main.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,16 @@ const htmlData = """
4040
漢<rt>かん</rt>
4141
字<rt>じ</rt>
4242
</ruby>
43-
&nbsp;is Japanese Kanji
43+
&nbsp;is Japanese Kanji.
44+
<br />
45+
<ruby>漢<rt>ㄏㄢˋ</rt>字<rt>ㄗˋ</rt></ruby> is Traditional Chinese.
46+
<br />
47+
<ruby>汉<rt>hàn</rt>字<rt>zì</rt></ruby> is Simplified Chinese
48+
<br />
49+
<ruby>
50+
<ruby>HT<rt>Hypertext</rt>M<rt>Markup</rt>L<rt>Language</rt></ruby>
51+
<rt>An abstract language for describing documents and applications
52+
</ruby>
4453
</p>
4554
Solve for <var>x<sub>n</sub></var>: log<sub>2</sub>(<var>x</var><sup>2</sup>+<var>n</var>) = 9<sup>3</sup>
4655
<p>One of the most common equations in all of physics is <var>E</var>=<var>m</var><var>c</var><sup>2</sup>.<p>

lib/src/replaced_element.dart

Lines changed: 135 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,19 +251,131 @@ class EmptyContentElement extends ReplacedElement {
251251
Widget toWidget(_) => null;
252252
}
253253

254+
//TODO(Sub6Resources): <ruby> formatting should adhere to
255+
// the most recent CSS WD specification: https://drafts.csswg.org/css-ruby/
254256
class RubyElement extends ReplacedElement {
255257
dom.Element element;
256258

257259
RubyElement({@required this.element, String name = "ruby"})
258260
: super(name: name, alignment: PlaceholderAlignment.middle);
259261

262+
static RubyElementInfo parseRuby(dom.Node root) {
263+
final RubyElementInfo info = RubyElementInfo();
264+
if(root.parent.localName != 'ruby') {
265+
dom.Node currentParent = root;
266+
int index = 0;
267+
int startIndex;
268+
int savedStartIndex;
269+
int lookaheadIndex;
270+
271+
BaseTextSegment currentBaseText;
272+
273+
//Start mode
274+
if(index >= currentParent.children.length) {
275+
//Jump to end mode
276+
277+
}
278+
279+
if(currentParent.children[index].localName == 'rt' || currentParent.children[index].localName == 'rp') {
280+
//Jump to annotation mode
281+
282+
}
283+
284+
startIndex = index;
285+
286+
//Base mode
287+
if(currentParent.children[index].localName == 'ruby' && currentParent == root) {
288+
currentParent = currentParent.children[index];
289+
index = 0;
290+
savedStartIndex = startIndex;
291+
startIndex = null;
292+
//Jump to start mode
293+
294+
}
295+
296+
if(currentParent.children[index].localName == 'rt' || currentParent.children[index].localName == 'rp') {
297+
BaseTextSegment newBaseTextSegment = BaseTextSegment();
298+
newBaseTextSegment.baseText = List<dom.Node>();
299+
for(int i = startIndex; i < index; i++) {
300+
newBaseTextSegment.baseText.add(currentParent.children[i]);
301+
}
302+
currentBaseText = newBaseTextSegment;
303+
info.baseTextSegments.add(newBaseTextSegment);
304+
//Jump to annotation mode
305+
}
306+
307+
index++;
308+
309+
//Base mode post-increment
310+
if(index >= currentParent.children.length) {
311+
//Jump to end mode
312+
}
313+
314+
// Jump back to base mode
315+
316+
//Annotation mode
317+
if(currentParent.children[index].localName == 'rt') {
318+
final rt = currentParent.children[index];
319+
AnnotationSegment annotationSegment = AnnotationSegment();
320+
annotationSegment.annotation = [rt];
321+
if(currentBaseText != null) {
322+
annotationSegment.segment = currentBaseText;
323+
}
324+
info.annotationSegments.add(annotationSegment);
325+
//Jump to annotation mode increment
326+
}
327+
328+
if(currentParent.children[index].localName == 'rp') {
329+
//Jump to annotation mode increment
330+
}
331+
332+
if(currentParent.children[index] is! dom.Text || (currentParent.children[index] is dom.Text && currentParent.children[index].text.trim().isNotEmpty)) {
333+
//Jump to base mode
334+
}
335+
336+
//Annotation mode increment
337+
lookaheadIndex = index + 1;
338+
339+
//Annotation mode white-space skipper
340+
if(lookaheadIndex == currentParent.children.length) {
341+
//Jump to end mode
342+
}
343+
344+
if(currentParent.children[lookaheadIndex].localName == 'rt' || currentParent.children[lookaheadIndex].localName == 'rp') {
345+
index = lookaheadIndex;
346+
//Jump to annotation mode
347+
}
348+
349+
if(currentParent.children[lookaheadIndex] is! dom.Text || (currentParent.children[lookaheadIndex] is dom.Text && currentParent.children[lookaheadIndex].text.trim().isNotEmpty)) {
350+
//Jump to base mode (without incrementing index)
351+
}
352+
lookaheadIndex++;
353+
354+
//Jump to annotation mode white space skipper
355+
356+
//End mode
357+
if(currentParent != root) {
358+
index = root.children.indexOf(currentParent);
359+
currentParent = root;
360+
index++;
361+
startIndex = savedStartIndex;
362+
savedStartIndex = null;
363+
//Jump to base mode post increment.
364+
}
365+
366+
}
367+
368+
//End
369+
return info;
370+
}
371+
260372
@override
261373
Widget toWidget(RenderContext context) {
262-
dom.Node textNode = null;
374+
dom.Node textNode;
263375
List<Widget> widgets = List<Widget>();
264376
//TODO calculate based off of parent font size.
265-
final rubySize = max(9.0, context.style.fontSize.size / 2);
266-
final rubyYPos = rubySize + 2;
377+
final rubySize = context.style.fontSize.size / 2;
378+
final rubyYPos = rubySize + 4;
267379
element.nodes.forEach((c) {
268380
if (c.nodeType == dom.Node.TEXT_NODE) {
269381
textNode = c;
@@ -301,6 +413,26 @@ class RubyElement extends ReplacedElement {
301413
}
302414
}
303415

416+
class RubyElementInfo {
417+
List<BaseTextSegment> baseTextSegments;
418+
List<AnnotationSegment> annotationSegments;
419+
420+
RubyElementInfo() {
421+
baseTextSegments = List<BaseTextSegment>();
422+
annotationSegments = List<AnnotationSegment>();
423+
}
424+
}
425+
426+
class BaseTextSegment {
427+
List<BaseTextSegment> subSegments;
428+
List<dom.Node> baseText;
429+
}
430+
431+
class AnnotationSegment {
432+
List<dom.Node> annotation;
433+
BaseTextSegment segment;
434+
}
435+
304436
ReplacedElement parseReplacedElement(dom.Element element) {
305437
switch (element.localName) {
306438
case "audio":

lib/style.dart

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,24 @@ class Style {
3636
///CSS attribute "`margin`"
3737
EdgeInsets margin;
3838

39+
/// CSS attribute "`ruby-align`"
40+
///
41+
/// inherited: yes,
42+
/// default: [RubyAlign.CENTER] (SPACE_AROUND currently unsupported),
43+
RubyAlign rubyAlign;
44+
45+
/// CSS attribute "`ruby-merge`"
46+
///
47+
/// inherited: yes,
48+
/// default: [RubyMerge.SEPARATE],
49+
RubyMerge rubyMerge;
50+
51+
/// CSS attribute "`ruby-position`"
52+
///
53+
/// inherited: yes,
54+
/// default: [RubyPosition.OVER],
55+
RubyPosition rubyPosition;
56+
3957
///CSS attribute "`text-decoration`" -
4058
TextDecoration textDecoration;
4159

@@ -71,6 +89,9 @@ class Style {
7189
this.listStyleType,
7290
this.padding,
7391
this.margin,
92+
this.rubyAlign,
93+
this.rubyMerge,
94+
this.rubyPosition,
7495
this.textDecoration,
7596
this.textDecorationStyle,
7697
this.verticalAlign,
@@ -120,6 +141,9 @@ class Style {
120141
//TODO merge EdgeInsets
121142
margin: other.margin,
122143
//TODO merge EdgeInsets
144+
rubyAlign: other.rubyAlign,
145+
rubyMerge: other.rubyMerge,
146+
rubyPosition: other.rubyPosition,
123147
textDecoration: other.textDecoration,
124148
textDecorationStyle: other.textDecorationStyle,
125149
verticalAlign: other.verticalAlign,
@@ -145,6 +169,9 @@ class Style {
145169
fontStyle: child.fontStyle ?? fontStyle,
146170
fontWeight: child.fontWeight ?? fontWeight,
147171
listStyleType: child.listStyleType ?? listStyleType,
172+
rubyAlign: child.rubyAlign ?? rubyAlign,
173+
rubyMerge: child.rubyMerge ?? rubyMerge,
174+
rubyPosition: child.rubyPosition ?? rubyPosition,
148175
whiteSpace: child.whiteSpace ?? whiteSpace,
149176
);
150177
}
@@ -161,6 +188,9 @@ class Style {
161188
ListStyleType listStyleType,
162189
EdgeInsets padding,
163190
EdgeInsets margin,
191+
RubyAlign rubyAlign,
192+
RubyMerge rubyMerge,
193+
RubyPosition rubyPosition,
164194
TextDecoration textDecoration,
165195
TextDecorationStyle textDecorationStyle,
166196
VerticalAlign verticalAlign,
@@ -187,6 +217,9 @@ class Style {
187217
listStyleType: listStyleType ?? this.listStyleType,
188218
padding: padding ?? this.padding,
189219
margin: margin ?? this.margin,
220+
rubyAlign: rubyAlign ?? this.rubyAlign,
221+
rubyMerge: rubyMerge ?? this.rubyMerge,
222+
rubyPosition: rubyPosition ?? this.rubyPosition,
190223
textDecoration: textDecoration ?? this.textDecoration,
191224
textDecorationStyle: textDecorationStyle ?? this.textDecorationStyle,
192225
verticalAlign: verticalAlign ?? this.verticalAlign,
@@ -218,6 +251,11 @@ enum Display {
218251
INLINE,
219252
INLINE_BLOCK,
220253
LIST_ITEM,
254+
RUBY,
255+
RUBY_BASE,
256+
RUBY_TEXT,
257+
RUBY_BASE_CONTAINER,
258+
RUBY_TEXT_CONTAINER,
221259
}
222260

223261
class FontSize {
@@ -251,6 +289,25 @@ enum ListStyleType {
251289
DECIMAL,
252290
}
253291

292+
enum RubyAlign {
293+
START,
294+
CENTER,
295+
//UNSUPPORTED: SPACE_BETWEEN,
296+
//UNSUPPORTED: SPACE_AROUND,
297+
}
298+
299+
enum RubyMerge {
300+
SEPARATE,
301+
COLLAPSE,
302+
//UNSUPPORTED: AUTO,
303+
}
304+
305+
enum RubyPosition {
306+
OVER,
307+
UNDER,
308+
INTER_CHARACTER,
309+
}
310+
254311
enum VerticalAlign {
255312
BASELINE,
256313
SUB,

0 commit comments

Comments
 (0)