Skip to content

Commit 3a795c3

Browse files
committed
refactoring html_view and code_block
1 parent 8812a56 commit 3a795c3

File tree

7 files changed

+426
-197
lines changed

7 files changed

+426
-197
lines changed

lib/habr_storage/habr_storage.dart

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import 'package:flutter/foundation.dart';
22
import 'package:habr_app/habr/habr.dart';
33
import 'package:habr_app/models/models.dart';
44
import 'package:habr_app/habr_storage/image_storage.dart';
5+
import 'package:habr_app/utils/images_finder.dart';
56
import 'package:habr_app/utils/workers/hasher.dart';
6-
import 'package:habr_app/utils/html_to_json.dart';
77
import 'package:habr_app/utils/log.dart';
88
import 'package:either_dart/either.dart';
99
import 'package:habr_app/app_error.dart';
@@ -166,7 +166,7 @@ class HabrStorage {
166166
if (eitherPost.isLeft) return;
167167
final post = eitherPost.right;
168168
await cache.cachedPostDao.deletePost(articleId);
169-
final urls = await compute(_getImageUrlsFromHtml, post.body);
169+
final urls = await compute(getImageUrlsFromHtml, post.body);
170170

171171
await Future.wait(urls.map((url) => imgStore.deleteImage(url)));
172172
}
@@ -183,27 +183,10 @@ class HabrStorage {
183183
insertTime: DateTime.now(),
184184
));
185185
logInfo('parse urls from html');
186-
final urls = await compute(_getImageUrlsFromHtml, post.body);
186+
final urls = await compute(getImageUrlsFromHtml, post.body);
187187
final cachedPaths =
188188
await Future.wait(urls.map((url) => imgStore.saveImage(url)));
189189
final allImagesCached = cachedPaths.every((element) => element.isRight);
190190
logInfo(allImagesCached ? "all images cached" : "not all images cached");
191191
}
192192
}
193-
194-
List<String> _getImageUrlsFromHtml(String html) {
195-
final parsedHtml = htmlAsParsedJson(html);
196-
final urls = _getImagesFromParsedPost(parsedHtml).toList();
197-
return urls;
198-
}
199-
200-
Iterable<String> _getImagesFromParsedPost(Map<String, dynamic> element) sync* {
201-
if (element['type'] == 'image') {
202-
yield element['src'];
203-
} else if (element.containsKey('child')) {
204-
yield* _getImagesFromParsedPost(element['child']);
205-
} else if (element.containsKey('children')) {
206-
for (final child in element['children'])
207-
yield* _getImagesFromParsedPost(child);
208-
}
209-
}
Lines changed: 117 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,140 @@
11
import 'text_mode.dart';
22
export 'text_mode.dart';
33

4-
Map<String, dynamic> buildWithChildren(String type, List<dynamic> children) =>
5-
{'type': type, 'children': children};
4+
abstract class Node {
5+
String get type;
6+
}
67

7-
Map<String, dynamic> buildWithChild(String type, dynamic child) =>
8-
{'type': type, 'child': child};
8+
abstract class NodeChild extends Node {
9+
Node child;
10+
}
911

10-
enum ListType { unordered, ordered }
12+
abstract class NodeChildren extends Node {
13+
List<Node> children;
14+
}
15+
16+
class Paragraph implements Node {
17+
List<Span> children;
18+
19+
Paragraph.empty() : children = [];
20+
21+
addSpan(Span span) {
22+
children.add(span);
23+
}
24+
25+
@override
26+
String get type => "paragraph";
27+
}
28+
29+
abstract class Span {}
1130

12-
Map<String, dynamic> buildDefaultParagraph() =>
13-
{'type': 'paragraph', 'children': []};
31+
class BlockSpan implements Span {
32+
Node child;
1433

15-
void addSpanToParagraph(p, span) {
16-
final pch = (p['children'] as List);
17-
pch.add(span);
34+
BlockSpan(this.child);
1835
}
1936

20-
Map<String, dynamic> buildTextParagraph(String text) => {
21-
'type': 'tp',
22-
'text': text,
23-
};
37+
class TextSpan implements Span {
38+
String text;
39+
List<String> modes;
2440

25-
Map<String, dynamic> buildTextSpan(String text,
26-
{List<TextMode> modes = const []}) =>
27-
{
28-
'type': 'span',
29-
'text': text,
30-
'mode': modes.map((mode) => mode.toString().substring('TextMode'.length + 1)).toList(),
31-
};
41+
TextSpan(this.text, {List<TextMode> modes = const []})
42+
: modes = modes
43+
.map((mode) => mode.toString().substring('TextMode'.length + 1))
44+
.toList();
45+
}
46+
47+
class LinkSpan implements Span {
48+
String text;
49+
String link;
3250

33-
Map<String, dynamic> buildHeadLine(String text, String headline) => {
34-
'type': 'hl',
35-
'text': text,
36-
'mode': headline,
37-
};
51+
LinkSpan(this.text, this.link);
52+
}
3853

39-
Map<String, dynamic> buildImage(String src) => {
40-
'type': 'image',
41-
'src': src,
42-
};
54+
class TextParagraph implements Node {
55+
String text;
4356

44-
Map<String, dynamic> buildCode(String text, List<String> language) =>
45-
{'type': 'code', 'text': text, 'language': language};
57+
TextParagraph(this.text);
4658

47-
void addCaption(image, String caption) {
48-
image['caption'] = caption;
59+
@override
60+
String get type => "text_paragraph";
4961
}
5062

51-
void addLink(image, String link) {
52-
image['link'] = link;
63+
class HeadLine implements Node {
64+
String text;
65+
String mode;
66+
67+
HeadLine(this.text, this.mode);
68+
69+
@override
70+
String get type => "headline";
5371
}
5472

55-
Map<String, dynamic> buildList(ListType listType, List<dynamic> children) =>
56-
buildWithChildren(
57-
listType.toString().substring('ListType'.length + 1) + '_list',
58-
children);
73+
class Image implements Node {
74+
String src;
75+
String caption;
5976

60-
Map<String, dynamic> buildDetails(String title, child) =>
61-
{'type': 'details', 'child': child, 'title': title};
77+
Image(this.src, {this.caption});
6278

63-
Map<String, dynamic> buildPre(dynamic child) => buildWithChild('pre', child);
79+
@override
80+
String get type => "image";
81+
}
82+
83+
class Code implements Node {
84+
String text;
85+
String language; // can be null
6486

65-
Map<String, dynamic> buildDiv(List<dynamic> children) =>
66-
buildWithChildren('div', children);
87+
Code(this.text, this.language);
6788

68-
Map<String, dynamic> buildBlockQuote(List<dynamic> children) =>
69-
buildWithChildren('blockquote', children);
89+
@override
90+
String get type => "code";
91+
}
92+
93+
enum ListType { unordered, ordered }
7094

71-
Map<String, dynamic> buildInlineLink(String text, String src) =>
72-
{'type': 'link_span', 'text': text, 'src': src};
95+
class BlockList implements NodeChildren {
96+
List<Node> children;
97+
ListType listType;
98+
99+
BlockList(this.listType, this.children);
100+
101+
@override
102+
String get type => "${listType}_list";
103+
}
104+
105+
class Details implements NodeChild {
106+
String title;
107+
Node child;
108+
109+
Details(this.title, this.child);
110+
111+
@override
112+
String get type => "details";
113+
}
114+
115+
class Scrollable implements NodeChild {
116+
Node child;
117+
118+
Scrollable(this.child);
119+
120+
@override
121+
String get type => "scrollable";
122+
}
123+
124+
class BlockColumn implements NodeChildren {
125+
List<Node> children;
126+
127+
BlockColumn(this.children);
128+
129+
@override
130+
String get type => "column";
131+
}
132+
133+
class BlockQuote implements NodeChild {
134+
Node child;
135+
136+
BlockQuote(this.child);
137+
138+
@override
139+
String get type => "quote";
140+
}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import 'dart:convert';
22
import 'package:html/parser.dart';
33
import 'transformer.dart';
4+
import 'element_builders.dart';
45

5-
Map<String, dynamic> htmlAsParsedJson(String input) {
6+
Node htmlAsParsedJson(String input) {
67
final doc = parse(input);
78
final block = prepareHtmlBlocElement(doc.body.children.first);
89
optimizeBlock(block);
910
return block;
1011
}
11-
12-
String htmlAsJson(String source) {
13-
return jsonEncode(htmlAsParsedJson(source));
14-
}

0 commit comments

Comments
 (0)