Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forward-delete in list items #124

Merged
merged 3 commits into from
Sep 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 41 additions & 25 deletions src/js/editor/post.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { MARKUP_SECTION_TYPE } from '../models/markup-section';
import { LIST_ITEM_TYPE } from '../models/list-item';
import { LIST_SECTION_TYPE } from '../models/list-section';
import { MARKUP_SECTION_TYPE, LIST_ITEM_TYPE } from '../models/types';
import Position from '../utils/cursor/position';
import {
filter,
compact
} from '../utils/array-utils';

import { filter, compact } from '../utils/array-utils';
import { DIRECTION } from '../utils/key';

function isMarkupSection(section) {
Expand All @@ -25,21 +19,6 @@ function isMarkerable(section) {
return !!section.markers;
}

function isListSection(section) {
return section.type === LIST_SECTION_TYPE;
}

// finds the immediately preceding section that is markerable
function findPreviousMarkerableSection(section) {
const prev = section.prev;
if (!prev) { return null; }
if (isMarkerable(prev)) {
return prev;
} else if (isListSection(prev)) {
return prev.items.tail;
}
}

class PostEditor {
constructor(editor) {
this.editor = editor;
Expand Down Expand Up @@ -231,7 +210,7 @@ class PostEditor {
} else if (isListItem(section)) {
nextPosition = this._convertListItemToMarkupSection(section);
} else {
const prevSection = findPreviousMarkerableSection(section);
const prevSection = section.immediatelyPreviousMarkerableSection();

if (prevSection) {
const { beforeMarker } = prevSection.join(section);
Expand All @@ -257,7 +236,44 @@ class PostEditor {
* @private
*/
_deleteForwardFrom(position) {
return this._deleteForwardFromMarkerPosition(position);
const { section, offset } = position;
if (section.isBlank) {
// remove this section, focus on start of next markerable section
const nextPosition = position.clone();
const next = section.immediatelyNextMarkerableSection();
if (next) {
this.removeSection(section);
nextPosition.section = next;
nextPosition.offset = 0;
}
return nextPosition;
} else if (offset === section.length) {
// join next markerable section to this one
return this._joinPositionToNextSection(position);
} else {
return this._deleteForwardFromMarkerPosition(position.markerPosition);
}
}

_joinPositionToNextSection(position) {
const { section } = position;
let nextPosition = position.clone();

if (!isMarkerable(section)) {
throw new Error('Cannot join non-markerable section to next section');
} else {
const next = section.immediatelyNextMarkerableSection();
if (next) {
section.join(next);
section.renderNode.markDirty();
this.removeSection(next);

this.scheduleRerender();
this.scheduleDidUpdate();
}
}

return nextPosition;
}

_deleteForwardFromMarkerPosition(markerPosition) {
Expand Down
2 changes: 1 addition & 1 deletion src/js/editor/text-expansions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Keycodes from '../utils/keycodes';
import Key from '../utils/key';
import { detect } from '../utils/array-utils';
import { MARKUP_SECTION_TYPE } from '../models/markup-section';
import { MARKUP_SECTION_TYPE } from '../models/types';

const { SPACE } = Keycodes;

Expand Down
17 changes: 4 additions & 13 deletions src/js/models/_markerable.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { normalizeTagName } from '../utils/dom-utils';
import { forEach, filter, reduce } from '../utils/array-utils';
import Set from '../utils/set';

import LinkedItem from '../utils/linked-item';
import LinkedList from '../utils/linked-list';
import Section from './_section';

export default class Markerable extends LinkedItem {
constructor(tagName, markers=[]) {
super();
export default class Markerable extends Section {
constructor(type, tagName, markers=[]) {
super(type);
this.tagName = tagName;
this.markers = new LinkedList({
adoptItem: m => m.section = m.parent = this,
Expand All @@ -17,14 +16,6 @@ export default class Markerable extends LinkedItem {
markers.forEach(m => this.markers.append(m));
}

set tagName(val) {
this._tagName = normalizeTagName(val);
}

get tagName() {
return this._tagName;
}

get isBlank() {
if (!this.markers.length) {
return true;
Expand Down
57 changes: 57 additions & 0 deletions src/js/models/_section.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { LIST_ITEM_TYPE, LIST_SECTION_TYPE } from './types';
import { normalizeTagName } from '../utils/dom-utils';
import LinkedItem from '../utils/linked-item';

function isMarkerable(section) {
return !!section.markers;
}

function isListSection(section) {
return section.type === LIST_SECTION_TYPE;
}

function isListItem(section) {
return section.type === LIST_ITEM_TYPE;
}

export default class Section extends LinkedItem {
constructor(type) {
super();
if (!type) { throw new Error('Cannot create section without type'); }
this.type = type;
}

set tagName(val) {
this._tagName = normalizeTagName(val);
}

get tagName() {
return this._tagName;
}

immediatelyNextMarkerableSection() {
const next = this.next;
if (next) {
if (isMarkerable(next)) {
return next;
} else if (isListSection(next)) {
const firstListItem = next.items.head;
return firstListItem;
}
} else if (isListItem(this)) {
const listSection = this.parent;
return listSection.immediatelyNextMarkerableSection();
}
}

immediatelyPreviousMarkerableSection() {
const prev = this.prev;
if (!prev) { return null; }
if (isMarkerable(prev)) {
return prev;
} else if (isListSection(prev)) {
const lastListItem = prev.items.tail;
return lastListItem;
}
}
}
10 changes: 4 additions & 6 deletions src/js/models/card.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import LinkedItem from "content-kit-editor/utils/linked-item";
import Section from './_section';
import { CARD_TYPE } from './types';

export const CARD_TYPE = 'card-section';

export default class Card extends LinkedItem {
export default class Card extends Section {
constructor(name, payload) {
super();
super(CARD_TYPE);
this.name = name;
this.payload = payload;
this.type = CARD_TYPE;
}
}
7 changes: 4 additions & 3 deletions src/js/models/image.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export const IMAGE_SECTION_TYPE = 'image-section';
import { IMAGE_SECTION_TYPE } from './types';
import Section from './_section';

export default class Image {
export default class Image extends Section {
constructor() {
this.type = IMAGE_SECTION_TYPE;
super(IMAGE_SECTION_TYPE);
this.src = null;
}
}
6 changes: 2 additions & 4 deletions src/js/models/list-item.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import Markerable from './_markerable';

export const LIST_ITEM_TYPE = 'list-item';
import { LIST_ITEM_TYPE } from './types';

export default class ListItem extends Markerable {
constructor(tagName, markers=[]) {
super(tagName, markers);
this.type = LIST_ITEM_TYPE;
super(LIST_ITEM_TYPE, tagName, markers);
}

splitAtMarker(marker, offset=0) {
Expand Down
11 changes: 6 additions & 5 deletions src/js/models/list-section.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { normalizeTagName } from '../utils/dom-utils';
import LinkedList from '../utils/linked-list';
import { LIST_SECTION_TYPE } from './types';
import Section from './_section';

export const DEFAULT_TAG_NAME = 'ul';
export const LIST_SECTION_TYPE = 'list-section';

export default class ListSection {
export default class ListSection extends Section {
constructor(tagName=DEFAULT_TAG_NAME, items=[]) {
this.tagName = normalizeTagName(tagName);
this.type = LIST_SECTION_TYPE;
super(LIST_SECTION_TYPE);

this.tagName = tagName;

this.items = new LinkedList({
adoptItem: i => i.section = i.parent = this,
Expand Down
22 changes: 6 additions & 16 deletions src/js/models/marker.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
export const MARKER_TYPE = 'marker';

import {
normalizeTagName
} from '../utils/dom-utils';
import {
detect,
commonItemLength,
forEach,
filter
} from 'content-kit-editor/utils/array-utils';
import LinkedItem from "content-kit-editor/utils/linked-item";
import { MARKER_TYPE } from './types';

import { normalizeTagName } from '../utils/dom-utils';
import { detect, commonItemLength, forEach, filter } from '../utils/array-utils';
import LinkedItem from '../utils/linked-item';

const Marker = class Marker extends LinkedItem {
constructor(value='', markups=[]) {
super();
this.value = value;
this.markups = [];
this.type = MARKER_TYPE;

if (markups && markups.length) {
markups.forEach(m => this.addMarkup(m));
}
markups.forEach(m => this.addMarkup(m));
}

clone() {
Expand Down
14 changes: 2 additions & 12 deletions src/js/models/markup-section.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
import Markerable from './_markerable';
import { normalizeTagName } from '../utils/dom-utils';
import { MARKUP_SECTION_TYPE } from './types';

export const VALID_MARKUP_SECTION_TAGNAMES = [
'p', 'h3', 'h2', 'h1', 'blockquote', 'ul', 'ol'
].map(normalizeTagName);
export const DEFAULT_TAG_NAME = VALID_MARKUP_SECTION_TAGNAMES[0];

export const MARKUP_SECTION_TYPE = 'markup-section';

const MarkupSection = class MarkupSection extends Markerable {
constructor(tagName=DEFAULT_TAG_NAME, markers=[]) {
super(tagName, markers);
this.type = MARKUP_SECTION_TYPE;
}

set tagName(val) {
this._tagName = normalizeTagName(val);
}

get tagName() {
return this._tagName;
super(MARKUP_SECTION_TYPE, tagName, markers);
}

setTagName(newTagName) {
Expand Down
7 changes: 3 additions & 4 deletions src/js/models/markup.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
normalizeTagName
} from '../utils/dom-utils';
export const MARKUP_TYPE = 'markup';
import { normalizeTagName } from '../utils/dom-utils';
import { MARKUP_TYPE } from './types';

export const VALID_MARKUP_TAGNAMES = [
'b',
'i',
Expand Down
2 changes: 1 addition & 1 deletion src/js/models/post.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const POST_TYPE = 'post';
import { POST_TYPE } from './types';
import LinkedList from 'content-kit-editor/utils/linked-list';
import { forEach, compact } from 'content-kit-editor/utils/array-utils';
import Set from 'content-kit-editor/utils/set';
Expand Down
8 changes: 8 additions & 0 deletions src/js/models/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const MARKUP_SECTION_TYPE = 'markup-section';
export const LIST_SECTION_TYPE = 'list-section';
export const MARKUP_TYPE = 'markup';
export const MARKER_TYPE = 'marker';
export const POST_TYPE = 'post';
export const LIST_ITEM_TYPE = 'list-item';
export const CARD_TYPE = 'card-section';
export const IMAGE_SECTION_TYPE = 'image-section';
9 changes: 6 additions & 3 deletions src/js/parsers/post.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { MARKUP_SECTION_TYPE } from '../models/markup-section';
import { LIST_SECTION_TYPE } from '../models/list-section';
import { LIST_ITEM_TYPE } from '../models/list-item';
import {
MARKUP_SECTION_TYPE,
LIST_SECTION_TYPE,
LIST_ITEM_TYPE
} from '../models/types';

import SectionParser from 'content-kit-editor/parsers/section';
import { forEach } from 'content-kit-editor/utils/array-utils';
import { getAttributesArray, walkTextNodes } from '../utils/dom-utils';
Expand Down
16 changes: 9 additions & 7 deletions src/js/renderers/editor-dom.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import RenderNode from 'content-kit-editor/models/render-node';
import CardNode from 'content-kit-editor/models/card-node';
import { detect } from 'content-kit-editor/utils/array-utils';
import { POST_TYPE } from '../models/post';
import { MARKUP_SECTION_TYPE } from '../models/markup-section';
import { LIST_SECTION_TYPE } from '../models/list-section';
import { LIST_ITEM_TYPE } from '../models/list-item';
import { MARKER_TYPE } from '../models/marker';
import { IMAGE_SECTION_TYPE } from '../models/image';
import { CARD_TYPE } from '../models/card';
import {
POST_TYPE,
MARKUP_SECTION_TYPE,
LIST_SECTION_TYPE,
LIST_ITEM_TYPE,
MARKER_TYPE,
IMAGE_SECTION_TYPE,
CARD_TYPE
} from '../models/types';
import { startsWith, endsWith } from '../utils/string-utils';
import { addClassName } from '../utils/dom-utils';

Expand Down
Loading