-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from bustlelabs/markers
Post, Section, Markers
- Loading branch information
Showing
23 changed files
with
1,010 additions
and
226 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
export const IMAGE_SECTION_TYPE = 'image-section'; | ||
|
||
export default class Image { | ||
constructor() { | ||
this.type = 'imageSection'; | ||
this.type = IMAGE_SECTION_TYPE; | ||
this.src = null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
export const MARKER_TYPE = 'marker'; | ||
|
||
import { detect } from 'content-kit-editor/utils/array-utils'; | ||
|
||
const Marker = class Marker { | ||
constructor(value='', markups=[]) { | ||
this.value = value; | ||
this.markups = []; | ||
this.type = MARKER_TYPE; | ||
|
||
if (markups && markups.length) { | ||
markups.forEach(m => this.addMarkup(m)); | ||
} | ||
} | ||
|
||
get length() { | ||
return this.value.length; | ||
} | ||
|
||
truncateFrom(offset) { | ||
this.value = this.value.substr(0, offset); | ||
} | ||
|
||
truncateTo(offset) { | ||
this.value = this.value.substr(offset); | ||
} | ||
|
||
addMarkup(markup) { | ||
this.markups.push(markup); | ||
} | ||
|
||
hasMarkup(tagName) { | ||
tagName = tagName.toLowerCase(); | ||
return detect(this.markups, markup => markup.tagName === tagName); | ||
} | ||
|
||
getMarkup(tagName) { | ||
return this.hasMarkup(tagName); | ||
} | ||
|
||
join(other) { | ||
const joined = new Marker(this.value + other.value); | ||
this.markups.forEach(m => joined.addMarkup(m)); | ||
other.markups.forEach(m => joined.addMarkup(m)); | ||
|
||
return joined; | ||
} | ||
|
||
split(offset) { | ||
const [m1, m2] = [ | ||
new Marker(this.value.substr(0, offset)), | ||
new Marker(this.value.substr(offset)) | ||
]; | ||
this.markups.forEach(m => {m1.addMarkup(m); m2.addMarkup(m);}); | ||
|
||
return [m1, m2]; | ||
} | ||
|
||
get openedMarkups() { | ||
if (!this.previousSibling) { | ||
return this.markups.slice(); | ||
} | ||
let i; | ||
for (i=0; i<this.markups.length; i++) { | ||
if (this.markups[i] !== this.previousSibling.markups[i]) { | ||
return this.markups.slice(i); | ||
} | ||
} | ||
return []; | ||
} | ||
|
||
get closedMarkups() { | ||
if (!this.nextSibling) { | ||
return this.markups.slice(); | ||
} | ||
let i; | ||
for (i=0; i<this.markups.length; i++) { | ||
if (this.markups[i] !== this.nextSibling.markups[i]) { | ||
return this.markups.slice(i); | ||
} | ||
} | ||
return []; | ||
} | ||
|
||
// FIXME this should be implemented as a linked list | ||
get nextSibling() { | ||
let index = this.section.markers.indexOf(this); | ||
if (index > -1 && index < this.section.markers.length-1) { | ||
return this.section.markers[index + 1]; | ||
} | ||
} | ||
|
||
get previousSibling() { | ||
let index = this.section.markers.indexOf(this); | ||
if (index > 0) { | ||
return this.section.markers[index - 1]; | ||
} | ||
} | ||
}; | ||
|
||
export default Marker; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
export const DEFAULT_TAG_NAME = 'p'; | ||
export const VALID_MARKUP_SECTION_TAGNAMES = [ | ||
'p', 'h3', 'h2', 'h1', 'blockquote', 'ul', 'ol' | ||
]; | ||
export const MARKUP_SECTION_TYPE = 'markup-section'; | ||
|
||
export default class Section { | ||
constructor(tagName, markers=[]) { | ||
this.markers = []; | ||
this.tagName = tagName || DEFAULT_TAG_NAME; | ||
this.type = MARKUP_SECTION_TYPE; | ||
|
||
markers.forEach(m => this.appendMarker(m)); | ||
} | ||
|
||
appendMarker(marker) { | ||
marker.section = this; | ||
this.markers.push(marker); | ||
} | ||
|
||
/** | ||
* @return {Array} 2 new sections | ||
*/ | ||
split(offset) { | ||
let left = [], right = [], middle; | ||
|
||
middle = this.markerContaining(offset); | ||
const middleIndex = this.markers.indexOf(middle); | ||
|
||
for (let i=0; i<this.markers.length; i++) { | ||
if (i < middleIndex) { left.push(this.markers[i]); } | ||
if (i > middleIndex) { right.push(this.markers[i]); } | ||
} | ||
|
||
let leftLength = left.reduce((prev, cur) => prev + cur.length, 0); | ||
let middleOffset = offset - leftLength; | ||
|
||
let [leftMiddle, rightMiddle] = middle.split(middleOffset); | ||
left.push(leftMiddle); | ||
right.push(rightMiddle); | ||
|
||
return [ | ||
new this.constructor(this.tagName, left), | ||
new this.constructor(this.tagName, right) | ||
]; | ||
} | ||
|
||
/** | ||
* A marker contains this offset if: | ||
* * The offset is between the marker's start and end | ||
* * it is the first marker and the offset is 0 | ||
* * it is the last marker and the offset is >= total length of all the markers | ||
* * the offset is between two markers and it is the left marker (right-inclusive) | ||
* | ||
* @return {Marker} The marker that contains this offset | ||
*/ | ||
markerContaining(offset) { | ||
var length=0, i=0; | ||
|
||
if (offset === 0) { return this.markers[0]; } | ||
|
||
while (length < offset && i < this.markers.length) { | ||
length += this.markers[i].length; | ||
i++; | ||
} | ||
return this.markers[i-1]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export const MARKUP_TYPE = 'markup'; | ||
export const VALID_MARKUP_TAGNAMES = [ | ||
'b', | ||
'i', | ||
'strong', | ||
'em', | ||
'a', | ||
'li' | ||
]; | ||
|
||
export default class Markup { | ||
constructor(tagName, attributes=[]) { | ||
this.tagName = tagName.toLowerCase(); | ||
this.attributes = attributes; | ||
this.type = MARKUP_TYPE; | ||
|
||
if (VALID_MARKUP_TAGNAMES.indexOf(this.tagName) === -1) { | ||
throw new Error(`Cannot create markup of tagName ${tagName}`); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import Post from 'content-kit-editor/models/post'; | ||
import SectionParser from 'content-kit-editor/parsers/section'; | ||
import { forEach } from 'content-kit-editor/utils/array-utils'; | ||
|
||
export default { | ||
parse(element) { | ||
const post = new Post(); | ||
|
||
forEach(element.childNodes, child => { | ||
post.appendSection(SectionParser.parse(child)); | ||
}); | ||
|
||
return post; | ||
}, | ||
|
||
parseSection(element) { | ||
return SectionParser.parse(element); | ||
} | ||
}; |
Oops, something went wrong.