Skip to content

Commit 6b526a7

Browse files
committed
Merge pull request #35 from mjmlio/issue-33-32
Add Background color on mjColumn & width on mjBody
2 parents cff6f86 + e16956e commit 6b526a7

File tree

7 files changed

+103
-38
lines changed

7 files changed

+103
-38
lines changed

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mjml",
3-
"version": "1.0.4",
3+
"version": "1.1.0",
44
"description": "MJML: the only framework that makes responsive-email easy",
55
"main": "./lib/mjml",
66
"scripts": {
@@ -61,16 +61,16 @@
6161
"homepage": "https://github.com/mjmlio/mjml",
6262
"devDependencies": {
6363
"babel-cli": "^6.4.3",
64+
"babel-eslint": "^4.1.8",
6465
"babel-plugin-transform-decorators-legacy": "^1.3.4",
6566
"babel-preset-es2015": "^6.3.13",
6667
"babel-preset-react": "^6.3.13",
6768
"babel-preset-stage-0": "^6.3.13",
6869
"babel-register": "^6.4.3",
69-
"eslint-plugin-react": "^3.15.0",
70-
"eslint": "^1.10.3",
7170
"chai": "^3.4.1",
72-
"mocha": "^2.3.4",
73-
"babel-eslint": "^4.1.8"
71+
"eslint": "^1.10.3",
72+
"eslint-plugin-react": "^3.15.0",
73+
"mocha": "^2.3.4"
7474
},
7575
"dependencies": {
7676
"commander": "^2.9.0",

src/components/Body.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import MJMLElement from './decorators/MJMLElement'
22
import React, { Component } from 'react'
3+
import { widthParser } from '../helpers/mjAttribute'
34

45
/**
56
* This is the starting point of your email. It is a unique and mandatory component. It corresponds to the HTML <body> tag.
67
*/
7-
@MJMLElement
8+
@MJMLElement({
9+
tagName: 'mj-body',
10+
attributes: {
11+
'width': '600'
12+
},
13+
inheritedAttributes: [
14+
'width'
15+
]
16+
})
817
class Body extends Component {
918

1019
getStyles() {
@@ -20,11 +29,15 @@ class Body extends Component {
2029

2130
render() {
2231
const { renderWrappedOutlookChildren, mjAttribute } = this.props
32+
const { width } = widthParser(mjAttribute('width'))
2333

2434
this.styles = this.getStyles()
2535

2636
return (
27-
<div className="mj-body" style={this.styles.div} data-background-color={mjAttribute('background-color')}>
37+
<div className="mj-body"
38+
style={this.styles.div}
39+
data-background-color={mjAttribute('background-color')}
40+
data-width={width}>
2841
{renderWrappedOutlookChildren()}
2942
</div>
3043
)

src/components/Column.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ class Column extends Component {
3030
verticalAlign: mjAttribute('vertical-align'),
3131
fontSize: "13",
3232
textAlign: "left",
33+
width: "100%",
3334
minWidth: mjAttribute('width')
35+
},
36+
table: {
37+
background: mjAttribute('background-color')
3438
}
3539
})
3640
}
@@ -64,8 +68,7 @@ class Column extends Component {
6468

6569
return (
6670
<div style={this.styles.div} className={mjColumnClass} aria-labelledby={mjColumnClass} data-column-width={parseInt(width)}>
67-
<table
68-
width="100%">
71+
<table style={this.styles.table} data-legacy-background={mjAttribute('background')} width="100%">
6972
<tbody>
7073
{renderChildren()}
7174
</tbody>

src/components/Image.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class Image extends Component {
3131
border: 'none',
3232
display: 'block',
3333
outline: 'none',
34-
textDecoration: 'none'
34+
textDecoration: 'none',
35+
width: "100%"
3536
}
3637
};
3738

src/components/Section.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ class Section extends Component {
1818

1919
static baseStyles = {
2020
div: {
21-
margin: "0 auto",
22-
maxWidth: "600px"
21+
margin: "0 auto"
2322
},
2423
table: {
2524
width: "100%",
@@ -43,29 +42,38 @@ class Section extends Component {
4342
const background = mjAttribute('background-url') ? {
4443
background: `url(${mjAttribute('background-url')}) top center / ${mjAttribute('background-size') || ''} ${mjAttribute('background-repeat') || ''}`
4544
} : {
46-
backgroundColor: mjAttribute('background-color')
45+
background: mjAttribute('background-color')
4746
}
4847

4948
return _.merge({}, this.constructor.baseStyles, {
50-
div: this.isFullWidth() ? {} : _.cloneDeep(background),
51-
table: this.isFullWidth() ? {} : _.cloneDeep(background),
52-
tableFullwidth: this.isFullWidth() ? _.cloneDeep(background) : {},
5349
td: {
5450
fontSize: 0,
5551
verticalAlign: mjAttribute('vertical-align'),
5652
paddingTop: mjAttribute('padding-top'),
5753
paddingBottom: mjAttribute('padding-bottom'),
5854
paddingRight: mjAttribute('padding-right'),
5955
paddingLeft: mjAttribute('padding-left')
56+
},
57+
div: {
58+
maxWidth: mjAttribute('parentWidth')
6059
}
60+
}, {
61+
div: this.isFullWidth() ? {} : _.cloneDeep(background),
62+
table: this.isFullWidth() ? {} : _.cloneDeep(background),
63+
tableFullwidth: this.isFullWidth() ? _.cloneDeep(background) : {}
6164
})
6265
}
6366

6467
renderFullWidthSection() {
6568
const { mjAttribute } = this.props
6669

6770
return (
68-
<table data-legacy-background={mjAttribute('background-url')}border="0" cellPadding="0" cellSpacing="0" style={_.merge({}, this.styles.tableFullwidth, this.styles.table)}>
71+
<table data-legacy-background={mjAttribute('background-url')}
72+
border="0"
73+
cellPadding="0"
74+
cellSpacing="0"
75+
data-width={mjAttribute('parentWidth')}
76+
style={_.merge({}, this.styles.tableFullwidth, this.styles.table)}>
6977
<tbody>
7078
<tr>
7179
<td>
@@ -83,7 +91,15 @@ class Section extends Component {
8391

8492
return (
8593
<div style={this.styles.div}>
86-
<table className="outlook-background-fix-open" data-url={mjAttribute('background-url') || ''} data-legacy-background={fullWidth ? undefined : mjAttribute('background-url')} border="0" cellPadding="0" cellSpacing="0" data-legacy-align="center" style={this.styles.table}>
94+
<table className="outlook-background-fix-open"
95+
data-url={mjAttribute('background-url') || ''}
96+
data-legacy-background={fullWidth ? undefined : mjAttribute('background-url')}
97+
border="0"
98+
cellPadding="0"
99+
cellSpacing="0"
100+
data-legacy-align="center"
101+
data-width={mjAttribute('parentWidth')}
102+
style={this.styles.table}>
87103
<tbody>
88104
<tr>
89105
<td style={this.styles.td}>

src/components/decorators/MJMLElement.js

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import _ from 'lodash'
55
import { widthParser } from "../../helpers/mjAttribute"
66
import { UnknownMJMLElement } from '../../Error'
77

8-
const getElementWidth = (element, siblings) => {
8+
const getElementWidth = ({element, siblings, parentWidth}) => {
99
const { elem } = element.props
1010
let { width } = element.props
1111

@@ -14,14 +14,14 @@ const getElementWidth = (element, siblings) => {
1414
}
1515

1616
if (width == undefined) {
17-
return 600 / siblings
17+
return parentWidth / siblings
1818
}
1919

2020
const { width: parsedWidth, unit } = widthParser(width)
2121

2222
switch(unit) {
2323
case '%':
24-
return parsedWidth * 6 // * 600 / 100
24+
return parsedWidth * parentWidth / 100
2525

2626
case 'px':
2727
default:
@@ -39,7 +39,8 @@ function createComponent(ComposedComponent, defaultAttributes) {
3939
this.state = Immutable.fromJS({
4040
elem: _.merge({
4141
children: [],
42-
attributes: {}
42+
attributes: {},
43+
inheritedAttributes: []
4344
}, defaultAttributes)
4445
})
4546

@@ -62,49 +63,73 @@ function createComponent(ComposedComponent, defaultAttributes) {
6263
return this.state.getIn(['elem', 'tagName']).substr(3)
6364
}
6465

66+
inheritedAttributes() {
67+
return _.reduce(this.state.getIn(['elem', 'inheritedAttributes']).toJS(), (result, value) => {
68+
result[value] = this.mjAttribute(value)
69+
return result
70+
}, {})
71+
}
72+
73+
isInheritedAttributes(name) {
74+
return _.indexOf(this.state.getIn(['elem', 'inheritedAttributes']).toJS(), name) != -1
75+
}
76+
6577
siblingsCount() {
6678
const children = this.state.getIn(['elem', 'children'])
6779

6880
return this.hasReactChildren() ? React.Children.count(children) : this.state.getIn(['elem', 'children']).size
6981
}
7082

83+
getWidth() {
84+
return this.mjAttribute('rawPxWidth') || this.mjAttribute('width')
85+
}
86+
7187
childDefaultProps(id) {
7288
return {
7389
id,
7490
key: id,
7591
color: this.mjAttribute('color'),
76-
parentWidth: this.mjAttribute('rawPxWidth'),
92+
parentWidth: this.getWidth(),
7793
verticalAlign: this.mjAttribute('vertical-align'),
7894
sibling: this.siblingsCount()
7995
}
8096
}
8197

8298
renderWrappedOutlookChildren() {
8399
let elements = this.renderChildren()
84-
const wrappedElements = []
85-
const prefix = `mj-${this.mjElementName()}-outlook`
86100

87101
if (elements && elements.get) {
88102
// had to break immutable here :(
89103
elements = elements.toArray()
90104
}
91105

92-
if (elements.length == 0) {
106+
const wrappedElements = []
107+
const prefix = `mj-${this.mjElementName()}-outlook`
108+
const parentWidth = this.getWidth()
109+
const siblings = elements.length
110+
const elementsWidth = elements.map((element) => {
111+
if (this.isInheritedAttributes('width')) {
112+
return parentWidth
113+
}
114+
115+
return getElementWidth({element, siblings, parentWidth})
116+
})
117+
118+
if (siblings == 0) {
93119
return []
94120
}
95121

96122
elements.forEach((element, n) => {
97-
const width = getElementWidth(element, elements.length)
98-
wrappedElements.push(React.cloneElement(element, {rawPxWidth: width}))
123+
const width = elementsWidth[n]
99124

100-
if ( n < elements.length - 1 ) {
101-
const nextWidth = getElementWidth(elements[n+1], elements.length)
125+
wrappedElements.push(React.cloneElement(element, _.merge({rawPxWidth: width}, this.inheritedAttributes())))
102126

103-
wrappedElements.push(<div key={`outlook-${n}`}className={`${prefix}-line`} data-width={nextWidth}/>)
127+
if ( n < elements.length - 1 ) {
128+
wrappedElements.push(<div key={`outlook-${n}`}className={`${prefix}-line`} data-width={elementsWidth[n+1]}/>)
104129
}
105130
})
106131

107-
const outlookOpenTag = <div key="outlook-open" className={`${prefix}-open`} data-width={getElementWidth(elements[0], elements.length)} />
132+
const outlookOpenTag = <div key="outlook-open" className={`${prefix}-open`} data-width={elementsWidth[0]} />
108133
const outlookCloseTag = <div key="outlook-close" className={`${prefix}-close`} />
109134

110135
return [outlookOpenTag].concat(wrappedElements, [outlookCloseTag])

src/mjml2html.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,24 @@ const internals = {
8888
},
8989

9090
fixOutlookLayout($) {
91+
const bodyWidth = $('.mj-body').data('width')
92+
$('.mj-body').removeAttr('data-width')
93+
9194
$(".outlook-background-fix-open").each(function() {
9295
const url = $(this).data('url')
93-
$(this).removeClass('outlook-background-fix-open').removeAttr('data-url')
96+
const width = $(this).data('width')
97+
98+
$(this).removeClass('outlook-background-fix-open')
99+
.removeAttr('data-url')
100+
.removeAttr('data-width')
94101

95102
if (!url) {
96103
return;
97104
}
98105

99106
$(this).before(`
100107
<!--[if gte mso 9]>
101-
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:600px;">
108+
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:${width}px;">
102109
<v:fill origin="0.5, 0" position="0.5,0" type="tile" src="${url}" />
103110
<v:textbox style="mso-fit-shape-to-text:true" inset="0,0,0,0">
104111
<![endif]-->`)
@@ -113,7 +120,7 @@ const internals = {
113120

114121
$(".mj-body-outlook-open").each(function() {
115122
$(this).replaceWith(`<!--[if mso]>
116-
<table border="0" cellpadding="0" cellspacing="0" width="600" align="center" style="width:600px;"><tr><td>
123+
<table border="0" cellpadding="0" cellspacing="0" width="${bodyWidth}" align="center" style="width:${bodyWidth}px;"><tr><td>
117124
<![endif]-->`)
118125
})
119126

@@ -122,7 +129,7 @@ const internals = {
122129
</td></tr></table>
123130
<![endif]-->
124131
<!--[if mso]>
125-
<table border="0" cellpadding="0" cellspacing="0" width="600" align="center" style="width:600px;"><tr><td>
132+
<table border="0" cellpadding="0" cellspacing="0" width="${bodyWidth}" align="center" style="width:${bodyWidth}px;"><tr><td>
126133
<![endif]-->`)
127134
})
128135

@@ -134,13 +141,13 @@ const internals = {
134141

135142
$(".mj-section-outlook-open").each(function() {
136143
$(this).replaceWith(`<!--[if mso]>
137-
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:${$(this).data('width')}px;">
144+
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:${parseInt($(this).data('width'))}px;">
138145
<![endif]-->`)
139146
})
140147

141148
$(".mj-section-outlook-line").each(function() {
142149
$(this).replaceWith(`<!--[if mso]>
143-
</td><td style="width:${$(this).data('width')}px;">
150+
</td><td style="width:${parseInt($(this).data('width'))}px;">
144151
<![endif]-->`)
145152
})
146153

0 commit comments

Comments
 (0)