-
Notifications
You must be signed in to change notification settings - Fork 0
/
textTransform.go
329 lines (274 loc) · 9.16 KB
/
textTransform.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
package htmlValidator
import (
"github.com/tdewolff/parse/v2"
"github.com/tdewolff/parse/v2/html"
"io"
)
type paragraphType byte
const (
pLeft paragraphType = 10
pRight paragraphType = 11
pCenter paragraphType = 12
pDef paragraphType = 20
pNone = 0
pWait = 1
)
type tagTransformObj struct {
begin string // Замена открывающего тега
end string // Замена закрывающего тега
}
type replaceTagParagraphObj struct {
def tagTransformObj //Абзац по умолчанию
replaceLeft tagTransformObj //Абзац по левому краю
replaceRight tagTransformObj //Абзац по правому краю
replaceCenter tagTransformObj //Абзац по центру
}
type TextTransformObj struct {
replaceTagParagraph replaceTagParagraphObj
replaceTagDelimiter string
replaceTagBold tagTransformObj
replaceTagItalic tagTransformObj
replaceTagUnderline tagTransformObj
replaceTagLineThrough tagTransformObj
replaceTagQuote tagTransformObj
replaceTagSubScript tagTransformObj
replaceTagSuperScript tagTransformObj
}
/* Конструктор класса транчформации текстового блока */
func TextTransform() TextTransformObj {
obj := TextTransformObj{}
return obj
}
//###################################################################//
// AddParagraph Установка замены для параграфа
func (obj *TextTransformObj) AddParagraph(begin string, end string) *TextTransformObj {
obj.replaceTagParagraph.def.begin = begin
obj.replaceTagParagraph.def.end = end
if obj.replaceTagParagraph.replaceLeft.begin == "" {
obj.AddParagraphLeft(begin, end)
}
if obj.replaceTagParagraph.replaceRight.begin == "" {
obj.AddParagraphRight(begin, end)
}
if obj.replaceTagParagraph.replaceCenter.begin == "" {
obj.AddParagraphCenter(begin, end)
}
return obj
}
// AddParagraphLeft Установка замены для параграфа с позиционированием по левому краю
func (obj *TextTransformObj) AddParagraphLeft(begin string, end string) *TextTransformObj {
obj.replaceTagParagraph.replaceLeft.begin = begin
obj.replaceTagParagraph.replaceLeft.end = end
return obj
}
// AddParagraphRight Установка замены для параграфа с позиционированием по правому краю
func (obj *TextTransformObj) AddParagraphRight(begin string, end string) *TextTransformObj {
obj.replaceTagParagraph.replaceRight.begin = begin
obj.replaceTagParagraph.replaceRight.end = end
return obj
}
// AddParagraphCenter Установка замены для параграфа с позиционированием по центру
func (obj *TextTransformObj) AddParagraphCenter(begin string, end string) *TextTransformObj {
obj.replaceTagParagraph.replaceCenter.begin = begin
obj.replaceTagParagraph.replaceCenter.end = end
return obj
}
//####//
// AddDelimiter Установка замены тега разделителя
func (obj *TextTransformObj) AddDelimiter(delimiter string) *TextTransformObj {
obj.replaceTagDelimiter = delimiter
return obj
}
//####//
// AddTagBold Установка замены для тега стиля `жирный`
func (obj *TextTransformObj) AddTagBold(begin string, end string) *TextTransformObj {
obj.replaceTagBold.begin = begin
obj.replaceTagBold.end = end
return obj
}
// AddTagItalic Установка замены для тега стиля `курсив`
func (obj *TextTransformObj) AddTagItalic(begin string, end string) *TextTransformObj {
obj.replaceTagItalic.begin = begin
obj.replaceTagItalic.end = end
return obj
}
// AddTagUnderline Установка замены для тега стиля `подчеркнутый`
func (obj *TextTransformObj) AddTagUnderline(begin string, end string) *TextTransformObj {
obj.replaceTagUnderline.begin = begin
obj.replaceTagUnderline.end = end
return obj
}
// AddTagLineThrough Установка замены для тега стиля `зачеркнутый`
func (obj *TextTransformObj) AddTagLineThrough(begin string, end string) *TextTransformObj {
obj.replaceTagLineThrough.begin = begin
obj.replaceTagLineThrough.end = end
return obj
}
// AddTagQuote Установка замены для тега стиля `цитата`
func (obj *TextTransformObj) AddTagQuote(begin string, end string) *TextTransformObj {
obj.replaceTagQuote.begin = begin
obj.replaceTagQuote.end = end
return obj
}
// AddTagSubScript Установка замены для тега стиля `мелкий внизу`
func (obj *TextTransformObj) AddTagSubScript(begin string, end string) *TextTransformObj {
obj.replaceTagSubScript.begin = begin
obj.replaceTagSubScript.end = end
return obj
}
// AddTagSuperScript Установка замены для тега стиля `мелкий вверху`
func (obj *TextTransformObj) AddTagSuperScript(begin string, end string) *TextTransformObj {
obj.replaceTagSuperScript.begin = begin
obj.replaceTagSuperScript.end = end
return obj
}
//###################################################################//
// валидация и подмена тега
func (obj *TextTransformObj) tagReplace(data []byte, isBegin bool) (tag string, isValid bool, isParagraph paragraphType) {
nameTag := string(data)
validTag := func() string {
switch nameTag {
case TagDelimiter:
return obj.replaceTagDelimiter
case TagBold:
if isBegin {
return obj.replaceTagBold.begin
} else {
return obj.replaceTagBold.end
}
case TagItalic:
if isBegin {
return obj.replaceTagItalic.begin
} else {
return obj.replaceTagItalic.end
}
case TagUnderline:
if isBegin {
return obj.replaceTagUnderline.begin
} else {
return obj.replaceTagUnderline.end
}
case TagLineThrough:
if isBegin {
return obj.replaceTagLineThrough.begin
} else {
return obj.replaceTagLineThrough.end
}
case TagQuote:
if isBegin {
return obj.replaceTagQuote.begin
} else {
return obj.replaceTagQuote.end
}
case TagSubScript:
if isBegin {
return obj.replaceTagSubScript.begin
} else {
return obj.replaceTagSubScript.end
}
case TagSuperScript:
if isBegin {
return obj.replaceTagSuperScript.begin
} else {
return obj.replaceTagSuperScript.end
}
}
return tag
}
switch nameTag {
case TagParagraph:
return "", true, pWait
case TagDelimiter, TagBold, TagItalic, TagUnderline, TagLineThrough, TagQuote, TagSubScript, TagSuperScript:
return validTag(), true, pNone
}
return "", false, pNone
}
// валидация параграфа
func (obj *TextTransformObj) paragraphReplace(key []byte) (isParagraph paragraphType) {
attr := string(key)
switch attr {
case AttrLeft:
return pLeft
case AttrRight:
return pRight
case AttrCenter:
return pCenter
}
return pDef
}
// подмена параграфа
func (obj *TextTransformObj) paragraphPrint(types paragraphType, isBegin bool) string {
switch types {
case pDef, pWait:
if isBegin {
return obj.replaceTagParagraph.def.begin
} else {
return obj.replaceTagParagraph.def.end
}
case pLeft:
if isBegin {
return obj.replaceTagParagraph.replaceLeft.begin
} else {
return obj.replaceTagParagraph.replaceLeft.end
}
case pRight:
if isBegin {
return obj.replaceTagParagraph.replaceRight.begin
} else {
return obj.replaceTagParagraph.replaceRight.end
}
case pCenter:
if isBegin {
return obj.replaceTagParagraph.replaceCenter.begin
} else {
return obj.replaceTagParagraph.replaceCenter.end
}
}
return ""
}
//.//
/* Трансормация входного html-текста согласно параметрам */
func (obj *TextTransformObj) Transform(htmlText io.Reader) (retText string) {
parser := html.NewLexer(parse.NewInput(htmlText))
var waitParagraph paragraphType = pNone
for {
typeToken, data := parser.Next()
switch typeToken {
case html.StartTagCloseToken, html.StartTagVoidToken:
continue
case html.AttributeToken:
if waitParagraph != pNone { //обрабатываем только ожидающие атрибуты
waitParagraph = obj.paragraphReplace(parser.AttrKey())
retText += obj.paragraphPrint(waitParagraph, true)
}
case html.StartTagToken:
tag, isValid, isParagraph := obj.tagReplace(parser.AttrKey(), true)
if isValid { //если тег валиден
if isParagraph == pNone { //и если это не параграф
retText += tag
} else { //если таки параграф
waitParagraph = pWait
}
}
case html.EndTagToken:
tag, isValid, isParagraph := obj.tagReplace(parser.AttrKey(), false)
if isValid { //если тег валиден
if isParagraph == pNone {
retText += tag //и если это не параграф
} else {
retText += obj.paragraphPrint(waitParagraph, false)
waitParagraph = pNone
}
}
case html.TextToken:
if waitParagraph == pWait { //если параграф поймало но без типов
retText += obj.paragraphPrint(waitParagraph, true)
}
retText += string(data)
case html.ErrorToken:
return retText
default:
continue
}
}
}