Skip to content

Commit 3b4677a

Browse files
committed
Add Editor#removeAttribute to remove section attributes 🕯
1 parent a0ae6cc commit 3b4677a

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

src/js/editor/editor.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,17 @@ class Editor {
969969
this.run(postEditor => postEditor.setAttribute(key, value, this.range));
970970
}
971971

972+
/**
973+
* Removes an attribute from the current active section(s).
974+
*
975+
* @param {String} key The attribute. The only valid attribute is 'text-align'.
976+
* @public
977+
* @see PostEditor#removeAttribute
978+
*/
979+
removeAttribute(key) {
980+
this.run(postEditor => postEditor.removeAttribute(key, this.range));
981+
}
982+
972983
/**
973984
* Finds and runs the first matching key command for the event
974985
*

src/js/editor/post.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,24 @@ class PostEditor {
841841
}
842842

843843
setAttribute(key, value, range=this._range) {
844+
this._mutateAttribute(key, range, (section, attribute) => {
845+
if (section.getAttribute(attribute) !== value) {
846+
section.setAttribute(attribute, value);
847+
return true;
848+
}
849+
});
850+
}
851+
852+
removeAttribute(key, range=this._range) {
853+
this._mutateAttribute(key, range, (section, attribute) => {
854+
if (section.hasAttribute(attribute)) {
855+
section.removeAttribute(attribute);
856+
return true;
857+
}
858+
});
859+
}
860+
861+
_mutateAttribute(key, range, cb) {
844862
range = toRange(range);
845863
let { post } = this.editor;
846864
let attribute = `data-md-${key}`;
@@ -850,8 +868,7 @@ class PostEditor {
850868
section = section.parent;
851869
}
852870

853-
if (section.getAttribute(attribute) !== value) {
854-
section.setAttribute(attribute, value);
871+
if (cb(section, attribute) === true) {
855872
this._markDirty(section);
856873
}
857874
});

src/js/models/_attributable.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export const VALID_ATTRIBUTES = [
1212
export function attributable(ctx) {
1313
ctx.attributes = {};
1414

15+
ctx.hasAttribute = key => key in ctx.attributes;
16+
1517
ctx.setAttribute = (key, value) => {
1618
if (!contains(VALID_ATTRIBUTES, key)) {
1719
throw new Error(`Invalid attribute "${key}" was passed. Constrain attributes to the spec-compliant whitelist.`);

tests/unit/editor/post-test.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,31 @@ test('#setAttribute sets attribute of a single section', (assert) => {
691691
);
692692
});
693693

694+
test('#removeAttribute removes attribute of a single section', (assert) => {
695+
let post = Helpers.postAbstract.build(({post, markupSection}) => {
696+
return post([markupSection('p', [], false, { 'data-md-text-align': 'center' })]);
697+
});
698+
699+
mockEditor = renderBuiltAbstract(post, mockEditor);
700+
const range = Range.create(post.sections.head, 0);
701+
702+
assert.deepEqual(
703+
post.sections.head.attributes,
704+
{
705+
'data-md-text-align': 'center'
706+
}
707+
);
708+
709+
postEditor = new PostEditor(mockEditor);
710+
postEditor.removeAttribute('text-align', range);
711+
postEditor.complete();
712+
713+
assert.deepEqual(
714+
post.sections.head.attributes,
715+
{}
716+
);
717+
});
718+
694719
test('#setAttribute sets attribute of multiple sections', (assert) => {
695720
let post = Helpers.postAbstract.build(
696721
({post, markupSection, marker, cardSection}) => {
@@ -724,6 +749,35 @@ test('#setAttribute sets attribute of multiple sections', (assert) => {
724749
);
725750
});
726751

752+
test('#removeAttribute removes attribute of multiple sections', (assert) => {
753+
let post = Helpers.postAbstract.build(
754+
({post, markupSection, marker, cardSection}) => {
755+
return post([
756+
markupSection('p', [marker('abc')], false, { 'data-md-text-align': 'center' }),
757+
cardSection('my-card'),
758+
markupSection('p', [marker('123')], { 'data-md-text-align': 'left' })
759+
]);
760+
});
761+
762+
mockEditor = renderBuiltAbstract(post, mockEditor);
763+
const range = Range.create(post.sections.head, 0,
764+
post.sections.tail, 2);
765+
766+
postEditor = new PostEditor(mockEditor);
767+
postEditor.removeAttribute('text-align', range);
768+
postEditor.complete();
769+
770+
assert.deepEqual(
771+
post.sections.head.attributes,
772+
{}
773+
);
774+
assert.ok(post.sections.objectAt(1).isCardSection);
775+
assert.deepEqual(
776+
post.sections.tail.attributes,
777+
{}
778+
);
779+
});
780+
727781
test('#setAttribute sets attribute of a single list', (assert) => {
728782
let post = Helpers.postAbstract.build(
729783
({post, listSection, listItem, marker, markup}) => {

0 commit comments

Comments
 (0)