a lot of refactoring of drafty to male it usable as a universal media container
This commit is contained in:
@@ -10,119 +10,112 @@
|
|||||||
//
|
//
|
||||||
// URLs, @mentions, and #hashtags are extracted and converted into links.
|
// URLs, @mentions, and #hashtags are extracted and converted into links.
|
||||||
//
|
//
|
||||||
// JSON data representation is similar (easily converted) to Draft.js raw formatting.
|
// JSON data representation is inspired by Draft.js raw formatting.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Text:
|
Text:
|
||||||
this is *bold*, `code`, _italic_ and ~deleted~.
|
this is *bold*, `code` and _italic_, ~strike~
|
||||||
nested styles: *just bold _bold-italic_*
|
combined *bold and _italic_*
|
||||||
couple of urls: http://www.example.com/path?a=b%20c#fragment, and bolded *www.tinode.co*
|
an url: https://www.example.com/abc#fragment and another _www.tinode.co_
|
||||||
this is a @mention and a #hashtag in a string
|
this is a @mention and a #hashtag in a string
|
||||||
the _#hashtag_ used again
|
second #hashtag
|
||||||
|
|
||||||
Sample JSON representation of the text above:
|
Sample JSON representation of the text above:
|
||||||
{
|
{
|
||||||
"blocks":[
|
"txt":"this is bold, code and italic, strike combined bold and italic an url: https://www.example.com/abc#fragment " +
|
||||||
|
"and another www.tinode.co this is a @mention and a #hashtag in a string second #hashtag",
|
||||||
|
"fmt":[
|
||||||
{
|
{
|
||||||
"txt":"this is bold, code, italic and deleted.",
|
"at":8,
|
||||||
"fmt":[
|
"len":4,
|
||||||
{
|
"tp":"ST"
|
||||||
"at":8,
|
|
||||||
"len":4,
|
|
||||||
"tp":"ST"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"at":14,
|
|
||||||
"len":4,
|
|
||||||
"tp":"CO"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"at":20,
|
|
||||||
"len":6,
|
|
||||||
"tp":"EM"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"at":31,
|
|
||||||
"len":7,
|
|
||||||
"tp":"DL"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"txt":"nested styles: just bold bold-italic",
|
"at":14,
|
||||||
"fmt":[
|
"len":4,
|
||||||
{
|
"tp":"CO"
|
||||||
"at":25,
|
|
||||||
"len":11,
|
|
||||||
"tp":"EM"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"at":15,
|
|
||||||
"len":21,
|
|
||||||
"tp":"ST"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"txt":"couple of urls: http://www.example.com/path?a=b%20c#fragment, and bolded www.tinode.co",
|
"at":23,
|
||||||
"fmt":[
|
"len":6,
|
||||||
{
|
"tp":"EM"
|
||||||
"at":73,
|
|
||||||
"len":13,
|
|
||||||
"tp":"ST"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ent":[
|
|
||||||
{
|
|
||||||
"at":16,
|
|
||||||
"len":44,
|
|
||||||
"key":0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"at":73,
|
|
||||||
"len":13,
|
|
||||||
"key":1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"txt":"this is a @mention and a #hashtag in a string",
|
"at":31,
|
||||||
"ent":[
|
"len":6,
|
||||||
{
|
"tp":"DL"
|
||||||
"at":10,
|
|
||||||
"len":8,
|
|
||||||
"key":2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"at":25,
|
|
||||||
"len":8,
|
|
||||||
"key":3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"txt":"the #hashtag used again",
|
"tp":"BR",
|
||||||
"fmt":[
|
"len":1,
|
||||||
{
|
"at":37
|
||||||
"at":4,
|
},
|
||||||
"len":8,
|
{
|
||||||
"tp":"EM"
|
"at":56,
|
||||||
}
|
"len":6,
|
||||||
],
|
"tp":"EM"
|
||||||
"ent":[
|
},
|
||||||
{
|
{
|
||||||
"at":4,
|
"at":47,
|
||||||
"len":8,
|
"len":15,
|
||||||
"key":3
|
"tp":"ST"
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
|
"tp":"BR",
|
||||||
|
"len":1,
|
||||||
|
"at":62
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at":120,
|
||||||
|
"len":13,
|
||||||
|
"tp":"EM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at":71,
|
||||||
|
"len":36,
|
||||||
|
"key":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at":120,
|
||||||
|
"len":13,
|
||||||
|
"key":1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tp":"BR",
|
||||||
|
"len":1,
|
||||||
|
"at":133
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at":144,
|
||||||
|
"len":8,
|
||||||
|
"key":2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at":159,
|
||||||
|
"len":8,
|
||||||
|
"key":3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tp":"BR",
|
||||||
|
"len":1,
|
||||||
|
"at":179
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"at":187,
|
||||||
|
"len":8,
|
||||||
|
"key":3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tp":"BR",
|
||||||
|
"len":1,
|
||||||
|
"at":195
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"refs":[
|
"refs":[
|
||||||
{
|
{
|
||||||
"tp":"LN",
|
"tp":"LN",
|
||||||
"data":{
|
"data":{
|
||||||
"url":"http://www.example.com/path?a=b%20c#fragment"
|
"url":"https://www.example.com/abc#fragment"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -158,12 +151,12 @@ Sample JSON representation of the text above:
|
|||||||
// Emphesized = italic, _italic text_
|
// Emphesized = italic, _italic text_
|
||||||
{name: "EM", start: /(?:^|[\W_])(_)[^\s_]/, end: /[^\s_](_)(?=$|[\W_])/},
|
{name: "EM", start: /(?:^|[\W_])(_)[^\s_]/, end: /[^\s_](_)(?=$|[\W_])/},
|
||||||
// Deleted, ~strike this though~
|
// Deleted, ~strike this though~
|
||||||
{name: "DL", start: /(?:^|\W)(~)[^\s~]/g, end: /[^\s~](~)(?=$|\W)/},
|
{name: "DL", start: /(?:^|\W)(~)[^\s~]/, end: /[^\s~](~)(?=$|\W)/},
|
||||||
// Code block `this is monospace`
|
// Code block `this is monospace`
|
||||||
{name: "CO", start: /(?:^|\W)(`)[^`]/, end: /[^`](`)(?=$|\W)/}
|
{name: "CO", start: /(?:^|\W)(`)[^`]/, end: /[^`](`)(?=$|\W)/}
|
||||||
];
|
];
|
||||||
|
|
||||||
// RegExps for entity extraction
|
// RegExps for entity extraction (RF = reference)
|
||||||
var ENTITY_TYPES = [
|
var ENTITY_TYPES = [
|
||||||
// URLs
|
// URLs
|
||||||
{name: "LN", dataName: "url",
|
{name: "LN", dataName: "url",
|
||||||
@@ -182,19 +175,19 @@ Sample JSON representation of the text above:
|
|||||||
// Hashtags #hashtag
|
// Hashtags #hashtag
|
||||||
{name: "HT", dataName: "val",
|
{name: "HT", dataName: "val",
|
||||||
pack: function(val) { return {val: val.slice(1)}; },
|
pack: function(val) { return {val: val.slice(1)}; },
|
||||||
re: /\b#(\w\w+)/g}
|
re: /\B#(\w\w+)/g}
|
||||||
];
|
];
|
||||||
|
|
||||||
// HTML tag name suggestions
|
// HTML tag name suggestions
|
||||||
var TAG_NAMES = {
|
var HTML_TAGS = {
|
||||||
ST: 'b',
|
ST: { name: 'b', isVoid: false },
|
||||||
EM: 'i',
|
EM: { name: 'i', isVoid: false },
|
||||||
DL: 'del',
|
DL: { name: 'del', isVoid: false },
|
||||||
CO: 'tt',
|
CO: { name: 'tt', isVoid: false },
|
||||||
BR: 'br',
|
BR: { name: 'br', isVoid: true },
|
||||||
LN: 'a',
|
LN: { name: 'a', isVoid: false },
|
||||||
MN: 'a',
|
MN: { name: 'a', isVoid: false },
|
||||||
HT: 'a'
|
HT: { name: 'a', isVoid: false }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helpers for converting Drafty to HTML.
|
// Helpers for converting Drafty to HTML.
|
||||||
@@ -203,6 +196,7 @@ Sample JSON representation of the text above:
|
|||||||
EM: { open: function() { return '<i>'; }, close: function() { return '</i>'}},
|
EM: { open: function() { return '<i>'; }, close: function() { return '</i>'}},
|
||||||
DL: { open: function() { return '<del>'; }, close: function() { return '</del>'}},
|
DL: { open: function() { return '<del>'; }, close: function() { return '</del>'}},
|
||||||
CO: { open: function() { return '<tt>'; }, close: function() { return '</tt>'}},
|
CO: { open: function() { return '<tt>'; }, close: function() { return '</tt>'}},
|
||||||
|
BR: { open: function() { return ''; }, close: function() { return '<br/>'}},
|
||||||
LN: {
|
LN: {
|
||||||
open: function(data) { return '<a href="' + data.url + '">'; },
|
open: function(data) { return '<a href="' + data.url + '">'; },
|
||||||
close: function(data) { return '</a>'; },
|
close: function(data) { return '</a>'; },
|
||||||
@@ -284,15 +278,16 @@ Sample JSON representation of the text above:
|
|||||||
i = si;
|
i = si;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tag = HTML_TAGS[span.tp] || {};
|
||||||
result.push(formatter.call(context, span.tp, span.data,
|
result.push(formatter.call(context, span.tp, span.data,
|
||||||
forEach(line, start, span.at + span.len, subspans, formatter, context)));
|
tag.isVoid ? null : forEach(line, start, span.at + span.len, subspans, formatter, context)));
|
||||||
|
|
||||||
start = span.at + span.len;
|
start = span.at + span.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the last unformatted range.
|
// Add the last unformatted range.
|
||||||
if (start < end) {
|
if (start < end) {
|
||||||
result.push(formatter.call(context, null, undefined, line.slice(start)));
|
result.push(formatter.call(context, null, undefined, line.slice(start, end)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -315,6 +310,7 @@ Sample JSON representation of the text above:
|
|||||||
if (start == null) {
|
if (start == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because javascript RegExp does not support lookbehind, the actual offset may not point
|
// Because javascript RegExp does not support lookbehind, the actual offset may not point
|
||||||
// at the markup character. Find it in the matched string.
|
// at the markup character. Find it in the matched string.
|
||||||
var start_offset = start['index'] + start[0].lastIndexOf(start[1]);
|
var start_offset = start['index'] + start[0].lastIndexOf(start[1]);
|
||||||
@@ -326,7 +322,7 @@ Sample JSON representation of the text above:
|
|||||||
index = start_offset + 1;
|
index = start_offset + 1;
|
||||||
|
|
||||||
// Find the matching closing token.
|
// Find the matching closing token.
|
||||||
var end = re_end.exec(line);
|
var end = re_end ? re_end.exec(line) : null;
|
||||||
if (end == null) {
|
if (end == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -449,12 +445,13 @@ Sample JSON representation of the text above:
|
|||||||
parse: function(content) {
|
parse: function(content) {
|
||||||
// Split text into lines. It makes further processing easier.
|
// Split text into lines. It makes further processing easier.
|
||||||
var lines = content.split(/\r?\n/);
|
var lines = content.split(/\r?\n/);
|
||||||
// Holds formatted lines
|
|
||||||
var blocks = [];
|
|
||||||
// Holds entities referenced from text
|
// Holds entities referenced from text
|
||||||
var entityMap = [];
|
var entityMap = [];
|
||||||
var entityIndex = {};
|
var entityIndex = {};
|
||||||
//
|
|
||||||
|
// Processing lines one by one, hold intermediate result in blx.
|
||||||
|
var blx = [];
|
||||||
lines.map(function(line) {
|
lines.map(function(line) {
|
||||||
var spans = [];
|
var spans = [];
|
||||||
var entities = [];
|
var entities = [];
|
||||||
@@ -489,8 +486,8 @@ Sample JSON representation of the text above:
|
|||||||
|
|
||||||
// Extract entities from the cleaned up string.
|
// Extract entities from the cleaned up string.
|
||||||
entities = extractEntities(block.txt);
|
entities = extractEntities(block.txt);
|
||||||
var ranges = [];
|
|
||||||
if (entities.length > 0) {
|
if (entities.length > 0) {
|
||||||
|
var ranges = [];
|
||||||
for (var i in entities) {
|
for (var i in entities) {
|
||||||
// {offset: match['index'], unique: match[0], len: match[0].length, data: ent.packer(), type: ent.name}
|
// {offset: match['index'], unique: match[0], len: match[0].length, data: ent.packer(), type: ent.name}
|
||||||
var ent = entities[i];
|
var ent = entities[i];
|
||||||
@@ -505,12 +502,42 @@ Sample JSON representation of the text above:
|
|||||||
block.ent = ranges;
|
block.ent = ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks.push(block);
|
blx.push(block);
|
||||||
});
|
});
|
||||||
|
|
||||||
var result = {blocks: blocks};
|
var result = {txt: ""};
|
||||||
if (entityMap.length > 0) {
|
|
||||||
result.refs = entityMap;
|
// Merge lines and save line breaks as BR inline formatting.
|
||||||
|
if (blx.length > 0) {
|
||||||
|
result.txt = blx[0].txt;
|
||||||
|
result.fmt = (blx[0].fmt || []).concat(blx[0].ent || []);
|
||||||
|
|
||||||
|
for (var i = 1; i<blx.length; i++) {
|
||||||
|
var block = blx[i];
|
||||||
|
var offset = result.txt.length + 1;
|
||||||
|
|
||||||
|
result.fmt.push({tp: "BR", len: 1, at: offset - 1});
|
||||||
|
|
||||||
|
result.txt += " " + block.txt;
|
||||||
|
if (block.fmt) {
|
||||||
|
result.fmt = result.fmt.concat(block.fmt.map(function(s) {
|
||||||
|
s.at += offset; return s;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (block.ent) {
|
||||||
|
result.fmt = result.fmt.concat(block.ent.map(function(s) {
|
||||||
|
s.at += offset; return s;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.fmt.length == 0) {
|
||||||
|
delete result.fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityMap.length > 0) {
|
||||||
|
result.refs = entityMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
@@ -526,46 +553,39 @@ Sample JSON representation of the text above:
|
|||||||
* @return HTML-representation of content
|
* @return HTML-representation of content
|
||||||
*/
|
*/
|
||||||
unsafeToHTML: function(content) {
|
unsafeToHTML: function(content) {
|
||||||
var {blocks} = content;
|
var {txt, fmt, refs} = content;
|
||||||
var {refs} = content;
|
|
||||||
|
|
||||||
if (!blocks) {
|
var markup = [];
|
||||||
return '';
|
if (fmt) {
|
||||||
}
|
for (var i in fmt) {
|
||||||
|
var range = fmt[i];
|
||||||
var text = [];
|
var tp = range.tp, data;
|
||||||
for (var i in blocks) {
|
if (!tp) {
|
||||||
var line = blocks[i].txt;
|
|
||||||
var markup = [];
|
|
||||||
if (blocks[i].fmt) {
|
|
||||||
for (var j in blocks[i].fmt) {
|
|
||||||
var range = blocks[i].fmt[j];
|
|
||||||
markup.push({idx: range.at, what: DECORATORS[range.tp].open()});
|
|
||||||
markup.push({idx: range.at + range.len, what: DECORATORS[range.tp].close()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blocks[i].ent) {
|
|
||||||
for (var j in blocks[i].ent) {
|
|
||||||
var range = blocks[i].ent[j];
|
|
||||||
var entity = refs[range.key];
|
var entity = refs[range.key];
|
||||||
markup.push({idx: range.at, what: DECORATORS[entity.tp].open(entity.data)});
|
if (entity) {
|
||||||
markup.push({idx: range.at + range.len, what: DECORATORS[entity.tp].close(entity.data)});
|
tp = entity.tp;
|
||||||
|
data = entity.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DECORATORS[tp]) {
|
||||||
|
markup.push({idx: range.at, what: DECORATORS[tp].open(data)});
|
||||||
|
markup.push({idx: range.at + range.len, what: DECORATORS[tp].close(data)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (markup.length > 0) {
|
|
||||||
markup.sort(function(a, b) {
|
|
||||||
return b.idx - a.idx; // in descending order
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var j in markup) {
|
|
||||||
line = splice(line, markup[j].idx, markup[j].what);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text.push(line);
|
|
||||||
}
|
}
|
||||||
return text.join("<br/>");
|
|
||||||
|
markup.sort(function(a, b) {
|
||||||
|
return b.idx - a.idx; // in descending order
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i in markup) {
|
||||||
|
if (markup[i].what) {
|
||||||
|
txt = splice(txt, markup[i].idx, markup[i].what);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return txt;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -578,116 +598,87 @@ Sample JSON representation of the text above:
|
|||||||
* @return {Object} context
|
* @return {Object} context
|
||||||
*/
|
*/
|
||||||
format: function(content, formatter, context) {
|
format: function(content, formatter, context) {
|
||||||
var {blocks} = content;
|
var {txt, fmt, refs} = content;
|
||||||
var {refs} = content;
|
|
||||||
|
|
||||||
if (!blocks) {
|
if (!fmt) {
|
||||||
return [];
|
return [txt];
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = [];
|
var spans = [].concat(fmt);
|
||||||
|
|
||||||
// Process blocks one by one
|
// Soft spans first by start index (asc) then by length (desc).
|
||||||
for (var i = 0; i < blocks.length; i++) {
|
spans.sort(function(a, b) {
|
||||||
var block = blocks[i];
|
if (a.at - b.at == 0) {
|
||||||
var spans = [];
|
return b.len - a.len; // longer one comes first (<0)
|
||||||
|
|
||||||
// Merge markup ranges and sort in ascending order.
|
|
||||||
if (block.fmt) {
|
|
||||||
spans = spans.concat(block.fmt);
|
|
||||||
}
|
}
|
||||||
if (block.ent) {
|
return a.at - b.at;
|
||||||
spans = spans.concat(block.ent);
|
});
|
||||||
|
|
||||||
|
// Denormalize entities into spans. Create a copy of the objects to leave
|
||||||
|
// original Drafty object unchanged.
|
||||||
|
spans = spans.map(function(s) {
|
||||||
|
var data;
|
||||||
|
var tp = s.tp;
|
||||||
|
if (s.key + 1 > 0) {
|
||||||
|
data = refs[s.key].data;
|
||||||
|
tp = refs[s.key].tp;
|
||||||
}
|
}
|
||||||
|
return {tp: tp, data: data, at: s.at, len: s.len};
|
||||||
|
});
|
||||||
|
|
||||||
// Soft spans first by start index (asc) then by length (desc).
|
return forEach(txt, 0, txt.length, spans, formatter, context);
|
||||||
spans.sort(function(a, b) {
|
|
||||||
if (a.at - b.at == 0) {
|
|
||||||
return b.len - a.len; // longer one comes first (<0)
|
|
||||||
}
|
|
||||||
return a.at - b.at;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Denormalize entities.
|
|
||||||
spans.map(function(s) {
|
|
||||||
if (s.key + 1 > 0) {
|
|
||||||
s.data = refs[s.key].data;
|
|
||||||
s.tp = refs[s.key].tp;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
result = result.concat(forEach(block.txt, 0, block.txt.length - 1, spans, formatter, context));
|
|
||||||
|
|
||||||
if (i != blocks.length - 1) {
|
|
||||||
// Add line break
|
|
||||||
result.push(formatter.call(context, "BR"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given structured representation of rich text, convert it to plain text.
|
* Given structured representation of rich text, convert it to plain text.
|
||||||
* The only structure preserved is line breaks as \n.
|
|
||||||
*
|
*
|
||||||
* @param {drafty} content - content to convert to plain text.
|
* @param {drafty} content - content to convert to plain text.
|
||||||
*/
|
*/
|
||||||
toPlainText: function(content) {
|
toPlainText: function(content) {
|
||||||
var {blocks} = content;
|
return content.text;
|
||||||
|
|
||||||
if (!blocks) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
var text = blocks[0].txt;
|
|
||||||
for (var i = 1; i < blocks.length; i++) {
|
|
||||||
text += (lineBreak ? lineBreak.call(context) : "\n") + blocks[i].txt;
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if content has no markup and no entities.
|
* Returns true if content has no markup and no entities.
|
||||||
*
|
*
|
||||||
* @param {drafty} content - content to check for presence of markup.
|
* @param {drafty} content - content to check for presence of markup.
|
||||||
* @param {boolean} noLineBreaks - true to treat line breaks as markup, false
|
|
||||||
* to treat them as plain text.
|
|
||||||
* @returns true is content is plain text, false otherwise.
|
* @returns true is content is plain text, false otherwise.
|
||||||
*/
|
*/
|
||||||
isPlainText: function(content, noLineBreaks) {
|
isPlainText: function(content, noLineBreaks) {
|
||||||
if (content.refs) {
|
return !(content.fmt || content.refs);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var {blocks} = content;
|
|
||||||
|
|
||||||
if (!blocks) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noLineBreaks && blocks.length > 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i in blocks) {
|
|
||||||
if (blocks[i].fmt) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get HTML tag for a given two-letter style name
|
||||||
|
* @param {string} style - two-letter style, like ST or LN
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
tagName: function(style) {
|
tagName: function(style) {
|
||||||
return TAG_NAMES[style];
|
return HTML_TAGS[style] ? HTML_TAGS[style].name : undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a given data bundle generate an object with HTML attributes,
|
||||||
|
* for instance, given {url: "http://www.example.com/"} return
|
||||||
|
* {href: "http://www.example.com/"}
|
||||||
|
* @param {stting} style - tw-letter style to generate attributes for.
|
||||||
|
* @param {Object} data - data bundle to convert to attributes
|
||||||
|
* @returns object with HTML attributes.
|
||||||
|
*/
|
||||||
attrValue: function(style, data) {
|
attrValue: function(style, data) {
|
||||||
if (data && DECORATORS[style]) {
|
if (data && DECORATORS[style]) {
|
||||||
return DECORATORS[style].props(data);
|
return DECORATORS[style].props(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content MIME type.
|
||||||
|
* @returns string suitabe for HTTP Content-Type field.
|
||||||
|
*/
|
||||||
|
getContentType: function() {
|
||||||
|
return "text/x-drafty";
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-8
@@ -2030,6 +2030,8 @@
|
|||||||
var elementKey = 0;
|
var elementKey = 0;
|
||||||
|
|
||||||
var formatter = function(style, data, values) {
|
var formatter = function(style, data, values) {
|
||||||
|
// console.log("El: " + style + ", data: " + JSON.stringify(data) + ", values: " + JSON.stringify(values));
|
||||||
|
|
||||||
elementKey += 1;
|
elementKey += 1;
|
||||||
var el = Drafty.tagName(style);
|
var el = Drafty.tagName(style);
|
||||||
if (el) {
|
if (el) {
|
||||||
@@ -2049,14 +2051,8 @@
|
|||||||
(this.props.sequence === "single" || this.props.sequence === "last"));
|
(this.props.sequence === "single" || this.props.sequence === "last"));
|
||||||
|
|
||||||
var content = this.props.content;
|
var content = this.props.content;
|
||||||
if (this.props.mimeType === "text/x-drafty+json") {
|
if (this.props.mimeType === Drafty.getContentType()) {
|
||||||
content = React.createElement('span', null, Drafty.format(content, formatter));
|
content = React.createElement('span', null, Drafty.format(content, formatter));
|
||||||
} else {
|
|
||||||
// Handle line breaks in plain text.
|
|
||||||
// Regex capure group keep line breaks in the array.
|
|
||||||
content = content.split(/(\n)/g).map(function(line, idx) {
|
|
||||||
return line.match("\n") ? <br key={idx} /> : line;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -2655,7 +2651,7 @@
|
|||||||
topic.publish(msg);
|
topic.publish(msg);
|
||||||
} else {
|
} else {
|
||||||
// Formatted message. Send it as a Drafty object.
|
// Formatted message. Send it as a Drafty object.
|
||||||
topic.publish(dft, undefined, "text/x-drafty+json");
|
topic.publish(dft, undefined, Drafty.getContentType());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// User chose a Sign Up menu item.
|
// User chose a Sign Up menu item.
|
||||||
|
|||||||
Reference in New Issue
Block a user