-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathEditorLineContent.js
106 lines (88 loc) · 3.18 KB
/
EditorLineContent.js
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
import _ from 'lodash'
import React from 'react/addons'
import classNames from 'classnames'
import { ATTR, hasAttributeFor } from '../core/attributes'
import { linesEq } from '../core/EditorCommon'
import ReactUtils from '../core/ReactUtils'
import TextFontMetrics from '../core/TextFontMetrics'
const T = React.PropTypes
const nbsp = String.fromCharCode(160)
export default React.createClass({
propTypes: {
line: T.object,
fontSize: T.number.isRequired,
renderOptimizations: T.bool
},
getDefaultProps() {
return {
renderOptimizations: true
}
},
shouldComponentUpdate(nextProps) {
if(!nextProps.renderOptimizations) {
return true
}
// for better performance make sure objects are immutable so that we can do reference equality checks
let propsEqual = this.props.fontSize === nextProps.fontSize
&& ReactUtils.deepEquals(this.props.line, nextProps.line, linesEq)
return !propsEqual
},
_renderStyledText(id, text, attributes) {
let hasAttribute = hasAttributeFor(attributes)
// vertical alignment
let superscript = hasAttribute(ATTR.SUPERSCRIPT)
let subscript = hasAttribute(ATTR.SUBSCRIPT)
let verticalAlign = classNames({
super: superscript,
sub: subscript,
baseline: !(superscript || subscript)
})
// font size, weight, style
let fontSize = TextFontMetrics.fontSizeFromAttributes(this.props.fontSize, attributes)
let fontWeight = hasAttribute(ATTR.BOLD) ? 'bold' : 'normal'
let fontStyle = hasAttribute(ATTR.ITALIC) ? 'italic' : 'normal'
// text-decoration
let underline = hasAttribute(ATTR.UNDERLINE)
let strikethrough = hasAttribute(ATTR.STRIKETHROUGH)
let textDecoration = classNames({
none: !(underline || strikethrough),
underline: underline,
'line-through': strikethrough
})
let style = {
color: '#000000',
backgroundColor: 'transparent',
fontFamily: 'Open Sans', // TODO test other fonts, make the font selectable
fontSize: fontSize,
fontWeight: fontWeight,
fontStyle: fontStyle,
fontVariant: 'normal',
textDecoration: textDecoration,
verticalAlign: verticalAlign
}
return (
<span style={style} key={id}>{text}</span>
)
},
_splitIntoChunks(line) {
if(!line) return []
return line.chunks.map(chunk => {
let chars = line.chars.slice(chunk.start, chunk.end)
return this._renderStyledText(chars[0].id, chars.map(c => c.char === ' ' ? nbsp : c.char).join(''), chunk.attributes)
})
},
render() {
//console.trace('render EditorLine')
let line = this.props.line
let blockHeight = 10000
let blockTop = TextFontMetrics.top(this.props.fontSize) - blockHeight
return (
<div className="ritzy-internal-text-lineview-content text-lineview-content" style={{marginLeft: 0, paddingTop: 0}}>
<span style={{display: 'inline-block', height: blockHeight}}></span>
<span style={{display: 'inline-block', position: 'relative', top: blockTop}}>
<span key="text" className="ritzy-internal-editor-inline-block ritzy-internal-text-lineview-text-block">{this._splitIntoChunks(line)}</span>
</span>
</div>
)
}
})