MailPoet Newsletters (New) - Version 3.0.0

Version Description

  • 2017-09-20 =
  • Official launch of the new MailPoet. :)
  • Improved: MailPoet 3 now works with other plugins that use a supported version of Twig templating engine. Thanks @supsysticcom;
  • Added: we now offer a free sending plan for 2000 subscribers or less. Thx MailPoet!
Download this release

Release Info

Developer wysija
Plugin Icon 128x128 MailPoet Newsletters (New)
Version 3.0.0
Comparing to
See all releases

Code changes from version 3.0.0-rc.2.0.3 to 3.0.0

Files changed (45) hide show
  1. assets/css/{admin.0df54f3d.css → admin.8b85810c.css} +14 -0
  2. assets/css/manifest.json +1 -1
  3. assets/js/{admin.d091b681.js → admin.ef421cc2.js} +3 -2
  4. assets/js/{admin_vendor.ee9853ec.js → admin_vendor.c1a3e332.js} +0 -0
  5. assets/js/{form_editor.c0e36e82.js → form_editor.00c531b6.js} +347 -204
  6. assets/js/{mailpoet.81b583ba.js → mailpoet.25f879a2.js} +68 -38
  7. assets/js/manifest.json +6 -6
  8. assets/js/{public.02e5f1af.js → public.5b18b937.js} +68 -38
  9. assets/js/{vendor.f4549608.js → vendor.2e3b215c.js} +1 -1
  10. lang/mailpoet-da_DK.mo +0 -0
  11. lang/mailpoet-de_DE.mo +0 -0
  12. lang/mailpoet-en_GB.mo +0 -0
  13. lang/mailpoet-es_ES.mo +0 -0
  14. lang/mailpoet-fa_IR.mo +0 -0
  15. lang/mailpoet-fr_CA.mo +0 -0
  16. lang/mailpoet-fr_FR.mo +0 -0
  17. lang/mailpoet-it_IT.mo +0 -0
  18. lang/mailpoet-ja.mo +0 -0
  19. lang/mailpoet-nl_NL.mo +0 -0
  20. lang/mailpoet-pl_PL.mo +0 -0
  21. lang/mailpoet-pt_BR.mo +0 -0
  22. lang/mailpoet-pt_PT.mo +0 -0
  23. lang/mailpoet-ru_RU.mo +0 -0
  24. lang/mailpoet-sv_SE.mo +0 -0
  25. lang/mailpoet-tr_TR.mo +0 -0
  26. lang/mailpoet.pot +152 -113
  27. lib/Config/RequirementsChecker.php +20 -3
  28. lib/Cron/CronHelper.php +33 -25
  29. lib/Cron/Daemon.php +1 -2
  30. lib/Helpscout/Beacon.php +3 -0
  31. lib/Segments/WP.php +16 -16
  32. lib/Twig/Analytics.php +1 -5
  33. lib/Twig/Assets.php +2 -11
  34. lib/Twig/Functions.php +1 -6
  35. lib/Twig/Handlebars.php +27 -22
  36. lib/Twig/Helpscout.php +1 -5
  37. lib/Twig/I18n.php +1 -4
  38. mailpoet.php +2 -2
  39. readme.txt +45 -20
  40. vendor/autoload.php +1 -1
  41. vendor/composer/autoload_real.php +7 -7
  42. vendor/composer/autoload_static.php +5 -5
  43. views/settings/mta.html +23 -18
  44. views/update.html +13 -3
  45. views/welcome.html +29 -7
assets/css/{admin.0df54f3d.css → admin.8b85810c.css} RENAMED
@@ -2908,6 +2908,17 @@ textarea.parsley-error {
2908
  margin-bottom: 2em;
2909
  margin-top: 2em;
2910
  }
 
 
 
 
 
 
 
 
 
 
 
2911
  #mailpoet_settings .mailpoet_success_item::before {
2912
  content: '✔ ';
2913
  }
@@ -3230,6 +3241,9 @@ textarea.parsley-error {
3230
  .mailpoet-about-wrap p.top-space-triple {
3231
  margin-top: 3em;
3232
  }
 
 
 
3233
  #logger {
3234
  width: 100%;
3235
  height: 300px;
2908
  margin-bottom: 2em;
2909
  margin-top: 2em;
2910
  }
2911
+ #mailpoet_settings .sending-free-plan-button {
2912
+ background: #ff5301;
2913
+ border-color: #e64c03;
2914
+ text-shadow: 0 -1px 1px #e64c03;
2915
+ -webkit-box-shadow: 0 1px 0 #e64c03;
2916
+ box-shadow: 0 1px 0 #e64c03;
2917
+ margin: 10px 0;
2918
+ }
2919
+ #mailpoet_settings .sending-free-plan-button strong {
2920
+ text-transform: uppercase;
2921
+ }
2922
  #mailpoet_settings .mailpoet_success_item::before {
2923
  content: '✔ ';
2924
  }
3241
  .mailpoet-about-wrap p.top-space-triple {
3242
  margin-top: 3em;
3243
  }
3244
+ .mailpoet-about-wrap p.mailpoet-top-text {
3245
+ margin-right: 0;
3246
+ }
3247
  #logger {
3248
  width: 100%;
3249
  height: 300px;
assets/css/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
  {
2
- "admin.css": "admin.0df54f3d.css",
3
  "importExport.css": "importExport.b3745466.css",
4
  "newsletter_editor.css": "newsletter_editor.55f2b9dc.css",
5
  "public.css": "public.cae357df.css",
1
  {
2
+ "admin.css": "admin.8b85810c.css",
3
  "importExport.css": "importExport.b3745466.css",
4
  "newsletter_editor.css": "newsletter_editor.55f2b9dc.css",
5
  "public.css": "public.cae357df.css",
assets/js/{admin.d091b681.js → admin.ef421cc2.js} RENAMED
@@ -35505,6 +35505,7 @@ webpackJsonp([0],[
35505
  }
35506
  return newField;
35507
  });
 
35508
  return React.createElement(
35509
  'div',
35510
  null,
@@ -35536,7 +35537,7 @@ webpackJsonp([0],[
35536
  type: 'button',
35537
  onClick: this.handleSend,
35538
  value: MailPoet.I18n.t('send')
35539
- }, this.getSendButtonOptions())),
35540
  ' ',
35541
  React.createElement('input', {
35542
  className: 'button button-secondary',
@@ -35554,7 +35555,7 @@ webpackJsonp([0],[
35554
  ),
35555
  '.'
35556
  ),
35557
- React.createElement(HelpTooltip, {
35558
  tooltip: MailPoet.I18n.t('helpTooltipSendEmail'),
35559
  tooltipId: 'helpTooltipSendEmail'
35560
  })
35505
  }
35506
  return newField;
35507
  });
35508
+ var sendButtonOptions = this.getSendButtonOptions();
35509
  return React.createElement(
35510
  'div',
35511
  null,
35537
  type: 'button',
35538
  onClick: this.handleSend,
35539
  value: MailPoet.I18n.t('send')
35540
+ }, sendButtonOptions)),
35541
  ' ',
35542
  React.createElement('input', {
35543
  className: 'button button-secondary',
35555
  ),
35556
  '.'
35557
  ),
35558
+ !isPaused && sendButtonOptions['disabled'] && sendButtonOptions['disabled'] === 'disabled' && React.createElement(HelpTooltip, {
35559
  tooltip: MailPoet.I18n.t('helpTooltipSendEmail'),
35560
  tooltipId: 'helpTooltipSendEmail'
35561
  })
assets/js/{admin_vendor.ee9853ec.js → admin_vendor.c1a3e332.js} RENAMED
File without changes
assets/js/{form_editor.c0e36e82.js → form_editor.00c531b6.js} RENAMED
@@ -1393,13 +1393,18 @@ webpackJsonp([2],{
1393
  }
1394
 
1395
  // Returns the value from the range [`from`; `to`] that satisfies
1396
- // `pred` and is closest to `from`. Assumes that at least `to` satisfies `pred`.
 
1397
  function findFirst(pred, from, to) {
 
 
 
1398
  for (;;) {
1399
- if (Math.abs(from - to) <= 1) { return pred(from) ? from : to }
1400
- var mid = Math.floor((from + to) / 2);
 
1401
  if (pred(mid)) { to = mid; }
1402
- else { from = mid; }
1403
  }
1404
  }
1405
 
@@ -2011,12 +2016,12 @@ webpackJsonp([2],{
2011
  // BIDI HELPERS
2012
 
2013
  function iterateBidiSections(order, from, to, f) {
2014
- if (!order) { return f(from, to, "ltr") }
2015
  var found = false;
2016
  for (var i = 0; i < order.length; ++i) {
2017
  var part = order[i];
2018
  if (part.from < to && part.to > from || from == to && part.to == from) {
2019
- f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
2020
  found = true;
2021
  }
2022
  }
@@ -2219,112 +2224,6 @@ webpackJsonp([2],{
2219
  return order
2220
  }
2221
 
2222
- function moveCharLogically(line, ch, dir) {
2223
- var target = skipExtendingChars(line.text, ch + dir, dir);
2224
- return target < 0 || target > line.text.length ? null : target
2225
- }
2226
-
2227
- function moveLogically(line, start, dir) {
2228
- var ch = moveCharLogically(line, start.ch, dir);
2229
- return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before")
2230
- }
2231
-
2232
- function endOfLine(visually, cm, lineObj, lineNo, dir) {
2233
- if (visually) {
2234
- var order = getOrder(lineObj, cm.doc.direction);
2235
- if (order) {
2236
- var part = dir < 0 ? lst(order) : order[0];
2237
- var moveInStorageOrder = (dir < 0) == (part.level == 1);
2238
- var sticky = moveInStorageOrder ? "after" : "before";
2239
- var ch;
2240
- // With a wrapped rtl chunk (possibly spanning multiple bidi parts),
2241
- // it could be that the last bidi part is not on the last visual line,
2242
- // since visual lines contain content order-consecutive chunks.
2243
- // Thus, in rtl, we are looking for the first (content-order) character
2244
- // in the rtl chunk that is on the last line (that is, the same line
2245
- // as the last (content-order) character).
2246
- if (part.level > 0) {
2247
- var prep = prepareMeasureForLine(cm, lineObj);
2248
- ch = dir < 0 ? lineObj.text.length - 1 : 0;
2249
- var targetTop = measureCharPrepared(cm, prep, ch).top;
2250
- ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
2251
- if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); }
2252
- } else { ch = dir < 0 ? part.to : part.from; }
2253
- return new Pos(lineNo, ch, sticky)
2254
- }
2255
- }
2256
- return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after")
2257
- }
2258
-
2259
- function moveVisually(cm, line, start, dir) {
2260
- var bidi = getOrder(line, cm.doc.direction);
2261
- if (!bidi) { return moveLogically(line, start, dir) }
2262
- if (start.ch >= line.text.length) {
2263
- start.ch = line.text.length;
2264
- start.sticky = "before";
2265
- } else if (start.ch <= 0) {
2266
- start.ch = 0;
2267
- start.sticky = "after";
2268
- }
2269
- var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos];
2270
- if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) {
2271
- // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines,
2272
- // nothing interesting happens.
2273
- return moveLogically(line, start, dir)
2274
- }
2275
-
2276
- var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); };
2277
- var prep;
2278
- var getWrappedLineExtent = function (ch) {
2279
- if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} }
2280
- prep = prep || prepareMeasureForLine(cm, line);
2281
- return wrappedLineExtentChar(cm, line, prep, ch)
2282
- };
2283
- var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch);
2284
-
2285
- if (cm.doc.direction == "rtl" || part.level == 1) {
2286
- var moveInStorageOrder = (part.level == 1) == (dir < 0);
2287
- var ch = mv(start, moveInStorageOrder ? 1 : -1);
2288
- if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) {
2289
- // Case 2: We move within an rtl part or in an rtl editor on the same visual line
2290
- var sticky = moveInStorageOrder ? "before" : "after";
2291
- return new Pos(start.line, ch, sticky)
2292
- }
2293
- }
2294
-
2295
- // Case 3: Could not move within this bidi part in this visual line, so leave
2296
- // the current bidi part
2297
-
2298
- var searchInVisualLine = function (partPos, dir, wrappedLineExtent) {
2299
- var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder
2300
- ? new Pos(start.line, mv(ch, 1), "before")
2301
- : new Pos(start.line, ch, "after"); };
2302
-
2303
- for (; partPos >= 0 && partPos < bidi.length; partPos += dir) {
2304
- var part = bidi[partPos];
2305
- var moveInStorageOrder = (dir > 0) == (part.level != 1);
2306
- var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1);
2307
- if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) }
2308
- ch = moveInStorageOrder ? part.from : mv(part.to, -1);
2309
- if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) }
2310
- }
2311
- };
2312
-
2313
- // Case 3a: Look for other bidi parts on the same visual line
2314
- var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent);
2315
- if (res) { return res }
2316
-
2317
- // Case 3b: Look for other bidi parts on the next visual line
2318
- var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1);
2319
- if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) {
2320
- res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh));
2321
- if (res) { return res }
2322
- }
2323
-
2324
- // Case 4: Nowhere to move
2325
- return null
2326
- }
2327
-
2328
  // EVENT HANDLING
2329
 
2330
  // Lightweight event framework. on/off also work on DOM nodes,
@@ -3835,15 +3734,22 @@ webpackJsonp([2],{
3835
  return window.pageYOffset || (document.documentElement || document.body).scrollTop
3836
  }
3837
 
 
 
 
 
 
 
 
3838
  // Converts a {top, bottom, left, right} box from line-local
3839
  // coordinates into another coordinate system. Context may be one of
3840
  // "line", "div" (display.lineDiv), "local"./null (editor), "window",
3841
  // or "page".
3842
  function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
3843
- if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) {
3844
- var size = widgetHeight(lineObj.widgets[i]);
3845
- rect.top += size; rect.bottom += size;
3846
- } } }
3847
  if (context == "line") { return rect }
3848
  if (!context) { context = "local"; }
3849
  var yOff = heightAtLine(lineObj);
@@ -3918,7 +3824,7 @@ webpackJsonp([2],{
3918
  if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") }
3919
 
3920
  function getBidi(ch, partPos, invert) {
3921
- var part = order[partPos], right = (part.level % 2) != 0;
3922
  return get(invert ? ch - 1 : ch, right != invert)
3923
  }
3924
  var partPos = getBidiPartAt(order, ch, sticky);
@@ -3976,77 +3882,146 @@ webpackJsonp([2],{
3976
  }
3977
 
3978
  function wrappedLineExtent(cm, lineObj, preparedMeasure, y) {
3979
- var measure = function (ch) { return intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line"); };
3980
  var end = lineObj.text.length;
3981
- var begin = findFirst(function (ch) { return measure(ch - 1).bottom <= y; }, end, 0);
3982
- end = findFirst(function (ch) { return measure(ch).top > y; }, begin, end);
3983
  return {begin: begin, end: end}
3984
  }
3985
 
3986
  function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) {
 
3987
  var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top;
3988
  return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop)
3989
  }
3990
 
 
 
 
 
 
 
3991
  function coordsCharInner(cm, lineObj, lineNo$$1, x, y) {
 
3992
  y -= heightAtLine(lineObj);
3993
- var begin = 0, end = lineObj.text.length;
3994
  var preparedMeasure = prepareMeasureForLine(cm, lineObj);
3995
- var pos;
 
 
 
 
3996
  var order = getOrder(lineObj, cm.doc.direction);
 
 
3997
  if (order) {
3998
- if (cm.options.lineWrapping) {
3999
- var assign;
4000
- ((assign = wrappedLineExtent(cm, lineObj, preparedMeasure, y), begin = assign.begin, end = assign.end, assign));
4001
- }
4002
- pos = new Pos(lineNo$$1, Math.floor(begin + (end - begin) / 2));
4003
- var beginLeft = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left;
4004
- var dir = beginLeft < x ? 1 : -1;
4005
- var prevDiff, diff = beginLeft - x, prevPos;
4006
- var steps = Math.ceil((end - begin) / 4);
4007
- outer: do {
4008
- prevDiff = diff;
4009
- prevPos = pos;
4010
- var i = 0;
4011
- for (; i < steps; ++i) {
4012
- var prevPos$1 = pos;
4013
- pos = moveVisually(cm, lineObj, pos, dir);
4014
- if (pos == null || pos.ch < begin || end <= (pos.sticky == "before" ? pos.ch - 1 : pos.ch)) {
4015
- pos = prevPos$1;
4016
- break outer
4017
- }
4018
- }
4019
- diff = cursorCoords(cm, pos, "line", lineObj, preparedMeasure).left - x;
4020
- if (steps > 1) {
4021
- var diff_change_per_step = Math.abs(diff - prevDiff) / steps;
4022
- steps = Math.min(steps, Math.ceil(Math.abs(diff) / diff_change_per_step));
4023
- dir = diff < 0 ? 1 : -1;
4024
- }
4025
- } while (diff != 0 && (steps > 1 || ((dir < 0) != (diff < 0) && (Math.abs(diff) <= Math.abs(prevDiff)))))
4026
- if (Math.abs(diff) > Math.abs(prevDiff)) {
4027
- if ((diff < 0) == (prevDiff < 0)) { throw new Error("Broke out of infinite loop in coordsCharInner") }
4028
- pos = prevPos;
4029
  }
 
 
 
 
 
 
 
 
 
 
 
4030
  } else {
4031
- var ch = findFirst(function (ch) {
4032
- var box = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), "line");
4033
- if (box.top > y) {
4034
- // For the cursor stickiness
4035
- end = Math.min(ch, end);
4036
- return true
4037
- }
4038
- else if (box.bottom <= y) { return false }
4039
- else if (box.left > x) { return true }
4040
- else if (box.right < x) { return false }
4041
- else { return (x - box.left < box.right - x) }
4042
- }, begin, end);
4043
- ch = skipExtendingChars(lineObj.text, ch, 1);
4044
- pos = new Pos(lineNo$$1, ch, ch == end ? "before" : "after");
4045
- }
4046
- var coords = cursorCoords(cm, pos, "line", lineObj, preparedMeasure);
4047
- if (y < coords.top || coords.bottom < y) { pos.outside = true; }
4048
- pos.xRel = x < coords.left ? -1 : (x > coords.right ? 1 : 0);
4049
- return pos
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4050
  }
4051
 
4052
  var measureText;
@@ -4172,12 +4147,14 @@ webpackJsonp([2],{
4172
  }
4173
 
4174
  function prepareSelection(cm, primary) {
 
 
4175
  var doc = cm.doc, result = {};
4176
  var curFragment = result.cursors = document.createDocumentFragment();
4177
  var selFragment = result.selection = document.createDocumentFragment();
4178
 
4179
  for (var i = 0; i < doc.sel.ranges.length; i++) {
4180
- if (primary === false && i == doc.sel.primIndex) { continue }
4181
  var range$$1 = doc.sel.ranges[i];
4182
  if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { continue }
4183
  var collapsed = range$$1.empty();
@@ -4208,6 +4185,8 @@ webpackJsonp([2],{
4208
  }
4209
  }
4210
 
 
 
4211
  // Draws the given range as a highlighted selection
4212
  function drawSelectionRange(cm, range$$1, output) {
4213
  var display = cm.display, doc = cm.doc;
@@ -4230,30 +4209,48 @@ webpackJsonp([2],{
4230
  return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
4231
  }
4232
 
4233
- iterateBidiSections(getOrder(lineObj, doc.direction), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) {
4234
- var leftPos = coords(from, "left"), rightPos, left, right;
4235
- if (from == to) {
4236
- rightPos = leftPos;
4237
- left = right = leftPos.left;
4238
- } else {
4239
- rightPos = coords(to - 1, "right");
4240
- if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
4241
- left = leftPos.left;
4242
- right = rightPos.right;
4243
- }
4244
- if (fromArg == null && from == 0) { left = leftSide; }
4245
- if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
4246
- add(left, leftPos.top, null, leftPos.bottom);
4247
- left = leftSide;
4248
- if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4249
  }
4250
- if (toArg == null && to == lineLen) { right = rightSide; }
4251
- if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
4252
- { start = leftPos; }
4253
- if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
4254
- { end = rightPos; }
4255
- if (left < leftSide + 1) { left = leftSide; }
4256
- add(left, rightPos.top, right - left, rightPos.bottom);
4257
  });
4258
  return {start: start, end: end}
4259
  }
@@ -4883,7 +4880,7 @@ webpackJsonp([2],{
4883
  }
4884
 
4885
  if (op.updatedDisplay || op.selectionChanged)
4886
- { op.preparedSelection = display.input.prepareSelection(op.focus); }
4887
  }
4888
 
4889
  function endOperation_W2(op) {
@@ -4896,7 +4893,7 @@ webpackJsonp([2],{
4896
  cm.display.maxLineChanged = false;
4897
  }
4898
 
4899
- var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus());
4900
  if (op.preparedSelection)
4901
  { cm.display.input.showSelection(op.preparedSelection, takeFocus); }
4902
  if (op.updatedDisplay || op.startHeight != cm.doc.height)
@@ -6496,7 +6493,8 @@ webpackJsonp([2],{
6496
 
6497
  function replaceRange(doc, code, from, to, origin) {
6498
  if (!to) { to = from; }
6499
- if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
 
6500
  if (typeof code == "string") { code = doc.splitLines(code); }
6501
  makeChange(doc, {from: from, to: to, text: code, origin: origin});
6502
  }
@@ -7857,6 +7855,112 @@ webpackJsonp([2],{
7857
  });
7858
  }
7859
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7860
  // Commands are parameter-less actions that can be performed on an
7861
  // editor, mostly used for keybindings.
7862
  var commands = {
@@ -8418,7 +8522,7 @@ webpackJsonp([2],{
8418
  anchor = maxPos(oldRange.to(), range$$1.head);
8419
  }
8420
  var ranges$1 = startSel.ranges.slice(0);
8421
- ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head);
8422
  setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse);
8423
  }
8424
  }
@@ -8470,13 +8574,52 @@ webpackJsonp([2],{
8470
  on(document, "mouseup", up);
8471
  }
8472
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8473
 
8474
  // Determines whether an event happened in the gutter, and fires the
8475
  // handlers for the corresponding event.
8476
  function gutterEvent(cm, e, type, prevent) {
8477
  var mX, mY;
8478
- try { mX = e.clientX; mY = e.clientY; }
8479
- catch(e) { return false }
 
 
 
 
 
8480
  if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
8481
  if (prevent) { e_preventDefault(e); }
8482
 
@@ -8814,7 +8957,7 @@ webpackJsonp([2],{
8814
  return dx * dx + dy * dy > 20 * 20
8815
  }
8816
  on(d.scroller, "touchstart", function (e) {
8817
- if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
8818
  d.input.ensurePolled();
8819
  clearTimeout(touchFinished);
8820
  var now = +new Date;
@@ -10598,7 +10741,7 @@ webpackJsonp([2],{
10598
 
10599
  addLegacyProps(CodeMirror$1);
10600
 
10601
- CodeMirror$1.version = "5.29.0";
10602
 
10603
  return CodeMirror$1;
10604
 
1393
  }
1394
 
1395
  // Returns the value from the range [`from`; `to`] that satisfies
1396
+ // `pred` and is closest to `from`. Assumes that at least `to`
1397
+ // satisfies `pred`. Supports `from` being greater than `to`.
1398
  function findFirst(pred, from, to) {
1399
+ // At any point we are certain `to` satisfies `pred`, don't know
1400
+ // whether `from` does.
1401
+ var dir = from > to ? -1 : 1;
1402
  for (;;) {
1403
+ if (from == to) { return from }
1404
+ var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF);
1405
+ if (mid == from) { return pred(mid) ? from : to }
1406
  if (pred(mid)) { to = mid; }
1407
+ else { from = mid + dir; }
1408
  }
1409
  }
1410
 
2016
  // BIDI HELPERS
2017
 
2018
  function iterateBidiSections(order, from, to, f) {
2019
+ if (!order) { return f(from, to, "ltr", 0) }
2020
  var found = false;
2021
  for (var i = 0; i < order.length; ++i) {
2022
  var part = order[i];
2023
  if (part.from < to && part.to > from || from == to && part.to == from) {
2024
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i);
2025
  found = true;
2026
  }
2027
  }
2224
  return order
2225
  }
2226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2227
  // EVENT HANDLING
2228
 
2229
  // Lightweight event framework. on/off also work on DOM nodes,
3734
  return window.pageYOffset || (document.documentElement || document.body).scrollTop
3735
  }
3736
 
3737
+ function widgetTopHeight(lineObj) {
3738
+ var height = 0;
3739
+ if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above)
3740
+ { height += widgetHeight(lineObj.widgets[i]); } } }
3741
+ return height
3742
+ }
3743
+
3744
  // Converts a {top, bottom, left, right} box from line-local
3745
  // coordinates into another coordinate system. Context may be one of
3746
  // "line", "div" (display.lineDiv), "local"./null (editor), "window",
3747
  // or "page".
3748
  function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
3749
+ if (!includeWidgets) {
3750
+ var height = widgetTopHeight(lineObj);
3751
+ rect.top += height; rect.bottom += height;
3752
+ }
3753
  if (context == "line") { return rect }
3754
  if (!context) { context = "local"; }
3755
  var yOff = heightAtLine(lineObj);
3824
  if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") }
3825
 
3826
  function getBidi(ch, partPos, invert) {
3827
+ var part = order[partPos], right = part.level == 1;
3828
  return get(invert ? ch - 1 : ch, right != invert)
3829
  }
3830
  var partPos = getBidiPartAt(order, ch, sticky);
3882
  }
3883
 
3884
  function wrappedLineExtent(cm, lineObj, preparedMeasure, y) {
3885
+ y -= widgetTopHeight(lineObj);
3886
  var end = lineObj.text.length;
3887
+ var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0);
3888
+ end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end);
3889
  return {begin: begin, end: end}
3890
  }
3891
 
3892
  function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) {
3893
+ if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
3894
  var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top;
3895
  return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop)
3896
  }
3897
 
3898
+ // Returns true if the given side of a box is after the given
3899
+ // coordinates, in top-to-bottom, left-to-right order.
3900
+ function boxIsAfter(box, x, y, left) {
3901
+ return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x
3902
+ }
3903
+
3904
  function coordsCharInner(cm, lineObj, lineNo$$1, x, y) {
3905
+ // Move y into line-local coordinate space
3906
  y -= heightAtLine(lineObj);
 
3907
  var preparedMeasure = prepareMeasureForLine(cm, lineObj);
3908
+ // When directly calling `measureCharPrepared`, we have to adjust
3909
+ // for the widgets at this line.
3910
+ var widgetHeight$$1 = widgetTopHeight(lineObj);
3911
+ var begin = 0, end = lineObj.text.length, ltr = true;
3912
+
3913
  var order = getOrder(lineObj, cm.doc.direction);
3914
+ // If the line isn't plain left-to-right text, first figure out
3915
+ // which bidi section the coordinates fall into.
3916
  if (order) {
3917
+ var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart)
3918
+ (cm, lineObj, lineNo$$1, preparedMeasure, order, x, y);
3919
+ ltr = part.level != 1;
3920
+ // The awkward -1 offsets are needed because findFirst (called
3921
+ // on these below) will treat its first bound as inclusive,
3922
+ // second as exclusive, but we want to actually address the
3923
+ // characters in the part's range
3924
+ begin = ltr ? part.from : part.to - 1;
3925
+ end = ltr ? part.to : part.from - 1;
3926
+ }
3927
+
3928
+ // A binary search to find the first character whose bounding box
3929
+ // starts after the coordinates. If we run across any whose box wrap
3930
+ // the coordinates, store that.
3931
+ var chAround = null, boxAround = null;
3932
+ var ch = findFirst(function (ch) {
3933
+ var box = measureCharPrepared(cm, preparedMeasure, ch);
3934
+ box.top += widgetHeight$$1; box.bottom += widgetHeight$$1;
3935
+ if (!boxIsAfter(box, x, y, false)) { return false }
3936
+ if (box.top <= y && box.left <= x) {
3937
+ chAround = ch;
3938
+ boxAround = box;
 
 
 
 
 
 
 
 
 
3939
  }
3940
+ return true
3941
+ }, begin, end);
3942
+
3943
+ var baseX, sticky, outside = false;
3944
+ // If a box around the coordinates was found, use that
3945
+ if (boxAround) {
3946
+ // Distinguish coordinates nearer to the left or right side of the box
3947
+ var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr;
3948
+ ch = chAround + (atStart ? 0 : 1);
3949
+ sticky = atStart ? "after" : "before";
3950
+ baseX = atLeft ? boxAround.left : boxAround.right;
3951
  } else {
3952
+ // (Adjust for extended bound, if necessary.)
3953
+ if (!ltr && (ch == end || ch == begin)) { ch++; }
3954
+ // To determine which side to associate with, get the box to the
3955
+ // left of the character and compare it's vertical position to the
3956
+ // coordinates
3957
+ sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" :
3958
+ (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight$$1 <= y) == ltr ?
3959
+ "after" : "before";
3960
+ // Now get accurate coordinates for this place, in order to get a
3961
+ // base X position
3962
+ var coords = cursorCoords(cm, Pos(lineNo$$1, ch, sticky), "line", lineObj, preparedMeasure);
3963
+ baseX = coords.left;
3964
+ outside = y < coords.top || y >= coords.bottom;
3965
+ }
3966
+
3967
+ ch = skipExtendingChars(lineObj.text, ch, 1);
3968
+ return PosWithInfo(lineNo$$1, ch, sticky, outside, x - baseX)
3969
+ }
3970
+
3971
+ function coordsBidiPart(cm, lineObj, lineNo$$1, preparedMeasure, order, x, y) {
3972
+ // Bidi parts are sorted left-to-right, and in a non-line-wrapping
3973
+ // situation, we can take this ordering to correspond to the visual
3974
+ // ordering. This finds the first part whose end is after the given
3975
+ // coordinates.
3976
+ var index = findFirst(function (i) {
3977
+ var part = order[i], ltr = part.level != 1;
3978
+ return boxIsAfter(cursorCoords(cm, Pos(lineNo$$1, ltr ? part.to : part.from, ltr ? "before" : "after"),
3979
+ "line", lineObj, preparedMeasure), x, y, true)
3980
+ }, 0, order.length - 1);
3981
+ var part = order[index];
3982
+ // If this isn't the first part, the part's start is also after
3983
+ // the coordinates, and the coordinates aren't on the same line as
3984
+ // that start, move one part back.
3985
+ if (index > 0) {
3986
+ var ltr = part.level != 1;
3987
+ var start = cursorCoords(cm, Pos(lineNo$$1, ltr ? part.from : part.to, ltr ? "after" : "before"),
3988
+ "line", lineObj, preparedMeasure);
3989
+ if (boxIsAfter(start, x, y, true) && start.top > y)
3990
+ { part = order[index - 1]; }
3991
+ }
3992
+ return part
3993
+ }
3994
+
3995
+ function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) {
3996
+ // In a wrapped line, rtl text on wrapping boundaries can do things
3997
+ // that don't correspond to the ordering in our `order` array at
3998
+ // all, so a binary search doesn't work, and we want to return a
3999
+ // part that only spans one line so that the binary search in
4000
+ // coordsCharInner is safe. As such, we first find the extent of the
4001
+ // wrapped line, and then do a flat search in which we discard any
4002
+ // spans that aren't on the line.
4003
+ var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y);
4004
+ var begin = ref.begin;
4005
+ var end = ref.end;
4006
+ var part = null, closestDist = null;
4007
+ for (var i = 0; i < order.length; i++) {
4008
+ var p = order[i];
4009
+ if (p.from >= end || p.to <= begin) { continue }
4010
+ var ltr = p.level != 1;
4011
+ var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right;
4012
+ // Weigh against spans ending before this, so that they are only
4013
+ // picked if nothing ends after
4014
+ var dist = endX < x ? x - endX + 1e9 : endX - x;
4015
+ if (!part || closestDist > dist) {
4016
+ part = p;
4017
+ closestDist = dist;
4018
+ }
4019
+ }
4020
+ if (!part) { part = order[order.length - 1]; }
4021
+ // Clip the part to the wrapped line.
4022
+ if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; }
4023
+ if (part.to > end) { part = {from: part.from, to: end, level: part.level}; }
4024
+ return part
4025
  }
4026
 
4027
  var measureText;
4147
  }
4148
 
4149
  function prepareSelection(cm, primary) {
4150
+ if ( primary === void 0 ) primary = true;
4151
+
4152
  var doc = cm.doc, result = {};
4153
  var curFragment = result.cursors = document.createDocumentFragment();
4154
  var selFragment = result.selection = document.createDocumentFragment();
4155
 
4156
  for (var i = 0; i < doc.sel.ranges.length; i++) {
4157
+ if (!primary && i == doc.sel.primIndex) { continue }
4158
  var range$$1 = doc.sel.ranges[i];
4159
  if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { continue }
4160
  var collapsed = range$$1.empty();
4185
  }
4186
  }
4187
 
4188
+ function cmpCoords(a, b) { return a.top - b.top || a.left - b.left }
4189
+
4190
  // Draws the given range as a highlighted selection
4191
  function drawSelectionRange(cm, range$$1, output) {
4192
  var display = cm.display, doc = cm.doc;
4209
  return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
4210
  }
4211
 
4212
+ var order = getOrder(lineObj, doc.direction);
4213
+ iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) {
4214
+ var fromPos = coords(from, dir == "ltr" ? "left" : "right");
4215
+ var toPos = coords(to - 1, dir == "ltr" ? "right" : "left");
4216
+ if (dir == "ltr") {
4217
+ var fromLeft = fromArg == null && from == 0 ? leftSide : fromPos.left;
4218
+ var toRight = toArg == null && to == lineLen ? rightSide : toPos.right;
4219
+ if (toPos.top - fromPos.top <= 3) { // Single line
4220
+ add(fromLeft, toPos.top, toRight - fromLeft, toPos.bottom);
4221
+ } else { // Multiple lines
4222
+ add(fromLeft, fromPos.top, null, fromPos.bottom);
4223
+ if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); }
4224
+ add(leftSide, toPos.top, toPos.right, toPos.bottom);
4225
+ }
4226
+ } else if (from < to) { // RTL
4227
+ var fromRight = fromArg == null && from == 0 ? rightSide : fromPos.right;
4228
+ var toLeft = toArg == null && to == lineLen ? leftSide : toPos.left;
4229
+ if (toPos.top - fromPos.top <= 3) { // Single line
4230
+ add(toLeft, toPos.top, fromRight - toLeft, toPos.bottom);
4231
+ } else { // Multiple lines
4232
+ var topLeft = leftSide;
4233
+ if (i) {
4234
+ var topEnd = wrappedLineExtentChar(cm, lineObj, null, from).end;
4235
+ // The coordinates returned for an RTL wrapped space tend to
4236
+ // be complete bogus, so try to skip that here.
4237
+ topLeft = coords(topEnd - (/\s/.test(lineObj.text.charAt(topEnd - 1)) ? 2 : 1), "left").left;
4238
+ }
4239
+ add(topLeft, fromPos.top, fromRight - topLeft, fromPos.bottom);
4240
+ if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); }
4241
+ var botWidth = null;
4242
+ if (i < order.length - 1 || true) {
4243
+ var botStart = wrappedLineExtentChar(cm, lineObj, null, to).begin;
4244
+ botWidth = coords(botStart, "right").right - toLeft;
4245
+ }
4246
+ add(toLeft, toPos.top, botWidth, toPos.bottom);
4247
+ }
4248
  }
4249
+
4250
+ if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; }
4251
+ if (cmpCoords(toPos, start) < 0) { start = toPos; }
4252
+ if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; }
4253
+ if (cmpCoords(toPos, end) < 0) { end = toPos; }
 
 
4254
  });
4255
  return {start: start, end: end}
4256
  }
4880
  }
4881
 
4882
  if (op.updatedDisplay || op.selectionChanged)
4883
+ { op.preparedSelection = display.input.prepareSelection(); }
4884
  }
4885
 
4886
  function endOperation_W2(op) {
4893
  cm.display.maxLineChanged = false;
4894
  }
4895
 
4896
+ var takeFocus = op.focus && op.focus == activeElt();
4897
  if (op.preparedSelection)
4898
  { cm.display.input.showSelection(op.preparedSelection, takeFocus); }
4899
  if (op.updatedDisplay || op.startHeight != cm.doc.height)
6493
 
6494
  function replaceRange(doc, code, from, to, origin) {
6495
  if (!to) { to = from; }
6496
+ if (cmp(to, from) < 0) { var assign;
6497
+ (assign = [to, from], from = assign[0], to = assign[1], assign); }
6498
  if (typeof code == "string") { code = doc.splitLines(code); }
6499
  makeChange(doc, {from: from, to: to, text: code, origin: origin});
6500
  }
7855
  });
7856
  }
7857
 
7858
+ function moveCharLogically(line, ch, dir) {
7859
+ var target = skipExtendingChars(line.text, ch + dir, dir);
7860
+ return target < 0 || target > line.text.length ? null : target
7861
+ }
7862
+
7863
+ function moveLogically(line, start, dir) {
7864
+ var ch = moveCharLogically(line, start.ch, dir);
7865
+ return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before")
7866
+ }
7867
+
7868
+ function endOfLine(visually, cm, lineObj, lineNo, dir) {
7869
+ if (visually) {
7870
+ var order = getOrder(lineObj, cm.doc.direction);
7871
+ if (order) {
7872
+ var part = dir < 0 ? lst(order) : order[0];
7873
+ var moveInStorageOrder = (dir < 0) == (part.level == 1);
7874
+ var sticky = moveInStorageOrder ? "after" : "before";
7875
+ var ch;
7876
+ // With a wrapped rtl chunk (possibly spanning multiple bidi parts),
7877
+ // it could be that the last bidi part is not on the last visual line,
7878
+ // since visual lines contain content order-consecutive chunks.
7879
+ // Thus, in rtl, we are looking for the first (content-order) character
7880
+ // in the rtl chunk that is on the last line (that is, the same line
7881
+ // as the last (content-order) character).
7882
+ if (part.level > 0) {
7883
+ var prep = prepareMeasureForLine(cm, lineObj);
7884
+ ch = dir < 0 ? lineObj.text.length - 1 : 0;
7885
+ var targetTop = measureCharPrepared(cm, prep, ch).top;
7886
+ ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
7887
+ if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); }
7888
+ } else { ch = dir < 0 ? part.to : part.from; }
7889
+ return new Pos(lineNo, ch, sticky)
7890
+ }
7891
+ }
7892
+ return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after")
7893
+ }
7894
+
7895
+ function moveVisually(cm, line, start, dir) {
7896
+ var bidi = getOrder(line, cm.doc.direction);
7897
+ if (!bidi) { return moveLogically(line, start, dir) }
7898
+ if (start.ch >= line.text.length) {
7899
+ start.ch = line.text.length;
7900
+ start.sticky = "before";
7901
+ } else if (start.ch <= 0) {
7902
+ start.ch = 0;
7903
+ start.sticky = "after";
7904
+ }
7905
+ var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos];
7906
+ if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) {
7907
+ // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines,
7908
+ // nothing interesting happens.
7909
+ return moveLogically(line, start, dir)
7910
+ }
7911
+
7912
+ var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); };
7913
+ var prep;
7914
+ var getWrappedLineExtent = function (ch) {
7915
+ if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} }
7916
+ prep = prep || prepareMeasureForLine(cm, line);
7917
+ return wrappedLineExtentChar(cm, line, prep, ch)
7918
+ };
7919
+ var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch);
7920
+
7921
+ if (cm.doc.direction == "rtl" || part.level == 1) {
7922
+ var moveInStorageOrder = (part.level == 1) == (dir < 0);
7923
+ var ch = mv(start, moveInStorageOrder ? 1 : -1);
7924
+ if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) {
7925
+ // Case 2: We move within an rtl part or in an rtl editor on the same visual line
7926
+ var sticky = moveInStorageOrder ? "before" : "after";
7927
+ return new Pos(start.line, ch, sticky)
7928
+ }
7929
+ }
7930
+
7931
+ // Case 3: Could not move within this bidi part in this visual line, so leave
7932
+ // the current bidi part
7933
+
7934
+ var searchInVisualLine = function (partPos, dir, wrappedLineExtent) {
7935
+ var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder
7936
+ ? new Pos(start.line, mv(ch, 1), "before")
7937
+ : new Pos(start.line, ch, "after"); };
7938
+
7939
+ for (; partPos >= 0 && partPos < bidi.length; partPos += dir) {
7940
+ var part = bidi[partPos];
7941
+ var moveInStorageOrder = (dir > 0) == (part.level != 1);
7942
+ var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1);
7943
+ if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) }
7944
+ ch = moveInStorageOrder ? part.from : mv(part.to, -1);
7945
+ if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) }
7946
+ }
7947
+ };
7948
+
7949
+ // Case 3a: Look for other bidi parts on the same visual line
7950
+ var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent);
7951
+ if (res) { return res }
7952
+
7953
+ // Case 3b: Look for other bidi parts on the next visual line
7954
+ var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1);
7955
+ if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) {
7956
+ res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh));
7957
+ if (res) { return res }
7958
+ }
7959
+
7960
+ // Case 4: Nowhere to move
7961
+ return null
7962
+ }
7963
+
7964
  // Commands are parameter-less actions that can be performed on an
7965
  // editor, mostly used for keybindings.
7966
  var commands = {
8522
  anchor = maxPos(oldRange.to(), range$$1.head);
8523
  }
8524
  var ranges$1 = startSel.ranges.slice(0);
8525
+ ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head));
8526
  setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse);
8527
  }
8528
  }
8574
  on(document, "mouseup", up);
8575
  }
8576
 
8577
+ // Used when mouse-selecting to adjust the anchor to the proper side
8578
+ // of a bidi jump depending on the visual position of the head.
8579
+ function bidiSimplify(cm, range$$1) {
8580
+ var anchor = range$$1.anchor;
8581
+ var head = range$$1.head;
8582
+ var anchorLine = getLine(cm.doc, anchor.line);
8583
+ if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range$$1 }
8584
+ var order = getOrder(anchorLine);
8585
+ if (!order) { return range$$1 }
8586
+ var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index];
8587
+ if (part.from != anchor.ch && part.to != anchor.ch) { return range$$1 }
8588
+ var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1);
8589
+ if (boundary == 0 || boundary == order.length) { return range$$1 }
8590
+
8591
+ // Compute the relative visual position of the head compared to the
8592
+ // anchor (<0 is to the left, >0 to the right)
8593
+ var leftSide;
8594
+ if (head.line != anchor.line) {
8595
+ leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0;
8596
+ } else {
8597
+ var headIndex = getBidiPartAt(order, head.ch, head.sticky);
8598
+ var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1);
8599
+ if (headIndex == boundary - 1 || headIndex == boundary)
8600
+ { leftSide = dir < 0; }
8601
+ else
8602
+ { leftSide = dir > 0; }
8603
+ }
8604
+
8605
+ var usePart = order[boundary + (leftSide ? -1 : 0)];
8606
+ var from = leftSide == (usePart.level == 1);
8607
+ var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before";
8608
+ return anchor.ch == ch && anchor.sticky == sticky ? range$$1 : new Range(new Pos(anchor.line, ch, sticky), head)
8609
+ }
8610
+
8611
 
8612
  // Determines whether an event happened in the gutter, and fires the
8613
  // handlers for the corresponding event.
8614
  function gutterEvent(cm, e, type, prevent) {
8615
  var mX, mY;
8616
+ if (e.touches) {
8617
+ mX = e.touches[0].clientX;
8618
+ mY = e.touches[0].clientY;
8619
+ } else {
8620
+ try { mX = e.clientX; mY = e.clientY; }
8621
+ catch(e) { return false }
8622
+ }
8623
  if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
8624
  if (prevent) { e_preventDefault(e); }
8625
 
8957
  return dx * dx + dy * dy > 20 * 20
8958
  }
8959
  on(d.scroller, "touchstart", function (e) {
8960
+ if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) {
8961
  d.input.ensurePolled();
8962
  clearTimeout(touchFinished);
8963
  var now = +new Date;
10741
 
10742
  addLegacyProps(CodeMirror$1);
10743
 
10744
+ CodeMirror$1.version = "5.30.0";
10745
 
10746
  return CodeMirror$1;
10747
 
assets/js/{mailpoet.81b583ba.js → mailpoet.25f879a2.js} RENAMED
@@ -51190,7 +51190,7 @@ webpackJsonp([3],[
51190
 
51191
  /* WEBPACK VAR INJECTION */(function(global) {/*!
51192
  * Parsley.js
51193
- * Version 2.7.2 - built Tue, May 9th 2017, 11:21 am
51194
  * http://parsleyjs.org
51195
  * Guillaume Potier - <guillaume@wisembly.com>
51196
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
@@ -51254,17 +51254,20 @@ webpackJsonp([3],[
51254
  element.setAttribute(this.dasherize(namespace + attr), String(value));
51255
  },
51256
 
 
 
 
 
51257
  generateID: function generateID() {
51258
  return '' + globalID++;
51259
  },
51260
 
51261
  /** Third party functions **/
51262
- // Zepto deserialize function
51263
  deserializeValue: function deserializeValue(value) {
51264
  var num;
51265
 
51266
  try {
51267
- return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value;
51268
  } catch (e) {
51269
  return value;
51270
  }
@@ -51674,7 +51677,7 @@ webpackJsonp([3],[
51674
  };
51675
 
51676
  var typeTesters = {
51677
- email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,
51678
 
51679
  // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
51680
  number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
@@ -51825,6 +51828,10 @@ webpackJsonp([3],[
51825
  return this._setValidator.apply(this, arguments);
51826
  },
51827
 
 
 
 
 
51828
  updateValidator: function updateValidator(name, arg1, arg2) {
51829
  if (!this.validators[name]) {
51830
  Utils.warn('Validator "' + name + '" is not already defined.');
@@ -52247,19 +52254,25 @@ webpackJsonp([3],[
52247
 
52248
  // Determine which element will have `parsley-error` and `parsley-success` classes
52249
  _manageClassHandler: function _manageClassHandler() {
52250
- // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
52251
- if ('string' === typeof this.options.classHandler) {
52252
- if ($(this.options.classHandler).length === 0) ParsleyUtils.warn('No elements found that match the selector `' + this.options.classHandler + '` set in options.classHandler or data-parsley-class-handler');
52253
-
52254
- //return element or empty set
52255
- return $(this.options.classHandler);
52256
- }
52257
 
52258
  // Class handled could also be determined by function given in Parsley options
52259
- if ('function' === typeof this.options.classHandler) var $handler = this.options.classHandler.call(this, this);
52260
 
52261
- // If this function returned a valid existing DOM element, go for it
52262
- if ('undefined' !== typeof $handler && $handler.length) return $handler;
 
 
 
 
 
 
 
 
 
 
 
52263
 
52264
  return this._inputHolder();
52265
  },
@@ -52273,16 +52286,18 @@ webpackJsonp([3],[
52273
  },
52274
 
52275
  _insertErrorWrapper: function _insertErrorWrapper() {
52276
- var $errorsContainer;
52277
 
52278
  // Nothing to do if already inserted
52279
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
52280
 
52281
- if ('string' === typeof this.options.errorsContainer) {
52282
- if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else Utils.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
52283
- } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
 
 
52284
 
52285
- if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
52286
 
52287
  return this._inputHolder().after(this._ui.$errorsWrapper);
52288
  },
@@ -52527,6 +52542,11 @@ webpackJsonp([3],[
52527
  return Utils.all(promises);
52528
  },
52529
 
 
 
 
 
 
52530
  // Reset UI
52531
  reset: function reset() {
52532
  // Form case: emit a reset event for each field
@@ -52704,7 +52724,7 @@ webpackJsonp([3],[
52704
  var group = _ref9.group;
52705
 
52706
  // do not validate a field if not the same as given validation group
52707
- this.refreshConstraints();
52708
  if (group && !this._isInGroup(group)) return;
52709
 
52710
  this.value = this.getValue();
@@ -52781,7 +52801,7 @@ webpackJsonp([3],[
52781
  var _refreshed = _ref10._refreshed;
52782
 
52783
  // Recompute options and rebind constraints to have latest changes
52784
- if (!_refreshed) this.refreshConstraints();
52785
  // do not validate a field if not the same as given validation group
52786
  if (group && !this._isInGroup(group)) return;
52787
 
@@ -52854,12 +52874,21 @@ webpackJsonp([3],[
52854
  this._trigger('destroy');
52855
  },
52856
 
52857
- // Actualize options that could have change since previous validation
52858
- // Re-bind accordingly constraints (could be some new, removed or updated)
52859
- refreshConstraints: function refreshConstraints() {
 
 
 
 
52860
  return this.actualizeOptions()._bindConstraints();
52861
  },
52862
 
 
 
 
 
 
52863
  /**
52864
  * Add a new constraint to a field
52865
  *
@@ -52952,7 +52981,7 @@ webpackJsonp([3],[
52952
  else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true);
52953
 
52954
  // html5 types
52955
- var type = this.element.type;
52956
 
52957
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
52958
  if ('number' === type) {
@@ -53039,8 +53068,8 @@ webpackJsonp([3],[
53039
  return this;
53040
  },
53041
 
53042
- // See `Field.refreshConstraints()`
53043
- refreshConstraints: function refreshConstraints() {
53044
  var fieldConstraints;
53045
 
53046
  this.constraints = [];
@@ -53061,7 +53090,7 @@ webpackJsonp([3],[
53061
  continue;
53062
  }
53063
 
53064
- fieldConstraints = this.$elements[i].data('FieldMultiple').refreshConstraints().constraints;
53065
 
53066
  for (var j = 0; j < fieldConstraints.length; j++) this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
53067
  }
@@ -53076,10 +53105,11 @@ webpackJsonp([3],[
53076
 
53077
  // Radio input case
53078
  if (this.element.nodeName === 'INPUT') {
53079
- if (this.element.type === 'radio') return this._findRelated().filter(':checked').val() || '';
 
53080
 
53081
  // checkbox input case
53082
- if (this.element.type === 'checkbox') {
53083
  var values = [];
53084
 
53085
  this._findRelated().filter(':checked').each(function () {
@@ -53137,7 +53167,7 @@ webpackJsonp([3],[
53137
  Factory.prototype = {
53138
  init: function init(options) {
53139
  this.__class__ = 'Parsley';
53140
- this.__version__ = '2.7.2';
53141
  this.__id__ = Utils.generateID();
53142
 
53143
  // Pre-compute options
@@ -53151,7 +53181,8 @@ webpackJsonp([3],[
53151
  },
53152
 
53153
  isMultiple: function isMultiple() {
53154
- return this.element.type === 'radio' || this.element.type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
 
53155
  },
53156
 
53157
  // Multiples fields are a real nightmare :(
@@ -53183,7 +53214,8 @@ webpackJsonp([3],[
53183
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
53184
  if (name) {
53185
  $('input[name="' + name + '"]').each(function (i, input) {
53186
- if (input.type === 'radio' || input.type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.options.multiple);
 
53187
  });
53188
  }
53189
 
@@ -53259,7 +53291,7 @@ webpackJsonp([3],[
53259
  actualizeOptions: null,
53260
  _resetOptions: null,
53261
  Factory: Factory,
53262
- version: '2.7.2'
53263
  });
53264
 
53265
  // Supplement Field and Form with Base
@@ -53283,9 +53315,7 @@ webpackJsonp([3],[
53283
  }
53284
 
53285
  // Return undefined if applied to non existing DOM element
53286
- if (!$(this).length) {
53287
- Utils.warn('You must bind Parsley on an existing element.');
53288
-
53289
  return;
53290
  }
53291
 
@@ -53317,7 +53347,7 @@ webpackJsonp([3],[
53317
  // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
53318
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
53319
  window.ParsleyValidator = {};
53320
- $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
53321
  window.Parsley[method] = function () {
53322
  return registry[method].apply(registry, arguments);
53323
  };
51190
 
51191
  /* WEBPACK VAR INJECTION */(function(global) {/*!
51192
  * Parsley.js
51193
+ * Version 2.8.0 - built Wed, Sep 13th 2017, 11:04 pm
51194
  * http://parsleyjs.org
51195
  * Guillaume Potier - <guillaume@wisembly.com>
51196
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
51254
  element.setAttribute(this.dasherize(namespace + attr), String(value));
51255
  },
51256
 
51257
+ getType: function getType(element) {
51258
+ return element.getAttribute('type') || 'text';
51259
+ },
51260
+
51261
  generateID: function generateID() {
51262
  return '' + globalID++;
51263
  },
51264
 
51265
  /** Third party functions **/
 
51266
  deserializeValue: function deserializeValue(value) {
51267
  var num;
51268
 
51269
  try {
51270
+ return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? JSON.parse(value) : value) : value;
51271
  } catch (e) {
51272
  return value;
51273
  }
51677
  };
51678
 
51679
  var typeTesters = {
51680
+ email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,
51681
 
51682
  // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
51683
  number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
51828
  return this._setValidator.apply(this, arguments);
51829
  },
51830
 
51831
+ hasValidator: function hasValidator(name) {
51832
+ return !!this.validators[name];
51833
+ },
51834
+
51835
  updateValidator: function updateValidator(name, arg1, arg2) {
51836
  if (!this.validators[name]) {
51837
  Utils.warn('Validator "' + name + '" is not already defined.');
52254
 
52255
  // Determine which element will have `parsley-error` and `parsley-success` classes
52256
  _manageClassHandler: function _manageClassHandler() {
52257
+ // Class handled could also be determined by function given in Parsley options
52258
+ if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler);
 
 
 
 
 
52259
 
52260
  // Class handled could also be determined by function given in Parsley options
52261
+ var $handlerFunction = this.options.classHandler;
52262
 
52263
+ // It might also be the function name of a global function
52264
+ if ('string' === typeof this.options.classHandler && 'function' === typeof window[this.options.classHandler]) $handlerFunction = window[this.options.classHandler];
52265
+
52266
+ if ('function' === typeof $handlerFunction) {
52267
+ var $handler = $handlerFunction.call(this, this);
52268
+
52269
+ // If this function returned a valid existing DOM element, go for it
52270
+ if ('undefined' !== typeof $handler && $handler.length) return $handler;
52271
+ } else if ('object' === typeof $handlerFunction && $handlerFunction instanceof jQuery && $handlerFunction.length) {
52272
+ return $handlerFunction;
52273
+ } else if ($handlerFunction) {
52274
+ Utils.warn('The class handler `' + $handlerFunction + '` does not exist in DOM nor as a global JS function');
52275
+ }
52276
 
52277
  return this._inputHolder();
52278
  },
52286
  },
52287
 
52288
  _insertErrorWrapper: function _insertErrorWrapper() {
52289
+ var $errorsContainer = this.options.errorsContainer;
52290
 
52291
  // Nothing to do if already inserted
52292
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
52293
 
52294
+ if ('string' === typeof $errorsContainer) {
52295
+ if ($($errorsContainer).length) return $($errorsContainer).append(this._ui.$errorsWrapper);else if ('function' === typeof window[$errorsContainer]) $errorsContainer = window[$errorsContainer];else Utils.warn('The errors container `' + $errorsContainer + '` does not exist in DOM nor as a global JS function');
52296
+ }
52297
+
52298
+ if ('function' === typeof $errorsContainer) $errorsContainer = $errorsContainer.call(this, this);
52299
 
52300
+ if ('object' === typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
52301
 
52302
  return this._inputHolder().after(this._ui.$errorsWrapper);
52303
  },
52542
  return Utils.all(promises);
52543
  },
52544
 
52545
+ refresh: function refresh() {
52546
+ this._refreshFields();
52547
+ return this;
52548
+ },
52549
+
52550
  // Reset UI
52551
  reset: function reset() {
52552
  // Form case: emit a reset event for each field
52724
  var group = _ref9.group;
52725
 
52726
  // do not validate a field if not the same as given validation group
52727
+ this.refresh();
52728
  if (group && !this._isInGroup(group)) return;
52729
 
52730
  this.value = this.getValue();
52801
  var _refreshed = _ref10._refreshed;
52802
 
52803
  // Recompute options and rebind constraints to have latest changes
52804
+ if (!_refreshed) this.refresh();
52805
  // do not validate a field if not the same as given validation group
52806
  if (group && !this._isInGroup(group)) return;
52807
 
52874
  this._trigger('destroy');
52875
  },
52876
 
52877
+ // Actualize options and rebind constraints
52878
+ refresh: function refresh() {
52879
+ this._refreshConstraints();
52880
+ return this;
52881
+ },
52882
+
52883
+ _refreshConstraints: function _refreshConstraints() {
52884
  return this.actualizeOptions()._bindConstraints();
52885
  },
52886
 
52887
+ refreshConstraints: function refreshConstraints() {
52888
+ Utils.warnOnce("Parsley's refreshConstraints is deprecated. Please use refresh");
52889
+ return this.refresh();
52890
+ },
52891
+
52892
  /**
52893
  * Add a new constraint to a field
52894
  *
52981
  else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true);
52982
 
52983
  // html5 types
52984
+ var type = Utils.getType(this.element);
52985
 
52986
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
52987
  if ('number' === type) {
53068
  return this;
53069
  },
53070
 
53071
+ // See `Field._refreshConstraints()`
53072
+ _refreshConstraints: function _refreshConstraints() {
53073
  var fieldConstraints;
53074
 
53075
  this.constraints = [];
53090
  continue;
53091
  }
53092
 
53093
+ fieldConstraints = this.$elements[i].data('FieldMultiple')._refreshConstraints().constraints;
53094
 
53095
  for (var j = 0; j < fieldConstraints.length; j++) this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
53096
  }
53105
 
53106
  // Radio input case
53107
  if (this.element.nodeName === 'INPUT') {
53108
+ var type = Utils.getType(this.element);
53109
+ if (type === 'radio') return this._findRelated().filter(':checked').val() || '';
53110
 
53111
  // checkbox input case
53112
+ if (type === 'checkbox') {
53113
  var values = [];
53114
 
53115
  this._findRelated().filter(':checked').each(function () {
53167
  Factory.prototype = {
53168
  init: function init(options) {
53169
  this.__class__ = 'Parsley';
53170
+ this.__version__ = '2.8.0';
53171
  this.__id__ = Utils.generateID();
53172
 
53173
  // Pre-compute options
53181
  },
53182
 
53183
  isMultiple: function isMultiple() {
53184
+ var type = Utils.getType(this.element);
53185
+ return type === 'radio' || type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
53186
  },
53187
 
53188
  // Multiples fields are a real nightmare :(
53214
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
53215
  if (name) {
53216
  $('input[name="' + name + '"]').each(function (i, input) {
53217
+ var type = Utils.getType(input);
53218
+ if (type === 'radio' || type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.options.multiple);
53219
  });
53220
  }
53221
 
53291
  actualizeOptions: null,
53292
  _resetOptions: null,
53293
  Factory: Factory,
53294
+ version: '2.8.0'
53295
  });
53296
 
53297
  // Supplement Field and Form with Base
53315
  }
53316
 
53317
  // Return undefined if applied to non existing DOM element
53318
+ if (this.length == 0) {
 
 
53319
  return;
53320
  }
53321
 
53347
  // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
53348
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
53349
  window.ParsleyValidator = {};
53350
+ $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator hasValidator'.split(' '), function (i, method) {
53351
  window.Parsley[method] = function () {
53352
  return registry[method].apply(registry, arguments);
53353
  };
assets/js/manifest.json CHANGED
@@ -1,10 +1,10 @@
1
  {
2
  "mp2migrator.js": "mp2migrator.923dd5b2.js",
3
- "public.js": "public.02e5f1af.js",
4
- "admin.js": "admin.d091b681.js",
5
- "admin_vendor.js": "admin_vendor.ee9853ec.js",
6
- "form_editor.js": "form_editor.c0e36e82.js",
7
- "mailpoet.js": "mailpoet.81b583ba.js",
8
  "newsletter_editor.js": "newsletter_editor.cc3c87be.js",
9
- "vendor.js": "vendor.f4549608.js"
10
  }
1
  {
2
  "mp2migrator.js": "mp2migrator.923dd5b2.js",
3
+ "public.js": "public.5b18b937.js",
4
+ "admin.js": "admin.ef421cc2.js",
5
+ "admin_vendor.js": "admin_vendor.c1a3e332.js",
6
+ "form_editor.js": "form_editor.00c531b6.js",
7
+ "mailpoet.js": "mailpoet.25f879a2.js",
8
  "newsletter_editor.js": "newsletter_editor.cc3c87be.js",
9
+ "vendor.js": "vendor.2e3b215c.js"
10
  }
assets/js/{public.02e5f1af.js → public.5b18b937.js} RENAMED
@@ -1996,7 +1996,7 @@
1996
 
1997
  /* WEBPACK VAR INJECTION */(function(global) {/*!
1998
  * Parsley.js
1999
- * Version 2.7.2 - built Tue, May 9th 2017, 11:21 am
2000
  * http://parsleyjs.org
2001
  * Guillaume Potier - <guillaume@wisembly.com>
2002
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
@@ -2060,17 +2060,20 @@
2060
  element.setAttribute(this.dasherize(namespace + attr), String(value));
2061
  },
2062
 
 
 
 
 
2063
  generateID: function generateID() {
2064
  return '' + globalID++;
2065
  },
2066
 
2067
  /** Third party functions **/
2068
- // Zepto deserialize function
2069
  deserializeValue: function deserializeValue(value) {
2070
  var num;
2071
 
2072
  try {
2073
- return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value;
2074
  } catch (e) {
2075
  return value;
2076
  }
@@ -2480,7 +2483,7 @@
2480
  };
2481
 
2482
  var typeTesters = {
2483
- email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,
2484
 
2485
  // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
2486
  number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
@@ -2631,6 +2634,10 @@
2631
  return this._setValidator.apply(this, arguments);
2632
  },
2633
 
 
 
 
 
2634
  updateValidator: function updateValidator(name, arg1, arg2) {
2635
  if (!this.validators[name]) {
2636
  Utils.warn('Validator "' + name + '" is not already defined.');
@@ -3053,19 +3060,25 @@
3053
 
3054
  // Determine which element will have `parsley-error` and `parsley-success` classes
3055
  _manageClassHandler: function _manageClassHandler() {
3056
- // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
3057
- if ('string' === typeof this.options.classHandler) {
3058
- if ($(this.options.classHandler).length === 0) ParsleyUtils.warn('No elements found that match the selector `' + this.options.classHandler + '` set in options.classHandler or data-parsley-class-handler');
3059
-
3060
- //return element or empty set
3061
- return $(this.options.classHandler);
3062
- }
3063
 
3064
  // Class handled could also be determined by function given in Parsley options
3065
- if ('function' === typeof this.options.classHandler) var $handler = this.options.classHandler.call(this, this);
3066
 
3067
- // If this function returned a valid existing DOM element, go for it
3068
- if ('undefined' !== typeof $handler && $handler.length) return $handler;
 
 
 
 
 
 
 
 
 
 
 
3069
 
3070
  return this._inputHolder();
3071
  },
@@ -3079,16 +3092,18 @@
3079
  },
3080
 
3081
  _insertErrorWrapper: function _insertErrorWrapper() {
3082
- var $errorsContainer;
3083
 
3084
  // Nothing to do if already inserted
3085
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
3086
 
3087
- if ('string' === typeof this.options.errorsContainer) {
3088
- if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else Utils.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
3089
- } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
 
 
3090
 
3091
- if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
3092
 
3093
  return this._inputHolder().after(this._ui.$errorsWrapper);
3094
  },
@@ -3333,6 +3348,11 @@
3333
  return Utils.all(promises);
3334
  },
3335
 
 
 
 
 
 
3336
  // Reset UI
3337
  reset: function reset() {
3338
  // Form case: emit a reset event for each field
@@ -3510,7 +3530,7 @@
3510
  var group = _ref9.group;
3511
 
3512
  // do not validate a field if not the same as given validation group
3513
- this.refreshConstraints();
3514
  if (group && !this._isInGroup(group)) return;
3515
 
3516
  this.value = this.getValue();
@@ -3587,7 +3607,7 @@
3587
  var _refreshed = _ref10._refreshed;
3588
 
3589
  // Recompute options and rebind constraints to have latest changes
3590
- if (!_refreshed) this.refreshConstraints();
3591
  // do not validate a field if not the same as given validation group
3592
  if (group && !this._isInGroup(group)) return;
3593
 
@@ -3660,12 +3680,21 @@
3660
  this._trigger('destroy');
3661
  },
3662
 
3663
- // Actualize options that could have change since previous validation
3664
- // Re-bind accordingly constraints (could be some new, removed or updated)
3665
- refreshConstraints: function refreshConstraints() {
 
 
 
 
3666
  return this.actualizeOptions()._bindConstraints();
3667
  },
3668
 
 
 
 
 
 
3669
  /**
3670
  * Add a new constraint to a field
3671
  *
@@ -3758,7 +3787,7 @@
3758
  else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true);
3759
 
3760
  // html5 types
3761
- var type = this.element.type;
3762
 
3763
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
3764
  if ('number' === type) {
@@ -3845,8 +3874,8 @@
3845
  return this;
3846
  },
3847
 
3848
- // See `Field.refreshConstraints()`
3849
- refreshConstraints: function refreshConstraints() {
3850
  var fieldConstraints;
3851
 
3852
  this.constraints = [];
@@ -3867,7 +3896,7 @@
3867
  continue;
3868
  }
3869
 
3870
- fieldConstraints = this.$elements[i].data('FieldMultiple').refreshConstraints().constraints;
3871
 
3872
  for (var j = 0; j < fieldConstraints.length; j++) this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
3873
  }
@@ -3882,10 +3911,11 @@
3882
 
3883
  // Radio input case
3884
  if (this.element.nodeName === 'INPUT') {
3885
- if (this.element.type === 'radio') return this._findRelated().filter(':checked').val() || '';
 
3886
 
3887
  // checkbox input case
3888
- if (this.element.type === 'checkbox') {
3889
  var values = [];
3890
 
3891
  this._findRelated().filter(':checked').each(function () {
@@ -3943,7 +3973,7 @@
3943
  Factory.prototype = {
3944
  init: function init(options) {
3945
  this.__class__ = 'Parsley';
3946
- this.__version__ = '2.7.2';
3947
  this.__id__ = Utils.generateID();
3948
 
3949
  // Pre-compute options
@@ -3957,7 +3987,8 @@
3957
  },
3958
 
3959
  isMultiple: function isMultiple() {
3960
- return this.element.type === 'radio' || this.element.type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
 
3961
  },
3962
 
3963
  // Multiples fields are a real nightmare :(
@@ -3989,7 +4020,8 @@
3989
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
3990
  if (name) {
3991
  $('input[name="' + name + '"]').each(function (i, input) {
3992
- if (input.type === 'radio' || input.type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.options.multiple);
 
3993
  });
3994
  }
3995
 
@@ -4065,7 +4097,7 @@
4065
  actualizeOptions: null,
4066
  _resetOptions: null,
4067
  Factory: Factory,
4068
- version: '2.7.2'
4069
  });
4070
 
4071
  // Supplement Field and Form with Base
@@ -4089,9 +4121,7 @@
4089
  }
4090
 
4091
  // Return undefined if applied to non existing DOM element
4092
- if (!$(this).length) {
4093
- Utils.warn('You must bind Parsley on an existing element.');
4094
-
4095
  return;
4096
  }
4097
 
@@ -4123,7 +4153,7 @@
4123
  // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
4124
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
4125
  window.ParsleyValidator = {};
4126
- $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
4127
  window.Parsley[method] = function () {
4128
  return registry[method].apply(registry, arguments);
4129
  };
1996
 
1997
  /* WEBPACK VAR INJECTION */(function(global) {/*!
1998
  * Parsley.js
1999
+ * Version 2.8.0 - built Wed, Sep 13th 2017, 11:04 pm
2000
  * http://parsleyjs.org
2001
  * Guillaume Potier - <guillaume@wisembly.com>
2002
  * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
2060
  element.setAttribute(this.dasherize(namespace + attr), String(value));
2061
  },
2062
 
2063
+ getType: function getType(element) {
2064
+ return element.getAttribute('type') || 'text';
2065
+ },
2066
+
2067
  generateID: function generateID() {
2068
  return '' + globalID++;
2069
  },
2070
 
2071
  /** Third party functions **/
 
2072
  deserializeValue: function deserializeValue(value) {
2073
  var num;
2074
 
2075
  try {
2076
+ return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? JSON.parse(value) : value) : value;
2077
  } catch (e) {
2078
  return value;
2079
  }
2483
  };
2484
 
2485
  var typeTesters = {
2486
+ email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,
2487
 
2488
  // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
2489
  number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
2634
  return this._setValidator.apply(this, arguments);
2635
  },
2636
 
2637
+ hasValidator: function hasValidator(name) {
2638
+ return !!this.validators[name];
2639
+ },
2640
+
2641
  updateValidator: function updateValidator(name, arg1, arg2) {
2642
  if (!this.validators[name]) {
2643
  Utils.warn('Validator "' + name + '" is not already defined.');
3060
 
3061
  // Determine which element will have `parsley-error` and `parsley-success` classes
3062
  _manageClassHandler: function _manageClassHandler() {
3063
+ // Class handled could also be determined by function given in Parsley options
3064
+ if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler);
 
 
 
 
 
3065
 
3066
  // Class handled could also be determined by function given in Parsley options
3067
+ var $handlerFunction = this.options.classHandler;
3068
 
3069
+ // It might also be the function name of a global function
3070
+ if ('string' === typeof this.options.classHandler && 'function' === typeof window[this.options.classHandler]) $handlerFunction = window[this.options.classHandler];
3071
+
3072
+ if ('function' === typeof $handlerFunction) {
3073
+ var $handler = $handlerFunction.call(this, this);
3074
+
3075
+ // If this function returned a valid existing DOM element, go for it
3076
+ if ('undefined' !== typeof $handler && $handler.length) return $handler;
3077
+ } else if ('object' === typeof $handlerFunction && $handlerFunction instanceof jQuery && $handlerFunction.length) {
3078
+ return $handlerFunction;
3079
+ } else if ($handlerFunction) {
3080
+ Utils.warn('The class handler `' + $handlerFunction + '` does not exist in DOM nor as a global JS function');
3081
+ }
3082
 
3083
  return this._inputHolder();
3084
  },
3092
  },
3093
 
3094
  _insertErrorWrapper: function _insertErrorWrapper() {
3095
+ var $errorsContainer = this.options.errorsContainer;
3096
 
3097
  // Nothing to do if already inserted
3098
  if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
3099
 
3100
+ if ('string' === typeof $errorsContainer) {
3101
+ if ($($errorsContainer).length) return $($errorsContainer).append(this._ui.$errorsWrapper);else if ('function' === typeof window[$errorsContainer]) $errorsContainer = window[$errorsContainer];else Utils.warn('The errors container `' + $errorsContainer + '` does not exist in DOM nor as a global JS function');
3102
+ }
3103
+
3104
+ if ('function' === typeof $errorsContainer) $errorsContainer = $errorsContainer.call(this, this);
3105
 
3106
+ if ('object' === typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
3107
 
3108
  return this._inputHolder().after(this._ui.$errorsWrapper);
3109
  },
3348
  return Utils.all(promises);
3349
  },
3350
 
3351
+ refresh: function refresh() {
3352
+ this._refreshFields();
3353
+ return this;
3354
+ },
3355
+
3356
  // Reset UI
3357
  reset: function reset() {
3358
  // Form case: emit a reset event for each field
3530
  var group = _ref9.group;
3531
 
3532
  // do not validate a field if not the same as given validation group
3533
+ this.refresh();
3534
  if (group && !this._isInGroup(group)) return;
3535
 
3536
  this.value = this.getValue();
3607
  var _refreshed = _ref10._refreshed;
3608
 
3609
  // Recompute options and rebind constraints to have latest changes
3610
+ if (!_refreshed) this.refresh();
3611
  // do not validate a field if not the same as given validation group
3612
  if (group && !this._isInGroup(group)) return;
3613
 
3680
  this._trigger('destroy');
3681
  },
3682
 
3683
+ // Actualize options and rebind constraints
3684
+ refresh: function refresh() {
3685
+ this._refreshConstraints();
3686
+ return this;
3687
+ },
3688
+
3689
+ _refreshConstraints: function _refreshConstraints() {
3690
  return this.actualizeOptions()._bindConstraints();
3691
  },
3692
 
3693
+ refreshConstraints: function refreshConstraints() {
3694
+ Utils.warnOnce("Parsley's refreshConstraints is deprecated. Please use refresh");
3695
+ return this.refresh();
3696
+ },
3697
+
3698
  /**
3699
  * Add a new constraint to a field
3700
  *
3787
  else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true);
3788
 
3789
  // html5 types
3790
+ var type = Utils.getType(this.element);
3791
 
3792
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
3793
  if ('number' === type) {
3874
  return this;
3875
  },
3876
 
3877
+ // See `Field._refreshConstraints()`
3878
+ _refreshConstraints: function _refreshConstraints() {
3879
  var fieldConstraints;
3880
 
3881
  this.constraints = [];
3896
  continue;
3897
  }
3898
 
3899
+ fieldConstraints = this.$elements[i].data('FieldMultiple')._refreshConstraints().constraints;
3900
 
3901
  for (var j = 0; j < fieldConstraints.length; j++) this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
3902
  }
3911
 
3912
  // Radio input case
3913
  if (this.element.nodeName === 'INPUT') {
3914
+ var type = Utils.getType(this.element);
3915
+ if (type === 'radio') return this._findRelated().filter(':checked').val() || '';
3916
 
3917
  // checkbox input case
3918
+ if (type === 'checkbox') {
3919
  var values = [];
3920
 
3921
  this._findRelated().filter(':checked').each(function () {
3973
  Factory.prototype = {
3974
  init: function init(options) {
3975
  this.__class__ = 'Parsley';
3976
+ this.__version__ = '2.8.0';
3977
  this.__id__ = Utils.generateID();
3978
 
3979
  // Pre-compute options
3987
  },
3988
 
3989
  isMultiple: function isMultiple() {
3990
+ var type = Utils.getType(this.element);
3991
+ return type === 'radio' || type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
3992
  },
3993
 
3994
  // Multiples fields are a real nightmare :(
4020
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
4021
  if (name) {
4022
  $('input[name="' + name + '"]').each(function (i, input) {
4023
+ var type = Utils.getType(input);
4024
+ if (type === 'radio' || type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.options.multiple);
4025
  });
4026
  }
4027
 
4097
  actualizeOptions: null,
4098
  _resetOptions: null,
4099
  Factory: Factory,
4100
+ version: '2.8.0'
4101
  });
4102
 
4103
  // Supplement Field and Form with Base
4121
  }
4122
 
4123
  // Return undefined if applied to non existing DOM element
4124
+ if (this.length == 0) {
 
 
4125
  return;
4126
  }
4127
 
4153
  // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
4154
  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
4155
  window.ParsleyValidator = {};
4156
+ $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator hasValidator'.split(' '), function (i, method) {
4157
  window.Parsley[method] = function () {
4158
  return registry[method].apply(registry, arguments);
4159
  };
assets/js/{vendor.f4549608.js → vendor.2e3b215c.js} RENAMED
@@ -76,7 +76,7 @@
76
  /******/ script.charset = 'utf-8';
77
  /******/ script.async = true;
78
 
79
- /******/ script.src = __webpack_require__.p + "" + ({"0":"admin","1":"admin_vendor","2":"form_editor","3":"mailpoet","4":"newsletter_editor"}[chunkId]||chunkId) + "." + {"0":"d091b681","1":"ee9853ec","2":"c0e36e82","3":"81b583ba","4":"cc3c87be"}[chunkId] + ".chunk.js";
80
  /******/ head.appendChild(script);
81
  /******/ }
82
  /******/ };
76
  /******/ script.charset = 'utf-8';
77
  /******/ script.async = true;
78
 
79
+ /******/ script.src = __webpack_require__.p + "" + ({"0":"admin","1":"admin_vendor","2":"form_editor","3":"mailpoet","4":"newsletter_editor"}[chunkId]||chunkId) + "." + {"0":"ef421cc2","1":"c1a3e332","2":"00c531b6","3":"25f879a2","4":"cc3c87be"}[chunkId] + ".chunk.js";
80
  /******/ head.appendChild(script);
81
  /******/ }
82
  /******/ };
lang/mailpoet-da_DK.mo CHANGED
Binary file
lang/mailpoet-de_DE.mo CHANGED
Binary file
lang/mailpoet-en_GB.mo CHANGED
Binary file
lang/mailpoet-es_ES.mo CHANGED
Binary file
lang/mailpoet-fa_IR.mo CHANGED
Binary file
lang/mailpoet-fr_CA.mo CHANGED
Binary file
lang/mailpoet-fr_FR.mo CHANGED
Binary file
lang/mailpoet-it_IT.mo CHANGED
Binary file
lang/mailpoet-ja.mo CHANGED
Binary file
lang/mailpoet-nl_NL.mo CHANGED
Binary file
lang/mailpoet-pl_PL.mo CHANGED
Binary file
lang/mailpoet-pt_BR.mo CHANGED
Binary file
lang/mailpoet-pt_PT.mo CHANGED
Binary file
lang/mailpoet-ru_RU.mo CHANGED
Binary file
lang/mailpoet-sv_SE.mo CHANGED
Binary file
lang/mailpoet-tr_TR.mo CHANGED
Binary file
lang/mailpoet.pot CHANGED
@@ -4,7 +4,7 @@ msgid ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
7
- "POT-Creation-Date: 2017-09-12 12:27:59+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -1031,19 +1031,19 @@ msgstr ""
1031
  msgid "An error has happened while performing a request, please try again later."
1032
  msgstr ""
1033
 
1034
- #: lib/Cron/CronHelper.php:108
1035
  msgid "Site URL is unreachable."
1036
  msgstr ""
1037
 
1038
- #: lib/Cron/CronHelper.php:114
1039
  msgid "Maximum execution time has been reached."
1040
  msgstr ""
1041
 
1042
- #: lib/Cron/Daemon.php:32
1043
  msgid "Invalid or missing request data."
1044
  msgstr ""
1045
 
1046
- #: lib/Cron/Daemon.php:35
1047
  msgid "Daemon does not exist."
1048
  msgstr ""
1049
 
@@ -1669,19 +1669,19 @@ msgstr ""
1669
  msgid "Accidentally unsubscribed?"
1670
  msgstr ""
1671
 
1672
- #: lib/Twig/Functions.php:106 views/settings/mta.html:1081
1673
  msgid "every minute"
1674
  msgstr ""
1675
 
1676
- #: lib/Twig/Functions.php:107 views/settings/mta.html:1082
1677
  msgid "every %1$d minutes"
1678
  msgstr ""
1679
 
1680
- #: lib/Twig/Functions.php:108 views/settings/mta.html:1083
1681
  msgid "every hour"
1682
  msgstr ""
1683
 
1684
- #: lib/Twig/Functions.php:109 views/settings/mta.html:1084
1685
  msgid "every %1$d hours"
1686
  msgstr ""
1687
 
@@ -1875,7 +1875,7 @@ msgstr ""
1875
  #: views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs:221
1876
  #: views/premium.html:56 views/settings/advanced.html:90
1877
  #: views/settings/advanced.html:130 views/settings/bounce.html:190
1878
- #: views/settings/mta.html:584 views/settings/signup.html:34
1879
  #: views/subscribers/importExport/export.html:33
1880
  #: views/subscribers/importExport/import/step2.html:63
1881
  msgid "Yes"
@@ -1894,8 +1894,8 @@ msgstr ""
1894
  #: views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs:227
1895
  #: views/premium.html:62 views/premium.html:63 views/settings/advanced.html:101
1896
  #: views/settings/advanced.html:141 views/settings/bounce.html:148
1897
- #: views/settings/bounce.html:179 views/settings/mta.html:541
1898
- #: views/settings/mta.html:595 views/settings/signup.html:46
1899
  #: views/subscribers/importExport/export.html:38
1900
  #: views/subscribers/importExport/import/step2.html:67
1901
  msgid "No"
@@ -3265,22 +3265,22 @@ msgstr ""
3265
 
3266
  #: views/newsletters.html:100
3267
  msgid ""
3268
- "Above 30% is excellent.\\\\n"
3269
- "Between 10 and 30% is good.\\\\n"
3270
  "Under 10% is bad."
3271
  msgstr ""
3272
 
3273
  #: views/newsletters.html:101
3274
  msgid ""
3275
- "Above 3% is excellent.\\\\n"
3276
- "Between 1 and 3% is good.\\\\n"
3277
  "Under 1% is bad."
3278
  msgstr ""
3279
 
3280
  #: views/newsletters.html:102
3281
  msgid ""
3282
- "Under 1% is excellent.\\\\n"
3283
- "Between 1 and 3% is good.\\\\n"
3284
  "Over 3% is bad."
3285
  msgstr ""
3286
 
@@ -3383,8 +3383,8 @@ msgid ""
3383
  "number."
3384
  msgstr ""
3385
 
3386
- #: views/newsletters.html:132 views/settings/mta.html:109
3387
- #: views/settings/mta.html:652
3388
  msgid "Activate"
3389
  msgstr ""
3390
 
@@ -4242,11 +4242,11 @@ msgstr ""
4242
  msgid "Hostname"
4243
  msgstr ""
4244
 
4245
- #: views/settings/bounce.html:50 views/settings/mta.html:490
4246
  msgid "Login"
4247
  msgstr ""
4248
 
4249
- #: views/settings/bounce.html:67 views/settings/mta.html:513
4250
  msgid "Password"
4251
  msgstr ""
4252
 
@@ -4298,236 +4298,264 @@ msgstr ""
4298
  msgid "Is it working? Try to connect"
4299
  msgstr ""
4300
 
4301
- #: views/settings/mta.html:76
 
 
 
 
4302
  msgid "You're now sending with MailPoet!"
4303
  msgstr ""
4304
 
4305
- #: views/settings/mta.html:78
4306
  msgid "Great, you're all set up. Your emails will now be sent quickly and reliably!"
4307
  msgstr ""
4308
 
4309
- #: views/settings/mta.html:85
4310
  msgid "Solve all of your sending problems!"
4311
  msgstr ""
4312
 
4313
- #: views/settings/mta.html:87
4314
- msgid ""
4315
- "Let MailPoet send your emails and get the Premium features for as little as "
4316
- "10 dollars or euros per month."
4317
- msgstr ""
4318
-
4319
- #: views/settings/mta.html:89
4320
  msgid "Reach the inbox, not the spam box."
4321
  msgstr ""
4322
 
4323
- #: views/settings/mta.html:90
4324
- msgid "Send emails up to 20 times faster than other sending methods."
4325
  msgstr ""
4326
 
4327
- #: views/settings/mta.html:91
4328
- msgid "SPF & DKIM signatures are already set up! No configuration required."
4329
  msgstr ""
4330
 
4331
- #: views/settings/mta.html:92
4332
  msgid ""
4333
  "Automatically remove invalid and bounced addresses (bounce handling) to "
4334
  "keep your lists clean."
4335
  msgstr ""
4336
 
4337
- #: views/settings/mta.html:98 views/welcome.html:37
4338
- msgid "Find out more"
 
 
4339
  msgstr ""
4340
 
4341
- #: views/settings/mta.html:102 views/settings/mta.html:133
4342
- msgid "Activated"
4343
  msgstr ""
4344
 
4345
- #: views/settings/mta.html:119
4346
- msgid "Other"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4347
  msgstr ""
4348
 
4349
  #: views/settings/mta.html:121
4350
- msgid "Send with your website or third party"
4351
  msgstr ""
4352
 
4353
  #: views/settings/mta.html:123
4354
- msgid ""
4355
- "Choose to send emails through your website (not recommended) or a third "
4356
- "party sender."
4357
  msgstr ""
4358
 
4359
  #: views/settings/mta.html:125
4360
- msgid "You'll probably end up in spam."
4361
  msgstr ""
4362
 
4363
  #: views/settings/mta.html:126
4364
- msgid "Sending speed is limited by your web host."
 
 
4365
  msgstr ""
4366
 
4367
  #: views/settings/mta.html:127
4368
  msgid "Manual configuration of SPF and DKIM required."
4369
  msgstr ""
4370
 
4371
- #: views/settings/mta.html:128
4372
- msgid "Bounce handling is available, but only with an extra add-on."
4373
  msgstr ""
4374
 
4375
- #: views/settings/mta.html:137
 
 
 
 
4376
  msgid "Configure"
4377
  msgstr ""
4378
 
4379
- #: views/settings/mta.html:144
4380
  msgid ""
4381
  "Need help to pick? [link]Check out the comparison table of sending "
4382
  "methods[/link]."
4383
  msgstr ""
4384
 
4385
- #: views/settings/mta.html:158
4386
  msgid "Method"
4387
  msgstr ""
4388
 
4389
- #: views/settings/mta.html:168
4390
  msgid "Your web host / web server"
4391
  msgstr ""
4392
 
4393
- #: views/settings/mta.html:177
4394
  msgid "SMTP"
4395
  msgstr ""
4396
 
4397
- #: views/settings/mta.html:180
4398
  msgid "Select your provider"
4399
  msgstr ""
4400
 
4401
- #: views/settings/mta.html:205
4402
  msgid "Your web host"
4403
  msgstr ""
4404
 
4405
- #: views/settings/mta.html:221
4406
  msgid "Not listed (default)"
4407
  msgstr ""
4408
 
4409
- #: views/settings/mta.html:241
4410
  msgid "Sending frequency"
4411
  msgstr ""
4412
 
4413
- #: views/settings/mta.html:252
4414
  msgid "Recommended"
4415
  msgstr ""
4416
 
4417
- #: views/settings/mta.html:261
4418
  msgid "I'll set my own frequency"
4419
  msgstr ""
4420
 
4421
- #: views/settings/mta.html:285
4422
  msgid "emails"
4423
  msgstr ""
4424
 
4425
- #: views/settings/mta.html:302
4426
  msgid "recommended"
4427
  msgstr ""
4428
 
4429
- #: views/settings/mta.html:311
4430
  msgid ""
4431
  "<strong>Warning!</strong> You may break the terms of your web host or "
4432
  "provider by sending more than the recommended emails per day. Contact your "
4433
  "host if you want to send more."
4434
  msgstr ""
4435
 
4436
- #: views/settings/mta.html:325
4437
  msgid "SMTP Hostname"
4438
  msgstr ""
4439
 
4440
- #: views/settings/mta.html:328
4441
  msgid "e.g.: smtp.mydomain.com"
4442
  msgstr ""
4443
 
4444
- #: views/settings/mta.html:350
4445
  msgid "SMTP Port"
4446
  msgstr ""
4447
 
4448
- #: views/settings/mta.html:377
4449
  msgid "Region"
4450
  msgstr ""
4451
 
4452
- #: views/settings/mta.html:412
4453
  msgid "Access Key"
4454
  msgstr ""
4455
 
4456
- #: views/settings/mta.html:439
4457
  msgid "Secret Key"
4458
  msgstr ""
4459
 
4460
- #: views/settings/mta.html:466
4461
  msgid "API Key"
4462
  msgstr ""
4463
 
4464
- #: views/settings/mta.html:536
4465
  msgid "Secure Connection"
4466
  msgstr ""
4467
 
4468
- #: views/settings/mta.html:567
4469
  msgid "Authentication"
4470
  msgstr ""
4471
 
4472
- #: views/settings/mta.html:570
4473
  msgid ""
4474
  "Leave this option set to Yes. Only a tiny portion of SMTP services prefer "
4475
  "Authentication to be turned off."
4476
  msgstr ""
4477
 
4478
- #: views/settings/mta.html:609
4479
  msgid "SPF Signature (Highly recommended!)"
4480
  msgstr ""
4481
 
4482
- #: views/settings/mta.html:612
4483
  msgid ""
4484
  "This improves your delivery rate by verifying that you're allowed to send "
4485
  "emails from your domain."
4486
  msgstr ""
4487
 
4488
- #: views/settings/mta.html:617
4489
  msgid ""
4490
  "SPF is set up in your DNS. Read your host's support documentation for more "
4491
  "information."
4492
  msgstr ""
4493
 
4494
- #: views/settings/mta.html:625
4495
  msgid "Test the sending method"
4496
  msgstr ""
4497
 
4498
- #: views/settings/mta.html:639
4499
  msgid "Send a test email"
4500
  msgstr ""
4501
 
4502
- #: views/settings/mta.html:657
4503
  msgid "or Cancel"
4504
  msgstr ""
4505
 
4506
- #: views/settings/mta.html:668
4507
  msgid ""
4508
  "Didn't receive the test email? Read our [link]quick guide[/link] to sending "
4509
  "issues."
4510
  msgstr ""
4511
 
4512
- #: views/settings/mta.html:706
4513
  msgid ""
4514
  "The email could not be sent. Make sure the option \"Email notifications\" "
4515
  "has a FROM email address in the Basics tab."
4516
  msgstr ""
4517
 
4518
- #: views/settings/mta.html:719
4519
  msgid "This is a Sending Method Test"
4520
  msgstr ""
4521
 
4522
- #: views/settings/mta.html:721 views/settings/mta.html:722
4523
  msgid "Yup, it works! You can start blasting away emails to the moon."
4524
  msgstr ""
4525
 
4526
- #: views/settings/mta.html:731
4527
  msgid "The email has been sent! Check your inbox."
4528
  msgstr ""
4529
 
4530
- #: views/settings/mta.html:782
4531
  msgid "You have selected an invalid sending method."
4532
  msgstr ""
4533
 
@@ -4942,8 +4970,8 @@ msgstr ""
4942
 
4943
  #: views/subscribers/subscribers.html:22
4944
  msgid ""
4945
- "Emails that are invalid or don't exist anymore are called \\\"bounced "
4946
- "addresses\\\". It's a good practice not to send emails to bounced addresses "
4947
  "to keep a good reputation with spam filters. Send your emails with MailPoet "
4948
  "and we'll automatically ensure to keep a list of bounced addresses without "
4949
  "any setup."
@@ -5123,7 +5151,7 @@ msgstr ""
5123
  msgid "Care to Give Your Opinion?"
5124
  msgstr ""
5125
 
5126
- #: views/update.html:70 views/welcome.html:71
5127
  msgid "Awesome! Now, take me to MailPoet"
5128
  msgstr ""
5129
 
@@ -5135,65 +5163,76 @@ msgstr ""
5135
  msgid "What's new"
5136
  msgstr ""
5137
 
 
 
 
 
5138
  #: views/welcome.html:29
 
 
 
 
 
 
 
 
5139
  msgid "Want to Make MailPoet Even Better?"
5140
  msgstr ""
5141
 
5142
- #: views/welcome.html:31
5143
- msgid "We Need Your Feedback!"
5144
  msgstr ""
5145
 
5146
- #: views/welcome.html:32
5147
  msgid ""
5148
- "As a beta tester, you have a very important job: to tell us what you think "
5149
- "about this new version. If you love it, tell us! If you hate it, let us "
5150
- "know! Any and all feedback is useful."
5151
  msgstr ""
5152
 
5153
- #: views/welcome.html:33
5154
- msgid ""
5155
- "To get in touch with us, simply click on the blue circle in the bottom "
5156
- "right corner of your screen. This button is visible on all MailPoet pages "
5157
- "on your WordPress dashboard."
5158
  msgstr ""
5159
 
5160
- #: views/welcome.html:36
5161
  msgid "Sharing is Caring"
5162
  msgstr ""
5163
 
5164
- #: views/welcome.html:37
5165
  msgid ""
5166
  "By sharing your data <i>anonymously</i> with us, you can help us understand "
5167
- "<i>how people use MailPoet</i> and <i>what sort of features they like and "
5168
- "don't like</i>."
 
 
 
5169
  msgstr ""
5170
 
5171
- #: views/welcome.html:42
5172
  msgid "Yes, I want to help!"
5173
  msgstr ""
5174
 
5175
- #: views/welcome.html:52 views/welcome.html:56
5176
  msgid "Subscribe To Our Newsletter"
5177
  msgstr ""
5178
 
5179
- #: views/welcome.html:53
5180
  msgid "About once a month, we send out a pretty cool newsletter ourselves."
5181
  msgstr ""
5182
 
5183
- #: views/welcome.html:54
5184
  msgid ""
5185
  "Sign up to get a curated selection of awesome links, tips and tricks for "
5186
  "using MailPoet, special offers, and important plugin updates!"
5187
  msgstr ""
5188
 
5189
- #: views/welcome.html:60
5190
  msgid "Learn the Ropes"
5191
  msgstr ""
5192
 
5193
- #: views/welcome.html:61
5194
  msgid ""
5195
- "New to MailPoet? Check out our brand new email course. Over the span of 3 "
5196
- "weeks, we'll teach you how to create and send your first MailPoet email "
5197
  "newsletter. Sign up below!"
5198
  msgstr ""
5199
 
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
7
+ "POT-Creation-Date: 2017-09-20 14:26:19+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
1031
  msgid "An error has happened while performing a request, please try again later."
1032
  msgstr ""
1033
 
1034
+ #: lib/Cron/CronHelper.php:116
1035
  msgid "Site URL is unreachable."
1036
  msgstr ""
1037
 
1038
+ #: lib/Cron/CronHelper.php:122
1039
  msgid "Maximum execution time has been reached."
1040
  msgstr ""
1041
 
1042
+ #: lib/Cron/Daemon.php:31
1043
  msgid "Invalid or missing request data."
1044
  msgstr ""
1045
 
1046
+ #: lib/Cron/Daemon.php:34
1047
  msgid "Daemon does not exist."
1048
  msgstr ""
1049
 
1669
  msgid "Accidentally unsubscribed?"
1670
  msgstr ""
1671
 
1672
+ #: lib/Twig/Functions.php:101 views/settings/mta.html:1086
1673
  msgid "every minute"
1674
  msgstr ""
1675
 
1676
+ #: lib/Twig/Functions.php:102 views/settings/mta.html:1087
1677
  msgid "every %1$d minutes"
1678
  msgstr ""
1679
 
1680
+ #: lib/Twig/Functions.php:103 views/settings/mta.html:1088
1681
  msgid "every hour"
1682
  msgstr ""
1683
 
1684
+ #: lib/Twig/Functions.php:104 views/settings/mta.html:1089
1685
  msgid "every %1$d hours"
1686
  msgstr ""
1687
 
1875
  #: views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs:221
1876
  #: views/premium.html:56 views/settings/advanced.html:90
1877
  #: views/settings/advanced.html:130 views/settings/bounce.html:190
1878
+ #: views/settings/mta.html:589 views/settings/signup.html:34
1879
  #: views/subscribers/importExport/export.html:33
1880
  #: views/subscribers/importExport/import/step2.html:63
1881
  msgid "Yes"
1894
  #: views/newsletter/templates/blocks/posts/settingsDisplayOptions.hbs:227
1895
  #: views/premium.html:62 views/premium.html:63 views/settings/advanced.html:101
1896
  #: views/settings/advanced.html:141 views/settings/bounce.html:148
1897
+ #: views/settings/bounce.html:179 views/settings/mta.html:546
1898
+ #: views/settings/mta.html:600 views/settings/signup.html:46
1899
  #: views/subscribers/importExport/export.html:38
1900
  #: views/subscribers/importExport/import/step2.html:67
1901
  msgid "No"
3265
 
3266
  #: views/newsletters.html:100
3267
  msgid ""
3268
+ "Above 30% is excellent.\\n"
3269
+ "Between 10 and 30% is good.\\n"
3270
  "Under 10% is bad."
3271
  msgstr ""
3272
 
3273
  #: views/newsletters.html:101
3274
  msgid ""
3275
+ "Above 3% is excellent.\\n"
3276
+ "Between 1 and 3% is good.\\n"
3277
  "Under 1% is bad."
3278
  msgstr ""
3279
 
3280
  #: views/newsletters.html:102
3281
  msgid ""
3282
+ "Under 1% is excellent.\\n"
3283
+ "Between 1 and 3% is good.\\n"
3284
  "Over 3% is bad."
3285
  msgstr ""
3286
 
3383
  "number."
3384
  msgstr ""
3385
 
3386
+ #: views/newsletters.html:132 views/settings/mta.html:111
3387
+ #: views/settings/mta.html:657
3388
  msgid "Activate"
3389
  msgstr ""
3390
 
4242
  msgid "Hostname"
4243
  msgstr ""
4244
 
4245
+ #: views/settings/bounce.html:50 views/settings/mta.html:495
4246
  msgid "Login"
4247
  msgstr ""
4248
 
4249
+ #: views/settings/bounce.html:67 views/settings/mta.html:518
4250
  msgid "Password"
4251
  msgstr ""
4252
 
4298
  msgid "Is it working? Try to connect"
4299
  msgstr ""
4300
 
4301
+ #: views/settings/mta.html:64
4302
+ msgid "MailPoet Sending Service"
4303
+ msgstr ""
4304
+
4305
+ #: views/settings/mta.html:71
4306
  msgid "You're now sending with MailPoet!"
4307
  msgstr ""
4308
 
4309
+ #: views/settings/mta.html:73
4310
  msgid "Great, you're all set up. Your emails will now be sent quickly and reliably!"
4311
  msgstr ""
4312
 
4313
+ #: views/settings/mta.html:80
4314
  msgid "Solve all of your sending problems!"
4315
  msgstr ""
4316
 
4317
+ #: views/settings/mta.html:83
 
 
 
 
 
 
4318
  msgid "Reach the inbox, not the spam box."
4319
  msgstr ""
4320
 
4321
+ #: views/settings/mta.html:84
4322
+ msgid "Super fast: send up to 50,000 emails per hour."
4323
  msgstr ""
4324
 
4325
+ #: views/settings/mta.html:85
4326
+ msgid "All emails are signed with SPF & DKIM."
4327
  msgstr ""
4328
 
4329
+ #: views/settings/mta.html:86
4330
  msgid ""
4331
  "Automatically remove invalid and bounced addresses (bounce handling) to "
4332
  "keep your lists clean."
4333
  msgstr ""
4334
 
4335
+ #: views/settings/mta.html:87
4336
+ msgid ""
4337
+ "Configuration is dead-simple: simply enter a key to activate the sending "
4338
+ "service."
4339
  msgstr ""
4340
 
4341
+ #: views/settings/mta.html:88
4342
+ msgid "Coming soon:"
4343
  msgstr ""
4344
 
4345
+ #: views/settings/mta.html:88
4346
+ msgid "MailPoet will send your WordPress site and account emails, too!"
4347
+ msgstr ""
4348
+
4349
+ #: views/settings/mta.html:89
4350
+ msgid "Plus:"
4351
+ msgstr ""
4352
+
4353
+ #: views/settings/mta.html:89
4354
+ msgid "get the Premium features for free."
4355
+ msgstr ""
4356
+
4357
+ #: views/settings/mta.html:96
4358
+ msgid "Find out more about our monthly plans"
4359
+ msgstr ""
4360
+
4361
+ #: views/settings/mta.html:99
4362
+ msgid "new!"
4363
+ msgstr ""
4364
+
4365
+ #: views/settings/mta.html:99
4366
+ msgid "Try it for free (for up to 2,000 subscribers)"
4367
+ msgstr ""
4368
+
4369
+ #: views/settings/mta.html:104 views/settings/mta.html:138
4370
+ msgid "Activated"
4371
  msgstr ""
4372
 
4373
  #: views/settings/mta.html:121
4374
+ msgid "Other"
4375
  msgstr ""
4376
 
4377
  #: views/settings/mta.html:123
4378
+ msgid "Send emails via your host (not recommended!) or via a third-party sender."
 
 
4379
  msgstr ""
4380
 
4381
  #: views/settings/mta.html:125
4382
+ msgid "Unless you're a pro, you’ll probably end up in spam."
4383
  msgstr ""
4384
 
4385
  #: views/settings/mta.html:126
4386
+ msgid ""
4387
+ "Sending speed is limited by your host and/or your third-party (with a 2,000 "
4388
+ "per hour maximum)."
4389
  msgstr ""
4390
 
4391
  #: views/settings/mta.html:127
4392
  msgid "Manual configuration of SPF and DKIM required."
4393
  msgstr ""
4394
 
4395
+ #: views/settings/mta.html:129
4396
+ msgid "Bounce handling is available, but only with an extra [link]add-on[/link]."
4397
  msgstr ""
4398
 
4399
+ #: views/settings/mta.html:133
4400
+ msgid "You’ll need a separate plugin to send your WordPress site emails (optional)."
4401
+ msgstr ""
4402
+
4403
+ #: views/settings/mta.html:142
4404
  msgid "Configure"
4405
  msgstr ""
4406
 
4407
+ #: views/settings/mta.html:149
4408
  msgid ""
4409
  "Need help to pick? [link]Check out the comparison table of sending "
4410
  "methods[/link]."
4411
  msgstr ""
4412
 
4413
+ #: views/settings/mta.html:163
4414
  msgid "Method"
4415
  msgstr ""
4416
 
4417
+ #: views/settings/mta.html:173
4418
  msgid "Your web host / web server"
4419
  msgstr ""
4420
 
4421
+ #: views/settings/mta.html:182
4422
  msgid "SMTP"
4423
  msgstr ""
4424
 
4425
+ #: views/settings/mta.html:185
4426
  msgid "Select your provider"
4427
  msgstr ""
4428
 
4429
+ #: views/settings/mta.html:210
4430
  msgid "Your web host"
4431
  msgstr ""
4432
 
4433
+ #: views/settings/mta.html:226
4434
  msgid "Not listed (default)"
4435
  msgstr ""
4436
 
4437
+ #: views/settings/mta.html:246
4438
  msgid "Sending frequency"
4439
  msgstr ""
4440
 
4441
+ #: views/settings/mta.html:257
4442
  msgid "Recommended"
4443
  msgstr ""
4444
 
4445
+ #: views/settings/mta.html:266
4446
  msgid "I'll set my own frequency"
4447
  msgstr ""
4448
 
4449
+ #: views/settings/mta.html:290
4450
  msgid "emails"
4451
  msgstr ""
4452
 
4453
+ #: views/settings/mta.html:307
4454
  msgid "recommended"
4455
  msgstr ""
4456
 
4457
+ #: views/settings/mta.html:316
4458
  msgid ""
4459
  "<strong>Warning!</strong> You may break the terms of your web host or "
4460
  "provider by sending more than the recommended emails per day. Contact your "
4461
  "host if you want to send more."
4462
  msgstr ""
4463
 
4464
+ #: views/settings/mta.html:330
4465
  msgid "SMTP Hostname"
4466
  msgstr ""
4467
 
4468
+ #: views/settings/mta.html:333
4469
  msgid "e.g.: smtp.mydomain.com"
4470
  msgstr ""
4471
 
4472
+ #: views/settings/mta.html:355
4473
  msgid "SMTP Port"
4474
  msgstr ""
4475
 
4476
+ #: views/settings/mta.html:382
4477
  msgid "Region"
4478
  msgstr ""
4479
 
4480
+ #: views/settings/mta.html:417
4481
  msgid "Access Key"
4482
  msgstr ""
4483
 
4484
+ #: views/settings/mta.html:444
4485
  msgid "Secret Key"
4486
  msgstr ""
4487
 
4488
+ #: views/settings/mta.html:471
4489
  msgid "API Key"
4490
  msgstr ""
4491
 
4492
+ #: views/settings/mta.html:541
4493
  msgid "Secure Connection"
4494
  msgstr ""
4495
 
4496
+ #: views/settings/mta.html:572
4497
  msgid "Authentication"
4498
  msgstr ""
4499
 
4500
+ #: views/settings/mta.html:575
4501
  msgid ""
4502
  "Leave this option set to Yes. Only a tiny portion of SMTP services prefer "
4503
  "Authentication to be turned off."
4504
  msgstr ""
4505
 
4506
+ #: views/settings/mta.html:614
4507
  msgid "SPF Signature (Highly recommended!)"
4508
  msgstr ""
4509
 
4510
+ #: views/settings/mta.html:617
4511
  msgid ""
4512
  "This improves your delivery rate by verifying that you're allowed to send "
4513
  "emails from your domain."
4514
  msgstr ""
4515
 
4516
+ #: views/settings/mta.html:622
4517
  msgid ""
4518
  "SPF is set up in your DNS. Read your host's support documentation for more "
4519
  "information."
4520
  msgstr ""
4521
 
4522
+ #: views/settings/mta.html:630
4523
  msgid "Test the sending method"
4524
  msgstr ""
4525
 
4526
+ #: views/settings/mta.html:644
4527
  msgid "Send a test email"
4528
  msgstr ""
4529
 
4530
+ #: views/settings/mta.html:662
4531
  msgid "or Cancel"
4532
  msgstr ""
4533
 
4534
+ #: views/settings/mta.html:673
4535
  msgid ""
4536
  "Didn't receive the test email? Read our [link]quick guide[/link] to sending "
4537
  "issues."
4538
  msgstr ""
4539
 
4540
+ #: views/settings/mta.html:711
4541
  msgid ""
4542
  "The email could not be sent. Make sure the option \"Email notifications\" "
4543
  "has a FROM email address in the Basics tab."
4544
  msgstr ""
4545
 
4546
+ #: views/settings/mta.html:724
4547
  msgid "This is a Sending Method Test"
4548
  msgstr ""
4549
 
4550
+ #: views/settings/mta.html:726 views/settings/mta.html:727
4551
  msgid "Yup, it works! You can start blasting away emails to the moon."
4552
  msgstr ""
4553
 
4554
+ #: views/settings/mta.html:736
4555
  msgid "The email has been sent! Check your inbox."
4556
  msgstr ""
4557
 
4558
+ #: views/settings/mta.html:787
4559
  msgid "You have selected an invalid sending method."
4560
  msgstr ""
4561
 
4970
 
4971
  #: views/subscribers/subscribers.html:22
4972
  msgid ""
4973
+ "Emails that are invalid or don't exist anymore are called \"bounced "
4974
+ "addresses\". It's a good practice not to send emails to bounced addresses "
4975
  "to keep a good reputation with spam filters. Send your emails with MailPoet "
4976
  "and we'll automatically ensure to keep a list of bounced addresses without "
4977
  "any setup."
5151
  msgid "Care to Give Your Opinion?"
5152
  msgstr ""
5153
 
5154
+ #: views/update.html:80 views/welcome.html:93
5155
  msgid "Awesome! Now, take me to MailPoet"
5156
  msgstr ""
5157
 
5163
  msgid "What's new"
5164
  msgstr ""
5165
 
5166
+ #: views/welcome.html:23
5167
+ msgid "Coming this Fall to a WordPress plugin page near you"
5168
+ msgstr ""
5169
+
5170
  #: views/welcome.html:29
5171
+ msgid "But first, watch this video"
5172
+ msgstr ""
5173
+
5174
+ #: views/welcome.html:36
5175
+ msgid "Explanatory videos are boring, we know"
5176
+ msgstr ""
5177
+
5178
+ #: views/welcome.html:52
5179
  msgid "Want to Make MailPoet Even Better?"
5180
  msgstr ""
5181
 
5182
+ #: views/welcome.html:54
5183
+ msgid "Documentation Is One Click Away"
5184
  msgstr ""
5185
 
5186
+ #: views/welcome.html:55
5187
  msgid ""
5188
+ "Simply click on the blue circle in the bottom right corner of any of the "
5189
+ "MailPoet pages to access our documentation."
 
5190
  msgstr ""
5191
 
5192
+ #: views/welcome.html:55
5193
+ msgid "Voilà!"
 
 
 
5194
  msgstr ""
5195
 
5196
+ #: views/welcome.html:58
5197
  msgid "Sharing is Caring"
5198
  msgstr ""
5199
 
5200
+ #: views/welcome.html:59
5201
  msgid ""
5202
  "By sharing your data <i>anonymously</i> with us, you can help us understand "
5203
+ "how people use MailPoet and what sort of features they like and don't like."
5204
+ msgstr ""
5205
+
5206
+ #: views/welcome.html:59
5207
+ msgid "Find out more"
5208
  msgstr ""
5209
 
5210
+ #: views/welcome.html:64
5211
  msgid "Yes, I want to help!"
5212
  msgstr ""
5213
 
5214
+ #: views/welcome.html:74 views/welcome.html:78
5215
  msgid "Subscribe To Our Newsletter"
5216
  msgstr ""
5217
 
5218
+ #: views/welcome.html:75
5219
  msgid "About once a month, we send out a pretty cool newsletter ourselves."
5220
  msgstr ""
5221
 
5222
+ #: views/welcome.html:76
5223
  msgid ""
5224
  "Sign up to get a curated selection of awesome links, tips and tricks for "
5225
  "using MailPoet, special offers, and important plugin updates!"
5226
  msgstr ""
5227
 
5228
+ #: views/welcome.html:82
5229
  msgid "Learn the Ropes"
5230
  msgstr ""
5231
 
5232
+ #: views/welcome.html:83
5233
  msgid ""
5234
+ "New to MailPoet? Check out our brand new email course. Over the course of a "
5235
+ "week, we'll teach you how to create and send your first MailPoet email "
5236
  "newsletter. Sign up below!"
5237
  msgstr ""
5238
 
lib/Config/RequirementsChecker.php CHANGED
@@ -13,6 +13,7 @@ class RequirementsChecker {
13
  const TEST_XML_EXTENSION = 'XmlExtension';
14
  const TEST_ZIP_EXTENSION = 'ZipExtension';
15
  const TEST_VENDOR_SOURCE = 'VendorSource';
 
16
 
17
  public $display_error_notice;
18
  public $vendor_classes = array(
@@ -22,7 +23,6 @@ class RequirementsChecker {
22
  '\Twig_Loader_Filesystem',
23
  '\Twig_Lexer',
24
  '\Twig_Extension',
25
- '\Twig_Extension_GlobalsInterface',
26
  '\Twig_SimpleFunction',
27
  '\Swift_Mailer',
28
  '\Swift_SmtpTransport',
@@ -141,13 +141,30 @@ class RequirementsChecker {
141
  $dependency_path
142
  );
143
 
144
- return $this->processError($error);
 
 
 
 
 
 
 
145
  }
146
  }
147
 
148
  return true;
149
  }
150
 
 
 
 
 
 
 
 
 
 
 
151
  private function getDependencyPath($namespaced_class) {
152
  try {
153
  $reflector = new \ReflectionClass($namespaced_class);
@@ -163,4 +180,4 @@ class RequirementsChecker {
163
  }
164
  return false;
165
  }
166
- }
13
  const TEST_XML_EXTENSION = 'XmlExtension';
14
  const TEST_ZIP_EXTENSION = 'ZipExtension';
15
  const TEST_VENDOR_SOURCE = 'VendorSource';
16
+ const TWIG_SUPPORTED_VERSIONS = '1.26.0-1.34.4';
17
 
18
  public $display_error_notice;
19
  public $vendor_classes = array(
23
  '\Twig_Loader_Filesystem',
24
  '\Twig_Lexer',
25
  '\Twig_Extension',
 
26
  '\Twig_SimpleFunction',
27
  '\Swift_Mailer',
28
  '\Swift_SmtpTransport',
141
  $dependency_path
142
  );
143
 
144
+ $return_error = true;
145
+
146
+ // if a Twig dependency is loaded by another plugin, check for valid version
147
+ if(strpos($dependency, '\Twig_') === 0) {
148
+ $return_error = ($this->isValidTwigVersion()) ? false : $return_error;
149
+ }
150
+
151
+ if($return_error) return $this->processError($error);
152
  }
153
  }
154
 
155
  return true;
156
  }
157
 
158
+ function isValidTwigVersion() {
159
+ list($minimum_version, $maximum_version) = explode('-', self::TWIG_SUPPORTED_VERSIONS);
160
+ return (
161
+ class_exists('\Twig_Environment') &&
162
+ defined('\Twig_Environment::VERSION') &&
163
+ version_compare(\Twig_Environment::VERSION, $minimum_version, '>=') &&
164
+ version_compare(\Twig_Environment::VERSION, $maximum_version, '<=')
165
+ );
166
+ }
167
+
168
  private function getDependencyPath($namespaced_class) {
169
  try {
170
  $reflector = new \ReflectionClass($namespaced_class);
180
  }
181
  return false;
182
  }
183
+ }
lib/Cron/CronHelper.php CHANGED
@@ -13,7 +13,7 @@ if(!defined('ABSPATH')) exit;
13
  class CronHelper {
14
  const DAEMON_EXECUTION_LIMIT = 20; // seconds
15
  const DAEMON_EXECUTION_TIMEOUT = 35; // seconds
16
- const DAEMON_REQUEST_TIMEOUT = 2; // seconds
17
  const DAEMON_SETTING = 'cron_daemon';
18
 
19
  static function createDaemon($token) {
@@ -49,45 +49,53 @@ class CronHelper {
49
  }
50
 
51
  static function pingDaemon() {
52
- $url = Router::buildRequest(
53
- CronDaemonEndpoint::ENDPOINT,
54
  CronDaemonEndpoint::ACTION_PING_RESPONSE
55
  );
56
- $url = str_replace(home_url(), self::getSiteUrl(), $url);
57
- $args = array(
58
- 'blocking' => true,
59
- 'sslverify' => false,
60
- 'timeout' => self::DAEMON_REQUEST_TIMEOUT,
61
- 'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
 
 
 
 
 
62
  );
63
- $result = wp_remote_get($url, $args);
64
  return wp_remote_retrieve_body($result);
65
  }
66
 
67
- static function accessDaemon($token, $timeout = self::DAEMON_REQUEST_TIMEOUT) {
68
- $data = array('token' => $token);
 
 
 
 
 
 
 
 
 
 
 
 
69
  $url = Router::buildRequest(
70
  CronDaemonEndpoint::ENDPOINT,
71
- CronDaemonEndpoint::ACTION_RUN,
72
  $data
73
  );
74
- $url = str_replace(home_url(), self::getSiteUrl(), $url);
75
- $args = array(
76
- 'blocking' => true,
77
- 'sslverify' => false,
78
- 'timeout' => $timeout,
79
- 'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
80
- );
81
- $result = wp_remote_get($url, $args);
82
- return wp_remote_retrieve_body($result);
83
  }
84
 
85
  static function getSiteUrl($site_url = false) {
86
  // additional check for some sites running inside a virtual machine or behind
87
  // proxy where there could be different ports (e.g., host:8080 => guest:80)
88
- $custom_cron_url = WPHooks::applyFilters('mailpoet_cron_request_url', null);
89
- if($custom_cron_url) return $custom_cron_url;
90
-
91
  $site_url = ($site_url) ? $site_url : home_url();
92
  $parsed_url = parse_url($site_url);
93
  $scheme = '';
13
  class CronHelper {
14
  const DAEMON_EXECUTION_LIMIT = 20; // seconds
15
  const DAEMON_EXECUTION_TIMEOUT = 35; // seconds
16
+ const DAEMON_REQUEST_TIMEOUT = 5; // seconds
17
  const DAEMON_SETTING = 'cron_daemon';
18
 
19
  static function createDaemon($token) {
49
  }
50
 
51
  static function pingDaemon() {
52
+ $url = self::getCronUrl(
 
53
  CronDaemonEndpoint::ACTION_PING_RESPONSE
54
  );
55
+ $result = self::queryCronUrl($url);
56
+ return (is_wp_error($result)) ?
57
+ $result->get_error_message() :
58
+ wp_remote_retrieve_body($result);
59
+ }
60
+
61
+ static function accessDaemon($token) {
62
+ $data = array('token' => $token);
63
+ $url = self::getCronUrl(
64
+ CronDaemonEndpoint::ACTION_RUN,
65
+ $data
66
  );
67
+ $result = self::queryCronUrl($url);
68
  return wp_remote_retrieve_body($result);
69
  }
70
 
71
+ static function queryCronUrl($url) {
72
+ $args = WPHooks::applyFilters(
73
+ 'mailpoet_cron_request_args',
74
+ array(
75
+ 'blocking' => true,
76
+ 'sslverify' => false,
77
+ 'timeout' => self::DAEMON_REQUEST_TIMEOUT,
78
+ 'user-agent' => 'MailPoet Cron'
79
+ )
80
+ );
81
+ return wp_remote_get($url, $args);
82
+ }
83
+
84
+ static function getCronUrl($action, $data = false) {
85
  $url = Router::buildRequest(
86
  CronDaemonEndpoint::ENDPOINT,
87
+ $action,
88
  $data
89
  );
90
+ $custom_cron_url = WPHooks::applyFilters('mailpoet_cron_request_url', $url);
91
+ return ($custom_cron_url === $url) ?
92
+ str_replace(home_url(), self::getSiteUrl(), $url) :
93
+ $custom_cron_url;
 
 
 
 
 
94
  }
95
 
96
  static function getSiteUrl($site_url = false) {
97
  // additional check for some sites running inside a virtual machine or behind
98
  // proxy where there could be different ports (e.g., host:8080 => guest:80)
 
 
 
99
  $site_url = ($site_url) ? $site_url : home_url();
100
  $parsed_url = parse_url($site_url);
101
  $scheme = '';
lib/Cron/Daemon.php CHANGED
@@ -13,7 +13,6 @@ class Daemon {
13
  public $daemon;
14
  public $request_data;
15
  public $timer;
16
- const REQUEST_TIMEOUT = 5; // seconds
17
 
18
  function __construct($request_data = false) {
19
  $this->request_data = $request_data;
@@ -100,7 +99,7 @@ class Daemon {
100
  }
101
 
102
  function callSelf() {
103
- CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
104
  return $this->terminateRequest();
105
  }
106
 
13
  public $daemon;
14
  public $request_data;
15
  public $timer;
 
16
 
17
  function __construct($request_data = false) {
18
  $this->request_data = $request_data;
99
  }
100
 
101
  function callSelf() {
102
+ CronHelper::accessDaemon($this->token);
103
  return $this->terminateRequest();
104
  }
105
 
lib/Helpscout/Beacon.php CHANGED
@@ -5,6 +5,7 @@ use MailPoet\Models\Subscriber;
5
  use MailPoet\Models\Setting;
6
  use MailPoet\Router\Endpoints\CronDaemon;
7
  use MailPoet\Router\Router;
 
8
 
9
  if(!defined('ABSPATH')) exit;
10
 
@@ -20,12 +21,14 @@ class Beacon {
20
  CronDaemon::ACTION_PING
21
  );
22
  $cron_ping_url = str_replace(home_url(), CronHelper::getSiteUrl(), $cron_ping_url);
 
23
  return array(
24
  'name' => $current_user->display_name,
25
  'email' => $current_user->user_email,
26
  'PHP version' => PHP_VERSION,
27
  'MailPoet Free version' => MAILPOET_VERSION,
28
  'MailPoet Premium version' => (defined('MAILPOET_PREMIUM_VERSION')) ? MAILPOET_PREMIUM_VERSION : 'N/A',
 
29
  'WordPress version' => get_bloginfo('version'),
30
  'Database version' => $db_version,
31
  'Web server' => (!empty($_SERVER["SERVER_SOFTWARE"])) ? $_SERVER["SERVER_SOFTWARE"] : 'N/A',
5
  use MailPoet\Models\Setting;
6
  use MailPoet\Router\Endpoints\CronDaemon;
7
  use MailPoet\Router\Router;
8
+ use MailPoet\Services\Bridge;
9
 
10
  if(!defined('ABSPATH')) exit;
11
 
21
  CronDaemon::ACTION_PING
22
  );
23
  $cron_ping_url = str_replace(home_url(), CronHelper::getSiteUrl(), $cron_ping_url);
24
+ $premium_key = Setting::getValue(Bridge::PREMIUM_KEY_SETTING_NAME) ?: Setting::getValue(Bridge::API_KEY_SETTING_NAME);
25
  return array(
26
  'name' => $current_user->display_name,
27
  'email' => $current_user->user_email,
28
  'PHP version' => PHP_VERSION,
29
  'MailPoet Free version' => MAILPOET_VERSION,
30
  'MailPoet Premium version' => (defined('MAILPOET_PREMIUM_VERSION')) ? MAILPOET_PREMIUM_VERSION : 'N/A',
31
+ 'MailPoet Premium/MSS key' => $premium_key,
32
  'WordPress version' => get_bloginfo('version'),
33
  'Database version' => $db_version,
34
  'Web server' => (!empty($_SERVER["SERVER_SOFTWARE"])) ? $_SERVER["SERVER_SOFTWARE"] : 'N/A',
lib/Segments/WP.php CHANGED
@@ -97,10 +97,10 @@ class WP {
97
  $subscribers_table = Subscriber::$_table;
98
  Subscriber::raw_execute(sprintf('
99
  UPDATE IGNORE %s
100
- JOIN %susers as wu ON %s.wp_user_id = wu.id
101
  SET email = user_email
102
  WHERE %s.wp_user_id IS NOT NULL
103
- ', $subscribers_table, $wpdb->prefix, $subscribers_table, $subscribers_table));
104
  }
105
 
106
  private static function insertSubscribers() {
@@ -108,10 +108,10 @@ class WP {
108
  $subscribers_table = Subscriber::$_table;
109
  Subscriber::raw_execute(sprintf('
110
  INSERT IGNORE INTO %s(wp_user_id, email, status, created_at)
111
- SELECT wu.id, wu.user_email, "subscribed", CURRENT_TIMESTAMP() FROM %susers wu
112
  LEFT JOIN %s mps ON wu.id = mps.wp_user_id
113
  WHERE mps.wp_user_id IS NULL
114
- ', $subscribers_table, $wpdb->prefix, $subscribers_table));
115
  }
116
 
117
  private static function updateFirstNames() {
@@ -119,11 +119,11 @@ class WP {
119
  $subscribers_table = Subscriber::$_table;
120
  Subscriber::raw_execute(sprintf('
121
  UPDATE %s
122
- JOIN %susermeta as wpum ON %s.wp_user_id = wpum.user_id AND meta_key = "first_name"
123
  SET first_name = meta_value
124
  WHERE %s.first_name = ""
125
  AND %s.wp_user_id IS NOT NULL
126
- ', $subscribers_table, $wpdb->prefix, $subscribers_table, $subscribers_table, $subscribers_table));
127
  }
128
 
129
  private static function updateLastNames() {
@@ -131,11 +131,11 @@ class WP {
131
  $subscribers_table = Subscriber::$_table;
132
  Subscriber::raw_execute(sprintf('
133
  UPDATE %s
134
- JOIN %susermeta as wpum ON %s.wp_user_id = wpum.user_id AND meta_key = "last_name"
135
  SET last_name = meta_value
136
  WHERE %s.last_name = ""
137
  AND %s.wp_user_id IS NOT NULL
138
- ', $subscribers_table, $wpdb->prefix, $subscribers_table, $subscribers_table, $subscribers_table));
139
  }
140
 
141
  private static function updateFristNameIfMissing() {
@@ -143,11 +143,11 @@ class WP {
143
  $subscribers_table = Subscriber::$_table;
144
  Subscriber::raw_execute(sprintf('
145
  UPDATE %s
146
- JOIN %susers wu ON %s.wp_user_id = wu.id
147
  SET first_name = display_name
148
  WHERE %s.first_name = ""
149
  AND %s.wp_user_id IS NOT NULL
150
- ', $subscribers_table, $wpdb->prefix, $subscribers_table, $subscribers_table, $subscribers_table));
151
  }
152
 
153
  private static function insertUsersToSegment() {
@@ -157,14 +157,14 @@ class WP {
157
  Subscriber::raw_execute(sprintf('
158
  INSERT IGNORE INTO %s(subscriber_id, segment_id, created_at)
159
  SELECT mps.id, "%s", CURRENT_TIMESTAMP() FROM %s mps
160
- WHERE mps.wp_user_id IS NOT NULL
161
  ', $wp_mailpoet_subscriber_segment_table, $wp_segment->id, $subscribers_table));
162
  }
163
 
164
  private static function removeFromTrash() {
165
  $subscribers_table = Subscriber::$_table;
166
  Subscriber::raw_execute(sprintf('
167
- UPDATE %s
168
  SET deleted_at = NULL
169
  WHERE %s.wp_user_id IS NOT NULL
170
  ', $subscribers_table, $subscribers_table));
@@ -175,13 +175,13 @@ class WP {
175
  // e.g. if wp users were deleted directly from the database
176
  global $wpdb;
177
 
178
- Subscriber::table_alias('wpms')
179
- ->leftOuterJoin($wpdb->prefix . 'users', array('wpms.wp_user_id', '=', 'wu.id'), 'wu')
 
 
180
  ->whereNull('wu.id')
181
  ->findResultSet()
182
  ->set('wp_user_id', null)
183
  ->delete();
184
-
185
  }
186
  }
187
-
97
  $subscribers_table = Subscriber::$_table;
98
  Subscriber::raw_execute(sprintf('
99
  UPDATE IGNORE %s
100
+ JOIN %s as wu ON %s.wp_user_id = wu.id
101
  SET email = user_email
102
  WHERE %s.wp_user_id IS NOT NULL
103
+ ', $subscribers_table, $wpdb->users, $subscribers_table, $subscribers_table));
104
  }
105
 
106
  private static function insertSubscribers() {
108
  $subscribers_table = Subscriber::$_table;
109
  Subscriber::raw_execute(sprintf('
110
  INSERT IGNORE INTO %s(wp_user_id, email, status, created_at)
111
+ SELECT wu.id, wu.user_email, "subscribed", CURRENT_TIMESTAMP() FROM %s wu
112
  LEFT JOIN %s mps ON wu.id = mps.wp_user_id
113
  WHERE mps.wp_user_id IS NULL
114
+ ', $subscribers_table, $wpdb->users, $subscribers_table));
115
  }
116
 
117
  private static function updateFirstNames() {
119
  $subscribers_table = Subscriber::$_table;
120
  Subscriber::raw_execute(sprintf('
121
  UPDATE %s
122
+ JOIN %s as wpum ON %s.wp_user_id = wpum.user_id AND meta_key = "first_name"
123
  SET first_name = meta_value
124
  WHERE %s.first_name = ""
125
  AND %s.wp_user_id IS NOT NULL
126
+ ', $subscribers_table, $wpdb->usermeta, $subscribers_table, $subscribers_table, $subscribers_table));
127
  }
128
 
129
  private static function updateLastNames() {
131
  $subscribers_table = Subscriber::$_table;
132
  Subscriber::raw_execute(sprintf('
133
  UPDATE %s
134
+ JOIN %s as wpum ON %s.wp_user_id = wpum.user_id AND meta_key = "last_name"
135
  SET last_name = meta_value
136
  WHERE %s.last_name = ""
137
  AND %s.wp_user_id IS NOT NULL
138
+ ', $subscribers_table, $wpdb->usermeta, $subscribers_table, $subscribers_table, $subscribers_table));
139
  }
140
 
141
  private static function updateFristNameIfMissing() {
143
  $subscribers_table = Subscriber::$_table;
144
  Subscriber::raw_execute(sprintf('
145
  UPDATE %s
146
+ JOIN %s wu ON %s.wp_user_id = wu.id
147
  SET first_name = display_name
148
  WHERE %s.first_name = ""
149
  AND %s.wp_user_id IS NOT NULL
150
+ ', $subscribers_table, $wpdb->users, $subscribers_table, $subscribers_table, $subscribers_table));
151
  }
152
 
153
  private static function insertUsersToSegment() {
157
  Subscriber::raw_execute(sprintf('
158
  INSERT IGNORE INTO %s(subscriber_id, segment_id, created_at)
159
  SELECT mps.id, "%s", CURRENT_TIMESTAMP() FROM %s mps
160
+ WHERE mps.wp_user_id > 0
161
  ', $wp_mailpoet_subscriber_segment_table, $wp_segment->id, $subscribers_table));
162
  }
163
 
164
  private static function removeFromTrash() {
165
  $subscribers_table = Subscriber::$_table;
166
  Subscriber::raw_execute(sprintf('
167
+ UPDATE %s
168
  SET deleted_at = NULL
169
  WHERE %s.wp_user_id IS NOT NULL
170
  ', $subscribers_table, $subscribers_table));
175
  // e.g. if wp users were deleted directly from the database
176
  global $wpdb;
177
 
178
+ $wp_segment = Segment::getWPSegment();
179
+
180
+ $wp_segment->subscribers()
181
+ ->leftOuterJoin($wpdb->users, array(MP_SUBSCRIBERS_TABLE . '.wp_user_id', '=', 'wu.id'), 'wu')
182
  ->whereNull('wu.id')
183
  ->findResultSet()
184
  ->set('wp_user_id', null)
185
  ->delete();
 
186
  }
187
  }
 
lib/Twig/Analytics.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  namespace MailPoet\Twig;
3
 
4
  use MailPoet\Analytics\Reporter;
@@ -7,11 +8,6 @@ use MailPoet\Analytics\Analytics as AnalyticsGenerator;
7
  if(!defined('ABSPATH')) exit;
8
 
9
  class Analytics extends \Twig_Extension {
10
-
11
- public function getName() {
12
- return 'analytics';
13
- }
14
-
15
  public function getFunctions() {
16
  $analytics = new AnalyticsGenerator(new Reporter());
17
  return array(
1
  <?php
2
+
3
  namespace MailPoet\Twig;
4
 
5
  use MailPoet\Analytics\Reporter;
8
  if(!defined('ABSPATH')) exit;
9
 
10
  class Analytics extends \Twig_Extension {
 
 
 
 
 
11
  public function getFunctions() {
12
  $analytics = new AnalyticsGenerator(new Reporter());
13
  return array(
lib/Twig/Assets.php CHANGED
@@ -1,25 +1,16 @@
1
  <?php
2
- namespace MailPoet\Twig;
3
 
4
- use MailPoet\Config\Env;
5
 
6
  if(!defined('ABSPATH')) exit;
7
 
8
- class Assets extends \Twig_Extension implements \Twig_Extension_GlobalsInterface {
9
  private $_globals;
10
 
11
  function __construct($globals) {
12
  $this->_globals = $globals;
13
  }
14
 
15
- function getName() {
16
- return 'assets';
17
- }
18
-
19
- function getGlobals() {
20
- return $this->_globals;
21
- }
22
-
23
  function getFunctions() {
24
  return array(
25
  new \Twig_SimpleFunction(
1
  <?php
 
2
 
3
+ namespace MailPoet\Twig;
4
 
5
  if(!defined('ABSPATH')) exit;
6
 
7
+ class Assets extends \Twig_Extension {
8
  private $_globals;
9
 
10
  function __construct($globals) {
11
  $this->_globals = $globals;
12
  }
13
 
 
 
 
 
 
 
 
 
14
  function getFunctions() {
15
  return array(
16
  new \Twig_SimpleFunction(
lib/Twig/Functions.php CHANGED
@@ -7,11 +7,6 @@ use MailPoet\Config\ServicesChecker;
7
  if(!defined('ABSPATH')) exit;
8
 
9
  class Functions extends \Twig_Extension {
10
-
11
- function getName() {
12
- return 'functions';
13
- }
14
-
15
  function getFunctions() {
16
  return array(
17
  new \Twig_SimpleFunction(
@@ -173,4 +168,4 @@ class Functions extends \Twig_Extension {
173
  function isRtl() {
174
  return is_rtl();
175
  }
176
- }
7
  if(!defined('ABSPATH')) exit;
8
 
9
  class Functions extends \Twig_Extension {
 
 
 
 
 
10
  function getFunctions() {
11
  return array(
12
  new \Twig_SimpleFunction(
168
  function isRtl() {
169
  return is_rtl();
170
  }
171
+ }
lib/Twig/Handlebars.php CHANGED
@@ -1,23 +1,23 @@
1
  <?php
 
2
  namespace MailPoet\Twig;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
6
  class Handlebars extends \Twig_Extension {
7
-
8
- public function getName() {
9
- return 'handlebars';
10
- }
11
-
12
  public function getFunctions() {
13
  return array(
14
  new \Twig_SimpleFunction(
15
  'partial',
16
- array($this, 'generatePartial'),
 
 
 
17
  array(
18
  'needs_environment' => true,
19
- 'needs_context' => true,
20
- 'is_safe' => array('all'))
 
21
  )
22
  );
23
  }
@@ -41,23 +41,28 @@ class Handlebars extends \Twig_Extension {
41
  return;
42
  }
43
 
44
- $output = array();
45
 
46
- $output[] = '<script id="'.$id.'" type="text/x-handlebars-template">';
47
- $output[] = twig_include($env, $context, $file);
48
- $output[] = '</script>';
 
 
49
 
50
  if($alias !== null) {
51
- $output[] = '<script type="text/javascript">';
52
- $output[] = 'jQuery(function($) {';
53
- $output[] = '$(function() {';
54
- $output[] = ' Handlebars.registerPartial(
55
- "'.$alias.'",
56
- jQuery("#'.$id.'").html());';
57
- $output[] = '});';
58
- $output[] = '});';
59
- $output[] = '</script>';
 
 
 
60
  }
61
- return join("\n", $output);
62
  }
63
  }
1
  <?php
2
+
3
  namespace MailPoet\Twig;
4
 
5
  if(!defined('ABSPATH')) exit;
6
 
7
  class Handlebars extends \Twig_Extension {
 
 
 
 
 
8
  public function getFunctions() {
9
  return array(
10
  new \Twig_SimpleFunction(
11
  'partial',
12
+ array(
13
+ $this,
14
+ 'generatePartial'
15
+ ),
16
  array(
17
  'needs_environment' => true,
18
+ 'needs_context' => true,
19
+ 'is_safe' => array('all')
20
+ )
21
  )
22
  );
23
  }
41
  return;
42
  }
43
 
44
+ $rendered_template = twig_include($env, $context, $file);
45
 
46
+ $output = <<<EOL
47
+ <script id="$id" type="text/x-handlebars-template">
48
+ $rendered_template
49
+ </script>
50
+ EOL;
51
 
52
  if($alias !== null) {
53
+ $output .= <<<EOL
54
+ <script type="text/javascript">
55
+ jQuery(function($) {
56
+ $(function() {
57
+ Handlebars.registerPartial(
58
+ '$alias',
59
+ jQuery('#$id').html()
60
+ );
61
+ });
62
+ });
63
+ </script>
64
+ EOL;
65
  }
66
+ return $output;
67
  }
68
  }
lib/Twig/Helpscout.php CHANGED
@@ -1,14 +1,10 @@
1
  <?php
 
2
  namespace MailPoet\Twig;
3
 
4
  if(!defined('ABSPATH')) exit;
5
 
6
  class Helpscout extends \Twig_Extension {
7
-
8
- public function getName() {
9
- return 'helpscout';
10
- }
11
-
12
  public function getFunctions() {
13
  return array(
14
  new \Twig_SimpleFunction(
1
  <?php
2
+
3
  namespace MailPoet\Twig;
4
 
5
  if(!defined('ABSPATH')) exit;
6
 
7
  class Helpscout extends \Twig_Extension {
 
 
 
 
 
8
  public function getFunctions() {
9
  return array(
10
  new \Twig_SimpleFunction(
lib/Twig/I18n.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  namespace MailPoet\Twig;
3
 
4
  if(!defined('ABSPATH')) exit;
@@ -12,10 +13,6 @@ class I18n extends \Twig_Extension {
12
  $this->_text_domain = $text_domain;
13
  }
14
 
15
- function getName() {
16
- return 'i18n';
17
- }
18
-
19
  function getFunctions() {
20
  // twig custom functions
21
  $twig_functions = array();
1
  <?php
2
+
3
  namespace MailPoet\Twig;
4
 
5
  if(!defined('ABSPATH')) exit;
13
  $this->_text_domain = $text_domain;
14
  }
15
 
 
 
 
 
16
  function getFunctions() {
17
  // twig custom functions
18
  $twig_functions = array();
mailpoet.php CHANGED
@@ -4,7 +4,7 @@ if(!defined('ABSPATH')) exit;
4
 
5
  /*
6
  * Plugin Name: MailPoet 3 (new)
7
- * Version: 3.0.0-rc.2.0.3
8
  * Plugin URI: http://www.mailpoet.com
9
  * Description: Create and send newsletters, post notifications and welcome emails from your WordPress.
10
  * Author: MailPoet
@@ -21,7 +21,7 @@ if(!defined('ABSPATH')) exit;
21
  */
22
 
23
  $mailpoet_plugin = array(
24
- 'version' => '3.0.0-rc.2.0.3',
25
  'filename' => __FILE__,
26
  'path' => dirname(__FILE__),
27
  'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
4
 
5
  /*
6
  * Plugin Name: MailPoet 3 (new)
7
+ * Version: 3.0.0
8
  * Plugin URI: http://www.mailpoet.com
9
  * Description: Create and send newsletters, post notifications and welcome emails from your WordPress.
10
  * Author: MailPoet
21
  */
22
 
23
  $mailpoet_plugin = array(
24
+ 'version' => '3.0.0',
25
  'filename' => __FILE__,
26
  'path' => dirname(__FILE__),
27
  'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
readme.txt CHANGED
@@ -1,42 +1,55 @@
1
- === MailPoet 3 (new) ===
2
  Contributors: mailpoet, wysija
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, signup, subscription, SMTP
4
  Requires at least: 4.6
5
  Tested up to: 4.8
6
  Requires PHP: 5.3
7
- Stable tag: 3.0.0-rc.2.0.3
 
 
 
8
  Create and send beautiful emails and newsletters from WordPress.
9
 
10
  == Description ==
11
 
12
- This is the release candidate of our completely new email newsletter plugin.
13
 
14
- = What's new? =
15
 
16
- * New designer
17
- * Responsive templates
18
- * Send with MailPoet (optional)
19
  * Improved user experience
20
- * Easier configuration
21
  * Solid reliability
22
- * Import subscribers, lists, forms and settings from old MailPoet
23
 
24
  = See it in action. =
25
  [Test the demo](http://demo3.mailpoet.com/launch/) or [see the 2 min. video](https://vimeo.com/223581490)
26
  [vimeo https://vimeo.com/223581490]
27
 
28
- = What is a release candidate? =
 
 
 
 
 
 
 
 
 
29
 
30
- MailPoet version 3 is considered production ready and will soon replace version 2 officially. It's fully featured, stable and supported. We only expect minor issues. Further notes:
31
 
32
- * Weekly releases with bug fixes and improvements
33
- * Report bugs directly from the user interface
34
- * Not optimized for right-to-left (RTL) languages, but it works
35
- * Multisite works but is not officially supported
36
 
37
- = Premium version available =
 
 
 
 
 
38
 
39
- [Get in touch](https://www.mailpoet.com/support/sales-pre-sales-questions/) if you are an existing customer and you want to switch.
40
 
41
  = Translations =
42
 
@@ -50,8 +63,15 @@ MailPoet version 3 is considered production ready and will soon replace version
50
  * Russian
51
  * Japanese
52
  * Persian (IR)
 
 
 
53
 
54
- We welcome translators to translate directly on [our Transifex project](https://www.transifex.com/wysija/mp3/). Please note that any translations submitted via the "Translating WordPress" web site will not work!
 
 
 
 
55
 
56
  == Installation ==
57
 
@@ -60,7 +80,7 @@ There are 3 ways to install this plugin:
60
  = 1. The super easy way =
61
  1. In your WordPress dashboard, navigate to Plugins > Add New
62
  1. Search for `MailPoet`
63
- 1. Click on "install now" under "MailPoet 3 – Beta Version"
64
  1. Activate the plugin
65
  1. A new `MailPoet` menu will appear in your WordPress dashboard
66
 
@@ -82,7 +102,7 @@ There are 3 ways to install this plugin:
82
 
83
  = Need help? =
84
 
85
- Our [support site](https://beta.docs.mailpoet.com) has plenty of articles. You can write to us on the forums too.
86
 
87
  == Screenshots ==
88
 
@@ -94,6 +114,11 @@ Our [support site](https://beta.docs.mailpoet.com) has plenty of articles. You c
94
 
95
  == Changelog ==
96
 
 
 
 
 
 
97
  = 3.0.0-rc.2.0.3 - 2017-09-12 =
98
  * Added: hook to override default cron URL. Thanks Fred;
99
  * Improved: WordPress user sync optimized for large membership sites; Thanks Nagui and @deltafactory!
1
+ === MailPoet 3 (New) ===
2
  Contributors: mailpoet, wysija
3
  Tags: newsletter, email, welcome email, post notification, autoresponder, signup, subscription, SMTP
4
  Requires at least: 4.6
5
  Tested up to: 4.8
6
  Requires PHP: 5.3
7
+ Stable tag: 3.0.0
8
+ License: GPLv3
9
+ License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
+
11
  Create and send beautiful emails and newsletters from WordPress.
12
 
13
  == Description ==
14
 
15
+ The new MailPoet is here! With our new free sending plan, send unlimited emails to up to 2,000 subscribers. All without ever leaving WordPress.
16
 
17
+ = What's inside? =
18
 
19
+ * New designer with responsive templates
20
+ * Send your emails with MailPoet’s Sending Service (optional)
 
21
  * Improved user experience
22
+ * Easy configuration
23
  * Solid reliability
24
+ * Weekly releases
25
 
26
  = See it in action. =
27
  [Test the demo](http://demo3.mailpoet.com/launch/) or [see the 2 min. video](https://vimeo.com/223581490)
28
  [vimeo https://vimeo.com/223581490]
29
 
30
+ = Before you install =
31
+
32
+ Take note:
33
+
34
+ * Not optimized for right-to-left (RTL) languages yet
35
+ * Multisite works, but is not officially supported
36
+ * Please check the translations in your language
37
+ * Review [our minimum requirements](http://beta.docs.mailpoet.com/article/152-minimum-requirements-for-mailpoet-3)
38
+
39
+ = What about the Premium? =
40
 
41
+ MailPoet is fully featured in its free version and works up until you have 2000 subscribers.
42
 
43
+ The Premium version adds the following features:
 
 
 
44
 
45
+ * for each newsletter, see which subscribers opened it and which links they clicked
46
+ * ability to send Welcome Emails automatically; i.e. "Welcome to my Newsletter” autoresponders or multi-email courses
47
+ * removes the small MailPoet logo in the footer of your emails
48
+ * same day support (Monday to Friday)
49
+ * send to over 2000 subscribers with your own sending method
50
+ * see the [short video summary on the Premium](http://beta.docs.mailpoet.com/article/208-video-overview-of-mailpoet-premium)
51
 
52
+ Plus: if you sign up to one of our sending plans, you’ll get all of these fancy features for free. Visit the Premium page inside the plugin for more info.
53
 
54
  = Translations =
55
 
63
  * Russian
64
  * Japanese
65
  * Persian (IR)
66
+ * Norwegian
67
+ * Swedish
68
+ * Turkish
69
 
70
+ We welcome experienced translators to translate directly on [our Transifex project](https://www.transifex.com/wysija/mp3/). Please note that any translations submitted via the "Translating WordPress" web site will not work.
71
+
72
+ = Security =
73
+
74
+ [Security audits are made by LogicalTrust](https://logicaltrust.net/en/), an independent third party.
75
 
76
  == Installation ==
77
 
80
  = 1. The super easy way =
81
  1. In your WordPress dashboard, navigate to Plugins > Add New
82
  1. Search for `MailPoet`
83
+ 1. Click on "install now"
84
  1. Activate the plugin
85
  1. A new `MailPoet` menu will appear in your WordPress dashboard
86
 
102
 
103
  = Need help? =
104
 
105
+ Stop by our [support site](https://www.mailpoet.com/support).
106
 
107
  == Screenshots ==
108
 
114
 
115
  == Changelog ==
116
 
117
+ = 3.0.0 - 2017-09-20 =
118
+ * Official launch of the new MailPoet. :)
119
+ * Improved: MailPoet 3 now works with other plugins that use a supported version of Twig templating engine. Thanks @supsysticcom;
120
+ * Added: we now offer a free sending plan for 2000 subscribers or less. Thx MailPoet!
121
+
122
  = 3.0.0-rc.2.0.3 - 2017-09-12 =
123
  * Added: hook to override default cron URL. Thanks Fred;
124
  * Improved: WordPress user sync optimized for large membership sites; Thanks Nagui and @deltafactory!
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit93d8437952c2c647922399b465db986a::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit5d9881c444dc082c214fb3c84d951ad4::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit93d8437952c2c647922399b465db986a
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit93d8437952c2c647922399b465db986a
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit93d8437952c2c647922399b465db986a', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit93d8437952c2c647922399b465db986a', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit93d8437952c2c647922399b465db986a::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit93d8437952c2c647922399b465db986a
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInit93d8437952c2c647922399b465db986a::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequire93d8437952c2c647922399b465db986a($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequire93d8437952c2c647922399b465db986a($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit5d9881c444dc082c214fb3c84d951ad4
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit5d9881c444dc082c214fb3c84d951ad4', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit5d9881c444dc082c214fb3c84d951ad4', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit5d9881c444dc082c214fb3c84d951ad4::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit5d9881c444dc082c214fb3c84d951ad4::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire5d9881c444dc082c214fb3c84d951ad4($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequire5d9881c444dc082c214fb3c84d951ad4($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit93d8437952c2c647922399b465db986a
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@@ -835,10 +835,10 @@ class ComposerStaticInit93d8437952c2c647922399b465db986a
835
  public static function getInitializer(ClassLoader $loader)
836
  {
837
  return \Closure::bind(function () use ($loader) {
838
- $loader->prefixLengthsPsr4 = ComposerStaticInit93d8437952c2c647922399b465db986a::$prefixLengthsPsr4;
839
- $loader->prefixDirsPsr4 = ComposerStaticInit93d8437952c2c647922399b465db986a::$prefixDirsPsr4;
840
- $loader->prefixesPsr0 = ComposerStaticInit93d8437952c2c647922399b465db986a::$prefixesPsr0;
841
- $loader->classMap = ComposerStaticInit93d8437952c2c647922399b465db986a::$classMap;
842
 
843
  }, null, ClassLoader::class);
844
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit5d9881c444dc082c214fb3c84d951ad4
8
  {
9
  public static $files = array (
10
  '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
835
  public static function getInitializer(ClassLoader $loader)
836
  {
837
  return \Closure::bind(function () use ($loader) {
838
+ $loader->prefixLengthsPsr4 = ComposerStaticInit5d9881c444dc082c214fb3c84d951ad4::$prefixLengthsPsr4;
839
+ $loader->prefixDirsPsr4 = ComposerStaticInit5d9881c444dc082c214fb3c84d951ad4::$prefixDirsPsr4;
840
+ $loader->prefixesPsr0 = ComposerStaticInit5d9881c444dc082c214fb3c84d951ad4::$prefixesPsr0;
841
+ $loader->classMap = ComposerStaticInit5d9881c444dc082c214fb3c84d951ad4::$classMap;
842
 
843
  }, null, ClassLoader::class);
844
  }
views/settings/mta.html CHANGED
@@ -61,12 +61,7 @@
61
  >
62
  <div class="mailpoet_sending_method_description">
63
  <h3>
64
- <img
65
- src="<%= assets_url %>/img/mailpoet_logo.png"
66
- alt="MailPoet"
67
- width="137"
68
- height="54"
69
- />
70
  </h3>
71
 
72
  <p
@@ -83,19 +78,26 @@
83
  id="mailpoet_sending_method_inactive_text"
84
  >
85
  <strong><%= __("Solve all of your sending problems!") %></strong>
86
- <br />
87
- <%= __("Let MailPoet send your emails and get the Premium features for as little as 10 dollars or euros per month.") %>
88
  <ul class="sending-method-benefits mailpoet_success">
89
  <li class="mailpoet_success_item"><%= __('Reach the inbox, not the spam box.') %>
90
- <li class="mailpoet_success_item"><%= __('Send emails up to 20 times faster than other sending methods.') %>
91
- <li class="mailpoet_success_item"><%= __('SPF & DKIM signatures are already set up! No configuration required.') %>
92
  <li class="mailpoet_success_item"><%= __('Automatically remove invalid and bounced addresses (bounce handling) to keep your lists clean.') %>
 
 
 
 
93
  </ul>
94
  <a
95
  href="<%= admin_url('admin.php?page=mailpoet-premium') %>"
96
  class="button button-primary"
97
  target="_blank"
98
- ><%= __('Find out more') %></a>
 
 
 
 
99
  </div>
100
  </div>
101
  <div class="mailpoet_status">
@@ -118,14 +120,17 @@
118
  <div class="mailpoet_sending_method_description">
119
  <h3><%= __('Other') %></h3>
120
  <div class="mailpoet_description">
121
- <strong><%= __('Send with your website or third party') %></strong>
122
- <br />
123
- <%= __('Choose to send emails through your website (not recommended) or a third party sender.') %>
124
  <ul class="sending-method-benefits mailpoet_error">
125
- <li class="mailpoet_error_item"><%= __("You'll probably end up in spam.") %>
126
- <li class="mailpoet_error_item"><%= __('Sending speed is limited by your web host.') %>
127
- <li class="mailpoet_error_item"><%= __('Manual configuration of SPF and DKIM required.') %>
128
- <li class="mailpoet_error_item"><%= __('Bounce handling is available, but only with an extra add-on.') %>
 
 
 
 
 
129
  </ul>
130
  </div>
131
  </div>
61
  >
62
  <div class="mailpoet_sending_method_description">
63
  <h3>
64
+ <%= __('MailPoet Sending Service') %>
 
 
 
 
 
65
  </h3>
66
 
67
  <p
78
  id="mailpoet_sending_method_inactive_text"
79
  >
80
  <strong><%= __("Solve all of your sending problems!") %></strong>
81
+
 
82
  <ul class="sending-method-benefits mailpoet_success">
83
  <li class="mailpoet_success_item"><%= __('Reach the inbox, not the spam box.') %>
84
+ <li class="mailpoet_success_item"><%= __('Super fast: send up to 50,000 emails per hour.') %>
85
+ <li class="mailpoet_success_item"><%= __('All emails are signed with SPF & DKIM.') %>
86
  <li class="mailpoet_success_item"><%= __('Automatically remove invalid and bounced addresses (bounce handling) to keep your lists clean.') %>
87
+ <li class="mailpoet_success_item"><%= __('Configuration is dead-simple: simply enter a key to activate the sending service.') %>
88
+ <li class="mailpoet_success_item"><strong><%= __('Coming soon:')%></strong> <%= __('MailPoet will send your WordPress site and account emails, too!') %>
89
+ <li class="mailpoet_success_item"><strong><%= __('Plus:')%></strong> <%= __('get the Premium features for free.') %>
90
+ </li>
91
  </ul>
92
  <a
93
  href="<%= admin_url('admin.php?page=mailpoet-premium') %>"
94
  class="button button-primary"
95
  target="_blank"
96
+ ><%= __('Find out more about our monthly plans') %></a>
97
+
98
+ <a href="https://www.mailpoet.com/free-plan/" class="button button-primary sending-free-plan-button" target="_blank">
99
+ <strong><%= __('new!') %></strong> <%= __('Try it for free (for up to 2,000 subscribers)') %>
100
+ </a>
101
  </div>
102
  </div>
103
  <div class="mailpoet_status">
120
  <div class="mailpoet_sending_method_description">
121
  <h3><%= __('Other') %></h3>
122
  <div class="mailpoet_description">
123
+ <strong><%= __('Send emails via your host (not recommended!) or via a third-party sender.') %></strong>
 
 
124
  <ul class="sending-method-benefits mailpoet_error">
125
+ <li class="mailpoet_error_item"><%= __("Unless you're a pro, you’ll probably end up in spam.") %>
126
+ <li class="mailpoet_error_item"><%= __("Sending speed is limited by your host and/or your third-party (with a 2,000 per hour maximum).") %>
127
+ <li class="mailpoet_error_item"><%= __("Manual configuration of SPF and DKIM required.") %>
128
+ <li class="mailpoet_error_item"><%=
129
+ __("Bounce handling is available, but only with an extra [link]add-on[/link].")
130
+ |replaceLinkTags('https://wordpress.org/plugins/bounce-handler-mailpoet/', {'target' : '_blank'})
131
+ |raw
132
+ %>
133
+ <li class="mailpoet_error_item"><%= __("You’ll need a separate plugin to send your WordPress site emails (optional).") %>
134
  </ul>
135
  </div>
136
  </div>
views/update.html CHANGED
@@ -6,7 +6,7 @@
6
  <h1><%= __('Greetings, humans.') %></h1>
7
 
8
  <p class="about-text"><%= __('Thanks for using MailPoet! We really appreciate all of your love, affection, [link]and (good) plugin reviews.[/link]')
9
- |replaceLinkTags('https://wordpress.org/support/plugin/wysija-newsletters/reviews/', {'target' : '_blank'})
10
  |raw
11
  %>
12
  </p>
@@ -60,8 +60,18 @@
60
  <div class="feature-section one-col mailpoet_centered">
61
  <h2><%= __('Care to Give Your Opinion?') %></h2>
62
 
63
- <script type="text/javascript" charset="utf-8" src="//secure.polldaddy.com/p/9801036.js"></script>
64
- <noscript><a href="//polldaddy.com/poll/9801036/">Should MailPoet include more default templates?</a></noscript>
 
 
 
 
 
 
 
 
 
 
65
  </div>
66
 
67
  <hr>
6
  <h1><%= __('Greetings, humans.') %></h1>
7
 
8
  <p class="about-text"><%= __('Thanks for using MailPoet! We really appreciate all of your love, affection, [link]and (good) plugin reviews.[/link]')
9
+ |replaceLinkTags('https://wordpress.org/support/plugin/mailpoet/reviews/', {'target' : '_blank'})
10
  |raw
11
  %>
12
  </p>
60
  <div class="feature-section one-col mailpoet_centered">
61
  <h2><%= __('Care to Give Your Opinion?') %></h2>
62
 
63
+ <div class="pd-embed" id="pd_1505214143"></div>
64
+ <script type="text/javascript">
65
+ var _polldaddy = [] || _polldaddy;
66
+ _polldaddy.push( {
67
+ type: "iframe",
68
+ auto: "1",
69
+ domain: "mailpoet.polldaddy.com/s/",
70
+ id: "what-s-one-feature-that-s-missing-in-mailpoet",
71
+ placeholder: "pd_1505214143"
72
+ } );
73
+ (function(d,c,j){if(!document.getElementById(j)){var pd=d.createElement(c),s;pd.id=j;pd.src=('https:'==document.location.protocol)?'https://polldaddy.com/survey.js':'http://i0.poll.fm/survey.js';s=document.getElementsByTagName(c)[0];s.parentNode.insertBefore(pd,s);}}(document,'script','pd-embed'));
74
+ </script>
75
  </div>
76
 
77
  <hr>
views/welcome.html CHANGED
@@ -6,7 +6,7 @@
6
  <h1><%= __('Greetings, humans.') %></h1>
7
 
8
  <p class="about-text"><%= __('Thanks for using MailPoet! We really appreciate all of your love, affection, [link]and (good) plugin reviews.[/link]')
9
- |replaceLinkTags('https://wordpress.org/support/plugin/wysija-newsletters/reviews/', {'target' : '_blank'})
10
  |raw
11
  %>
12
  </p>
@@ -17,9 +17,32 @@
17
  <a href="admin.php?page=mailpoet-update" class="nav-tab"><%= __("What's new") %></a>
18
  </h2>
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  <div class="headline-feature feature-video">
21
  <div class="videoWrapper">
22
- <iframe width="1050" height="591" src="https://player.vimeo.com/video/184501111?title=0&byline=0&portrait=0" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
23
  </div>
24
  </div>
25
 
@@ -28,13 +51,12 @@
28
  <div class="feature-section two-col">
29
  <h2><%= __('Want to Make MailPoet Even Better?') %></h2>
30
  <div class="col">
31
- <h3><%= __('We Need Your Feedback!') %></h3>
32
- <p><%= __('As a beta tester, you have a very important job: to tell us what you think about this new version. If you love it, tell us! If you hate it, let us know! Any and all feedback is useful.') %></p>
33
- <p><%= __('To get in touch with us, simply click on the blue circle in the bottom right corner of your screen. This button is visible on all MailPoet pages on your WordPress dashboard.') %> <img width="30" style="margin:0" src="<%= image_url('welcome_template/beacon.png') %>" alt="Beacon" /></p>
34
  </div>
35
  <div class="col">
36
  <h3><%= __('Sharing is Caring') %></h3>
37
- <p><%= __("By sharing your data <i>anonymously</i> with us, you can help us understand <i>how people use MailPoet</i> and <i>what sort of features they like and don't like</i>.") %> <a href="http://beta.docs.mailpoet.com/article/130-sharing-your-data-with-us" target="_blank"><%= __('Find out more') %> &rarr;</a>
38
  <br><br>
39
  <label>
40
  <input type="checkbox" id="mailpoet_analytics_enabled" value="1"
@@ -58,7 +80,7 @@
58
  </div>
59
  <div class="col">
60
  <h3><%= __("Learn the Ropes") %></h3>
61
- <p><%= __("New to MailPoet? Check out our brand new email course. Over the span of 3 weeks, we'll teach you how to create and send your first MailPoet email newsletter. Sign up below!") %></p>
62
  <p>
63
  <iframe width="100%" height="100%" scrolling="no" frameborder="0" src="http://newsletters.mailpoet.com?mailpoet_form_iframe=4" class="mailpoet_form_iframe" vspace="0" tabindex="0" onload="if(window['MailPoet']) MailPoet.Iframe.autoSize(this);" marginwidth="0" marginheight="0" hspace="0" allowtransparency="true"></iframe>
64
  </p>
6
  <h1><%= __('Greetings, humans.') %></h1>
7
 
8
  <p class="about-text"><%= __('Thanks for using MailPoet! We really appreciate all of your love, affection, [link]and (good) plugin reviews.[/link]')
9
+ |replaceLinkTags('https://wordpress.org/support/plugin/mailpoet/reviews/', {'target' : '_blank'})
10
  |raw
11
  %>
12
  </p>
17
  <a href="admin.php?page=mailpoet-update" class="nav-tab"><%= __("What's new") %></a>
18
  </h2>
19
 
20
+ <% set random = random(2) %>
21
+
22
+ <div <% if random != 0 %>style="display: none;"<% endif %>>
23
+ <h2><%= __('Coming this Fall to a WordPress plugin page near you') %></h2>
24
+ <p class="about-text mailpoet_centered mailpoet-top-text"><%= __('The highly-anticipated sequel to Dead Poets Society, Introduction to MailPoet will keep you on the edge of your seat.
25
+ “Five out of five stars,” says Rafael Ehlers, MailPoet Support Manager.
26
+ “A must-watch for aspiring email poets.”') %>
27
+ </div>
28
+ <div <% if random != 1 %>style="display: none;"<% endif %>>
29
+ <h2><%= __('But first, watch this video') %></h2>
30
+ <p class="about-text mailpoet_centered mailpoet-top-text"><%= __('Wait a second. Don’t click that big blue button just yet.
31
+ Yeah, we’re talking to you. Before you do anything, you should really watch this video.
32
+ It won’t change your life, but it will save you (and our support team) a ton of time.
33
+ And what is life without time? So, maybe it is life-changing, after all…') %>
34
+ </div>
35
+ <div <% if random != 2 %>style="display: none;"<% endif %>>
36
+ <h2><%= __('Explanatory videos are boring, we know') %></h2>
37
+ <p class="about-text mailpoet_centered mailpoet-top-text"><%= __('But this video is really important!
38
+ We promise. Over the course of three minutes, you’ll learn how to send your first newsletter,
39
+ manage your lists, make billions of dollars and live happily ever after.
40
+ That’s right – it’s that good. So get watching.') %>
41
+ </div>
42
+
43
  <div class="headline-feature feature-video">
44
  <div class="videoWrapper">
45
+ <iframe width="1050" height="591" src="https://player.vimeo.com/video/229737424" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
46
  </div>
47
  </div>
48
 
51
  <div class="feature-section two-col">
52
  <h2><%= __('Want to Make MailPoet Even Better?') %></h2>
53
  <div class="col">
54
+ <h3><%= __('Documentation Is One Click Away') %></h3>
55
+ <p><%= __('Simply click on the blue circle in the bottom right corner of any of the MailPoet pages to access our documentation.') %> <em><%= __('Voilà!') %></em>
 
56
  </div>
57
  <div class="col">
58
  <h3><%= __('Sharing is Caring') %></h3>
59
+ <p><%= __("By sharing your data <i>anonymously</i> with us, you can help us understand how people use MailPoet and what sort of features they like and don't like.") %> <a href="http://beta.docs.mailpoet.com/article/130-sharing-your-data-with-us" target="_blank"><%= __('Find out more') %> &rarr;</a>
60
  <br><br>
61
  <label>
62
  <input type="checkbox" id="mailpoet_analytics_enabled" value="1"
80
  </div>
81
  <div class="col">
82
  <h3><%= __("Learn the Ropes") %></h3>
83
+ <p><%= __("New to MailPoet? Check out our brand new email course. Over the course of a week, we'll teach you how to create and send your first MailPoet email newsletter. Sign up below!") %></p>
84
  <p>
85
  <iframe width="100%" height="100%" scrolling="no" frameborder="0" src="http://newsletters.mailpoet.com?mailpoet_form_iframe=4" class="mailpoet_form_iframe" vspace="0" tabindex="0" onload="if(window['MailPoet']) MailPoet.Iframe.autoSize(this);" marginwidth="0" marginheight="0" hspace="0" allowtransparency="true"></iframe>
86
  </p>