Skip to content
This repository has been archived by the owner on Mar 29, 2021. It is now read-only.

Commit

Permalink
finish removal of tinymce dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
dsifford committed Jul 16, 2017
1 parent 4abb24f commit f105652
Show file tree
Hide file tree
Showing 22 changed files with 176 additions and 362 deletions.
16 changes: 12 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"tslint": "^5.5.0",
"tslint-microsoft-contrib": "^5.0.1",
"tslint-react": "^3.0.0",
"uglify-es": "^3.0.24",
"uglify-es": "^3.0.25",
"webpack": "^3.3.0",
"webpack-bundle-analyzer": "^2.8.3"
},
Expand Down
2 changes: 1 addition & 1 deletion src/academic-bloggers-toolkit.pot
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ msgstr ""
msgid "<strong>Notice:</strong> Rich editing must be enabled to use the Academic Blogger's Toolkit plugin"
msgstr ""

#: php/backend.php:133
#: php/backend.php:132
msgid "Reference List"
msgstr ""

Expand Down
2 changes: 1 addition & 1 deletion src/js/components/ToggleSwitch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface Props {
}

@observer
export class ToggleSwitch extends React.PureComponent<Props, {}> {
export class ToggleSwitch extends React.PureComponent<Props> {
handleMouseOver = (e: React.MouseEvent<HTMLLabelElement>) => {
createTooltip(e.currentTarget, e.currentTarget.getAttribute('data-tooltip')!, 'left');
};
Expand Down
2 changes: 1 addition & 1 deletion src/js/dialogs/add/button-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface Props {
}

@observer
export class ButtonRow extends React.PureComponent<Props, {}> {
export class ButtonRow extends React.PureComponent<Props> {
static readonly labels = top.ABT_i18n.tinymce.referenceWindow.buttonRow;

currentDialog = observable('');
Expand Down
2 changes: 1 addition & 1 deletion src/js/dialogs/add/identifier-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface Props {
}

@observer
export class IdentifierInput extends React.PureComponent<Props, {}> {
export class IdentifierInput extends React.PureComponent<Props> {
labels = top.ABT_i18n.tinymce.referenceWindow.identifierInput;

focusInputField = (el: HTMLInputElement | null) => (el ? el.focus() : void 0);
Expand Down
21 changes: 13 additions & 8 deletions src/js/dialogs/add/manual-entry-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ interface ManualEntryProps {

@observer
export class ManualEntryContainer extends React.PureComponent<ManualEntryProps, {}> {
labels = top.ABT_i18n.tinymce.referenceWindow.manualEntryContainer;
static readonly labels = top.ABT_i18n.tinymce.referenceWindow.manualEntryContainer;

// FIXME: Should this be done server-side?
citationTypes = top.ABT_i18n.citationTypes.sort((a, b) => {
const strA = a.label.toUpperCase();
const strB = b.label.toUpperCase();
Expand Down Expand Up @@ -59,7 +61,10 @@ export class ManualEntryContainer extends React.PureComponent<ManualEntryProps,
<div>
{this.props.loading && <Spinner size="40px" overlay />}
<div id="type-select-row">
<label htmlFor="type-select" children={this.labels.citationType} />
<label
htmlFor="type-select"
children={ManualEntryContainer.labels.citationType}
/>
<select id="type-select" onChange={this.handleTypeChange} value={itemType}>
{this.citationTypes.map((item, i) =>
<option
Expand All @@ -76,15 +81,15 @@ export class ManualEntryContainer extends React.PureComponent<ManualEntryProps,
<AutoCite
getter={this.props.autoCite}
kind={itemType as 'webpage'}
placeholder={this.labels.URL}
placeholder={ManualEntryContainer.labels.URL}
inputType="url"
/>}
{renderAutocite &&
['book', 'chapter'].indexOf(itemType) > -1 &&
<AutoCite
getter={this.props.autoCite}
kind={itemType as 'book' | 'chapter'}
placeholder={this.labels.ISBN}
placeholder={ManualEntryContainer.labels.ISBN}
pattern="(?:[\dxX]-?){10}|(?:[\dxX]-?){13}"
inputType="text"
/>}
Expand Down Expand Up @@ -135,11 +140,11 @@ interface AutoCiteProps {

@observer
export class AutoCite extends React.Component<AutoCiteProps, {}> {
static readonly labels = top.ABT_i18n.tinymce.referenceWindow.manualEntryContainer;
/**
* Needed for handling the initial focus() of the field
*/
input: HTMLInputElement;
labels = top.ABT_i18n.tinymce.referenceWindow.manualEntryContainer;

@observable query = '';

Expand Down Expand Up @@ -175,7 +180,7 @@ export class AutoCite extends React.Component<AutoCiteProps, {}> {
const { placeholder, inputType } = this.props;
return (
<div id="autocite" className="row">
<label htmlFor="citequery" children={this.labels.autocite} />
<label htmlFor="citequery" children={AutoCite.labels.autocite} />
<input
type={inputType}
id="citequery"
Expand All @@ -188,13 +193,13 @@ export class AutoCite extends React.Component<AutoCiteProps, {}> {
/>
<input
type="button"
aria-label={this.labels.search}
aria-label={AutoCite.labels.search}
className={
this.query.length === 0 || !this.input.validity.valid
? 'abt-btn abt-btn_flat abt-btn_disabled'
: 'abt-btn abt-btn_flat'
}
value={this.labels.search}
value={AutoCite.labels.search}
onClick={this.handleQuery}
/>
<style jsx>{`
Expand Down
2 changes: 1 addition & 1 deletion src/js/dialogs/import/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface Props {
}

@observer
export default class ImportDialog extends React.Component<Props, {}> {
export default class ImportDialog extends React.Component<Props> {
static readonly labels = top.ABT_i18n.tinymce.importWindow;
static readonly errors = top.ABT_i18n.errors;

Expand Down
2 changes: 1 addition & 1 deletion src/js/dialogs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface Props {
}

@observer
export default class DialogRouter extends React.PureComponent<Props, {}> {
export default class DialogRouter extends React.PureComponent<Props> {
render() {
const { currentDialog, onSubmit } = this.props;
switch (currentDialog.get()) {
Expand Down
32 changes: 27 additions & 5 deletions src/js/drivers/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,28 @@ export interface RelativeCitationPositions {
locations: [Citeproc.CitationsPrePost, Citeproc.CitationsPrePost];
}

enum EditorEvents {
SHOW = 'EDITOR_SHOW',
HIDE = 'EDITOR_HIDE',
}

/**
* Base class from which all editor drivers must be derived
*/
export default abstract class EditorDriver {
public static readonly events = EditorEvents;

protected readonly citationClass = 'abt-citation';
protected readonly bibliographyId = 'abt-bibliography';
protected readonly staticBibClass = 'abt-static-bib';
protected readonly footnoteId = 'abt-footnote';

/** Retrieve an array of every citationId currently existing in the editor. */
public abstract get citationIds(): string[];

/** Retrive the currently selected content in the editor as a raw HTML string. */
public abstract get selection(): string;

/**
* Called when the window is loaded. Should resolve when the editor is
* available and ready.
Expand Down Expand Up @@ -72,11 +85,12 @@ export default abstract class EditorDriver {
*/
public abstract getRelativeCitationPositions(validIds: string[]): RelativeCitationPositions;

/** Retrieve an array of every citationId currently existing in the editor. */
public abstract get citationIds(): string[];

/** Retrive the currently selected content in the editor as a raw HTML string. */
public abstract get selection(): string;
/**
* Responsible for finding and removing elements from the editor that have
* the given HTML Element IDs.
* @param idList Array of HTML element IDs to remove from the document
*/
public abstract removeItems(idList: string[]): void;

/**
* If the editor supports a 'loading' state which shows a spinner or some
Expand All @@ -99,4 +113,12 @@ export default abstract class EditorDriver {
public alert(message: string): void {
window.alert(message);
}

/**
* Should be used for binding all `EditorEvents` to the appropriate
* handlers for the editor. Must be called internally (ideally should be
* done directly before promise resolution in the `init()` method).
* @emits EditorEvents
*/
protected abstract bindEvents(): void;
}
19 changes: 19 additions & 0 deletions src/js/drivers/tinymce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default class TinyMCEDriver extends EditorDriver {
}
this.editor = top.tinyMCE.editors.content;
clearInterval(interval);
this.bindEvents();
return resolve();
}, 500);
});
Expand All @@ -54,6 +55,19 @@ export default class TinyMCEDriver extends EditorDriver {
}
}

public removeItems(itemIds: string[]) {
const doc = this.editor.getDoc();
for (const id of itemIds) {
const item = doc.getElementById(id);
if (!item) {
throw new Error(`Item with id ${id} could not be found.`);
}
if (item && item.parentElement) {
item.parentElement.removeChild(item);
}
}
}

public getRelativeCitationPositions(validIds: string[]) {
const doc = this.editor.getDoc();
const currentSelection = this.selection;
Expand Down Expand Up @@ -122,6 +136,11 @@ export default class TinyMCEDriver extends EditorDriver {
: this.setStandardBibliography(options, bibliography);
}

protected bindEvents() {
this.editor.on('show', () => dispatchEvent(new CustomEvent(EditorDriver.events.SHOW)));
this.editor.on('hide', () => dispatchEvent(new CustomEvent(EditorDriver.events.HIDE)));
}

private setStandardBibliography(options: BibOptions, bibliography: ABT.Bibliography | boolean) {
const doc = this.editor.getDoc();
const existingBib = doc.getElementById(this.bibliographyId);
Expand Down
71 changes: 32 additions & 39 deletions src/js/reference-list/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { generateID } from 'utils/helpers/';
import { parseCSLDate } from 'utils/parsers/';
import { getFromDOI, getFromPubmed } from 'utils/resolvers/';

export async function getRemoteData(identifierList: string): Promise<CSL.Data[]> {
export async function getRemoteData(identifierList: string): Promise<[CSL.Data[], string]> {
let pmidList: string[] = [];
let pmcidList: string[] = [];
let doiList: string[] = [];
Expand Down Expand Up @@ -37,9 +37,7 @@ export async function getRemoteData(identifierList: string): Promise<CSL.Data[]>
}

if (promises.length === 0) {
// FIXME:
// mce.alert(`${top.ABT_i18n.errors.identifiersNotFound.all}`);
return [];
return [[], top.ABT_i18n.errors.identifiersNotFound.all];
}

const data = await Promise.all(promises);
Expand All @@ -51,46 +49,41 @@ export async function getRemoteData(identifierList: string): Promise<CSL.Data[]>
[[], [...errList]]
);

if (errs.length > 0) {
// FIXME:
// mce.alert(
// `${top.ABT_i18n.errors.prefix}: ${top.ABT_i18n.errors.identifiersNotFound
// .some}: ${errs.join(', ')}`
// );
}
return csl;
return [
csl,
errs.length > 0
? `${top.ABT_i18n.errors.identifiersNotFound.some}: ${errs.join(', ')}`
: '',
];
}

// FIXME: This should not be asyncronous
export function parseManualData(data: ABT.ManualData): Promise<CSL.Data[]> {
return new Promise(resolve => {
data.people.forEach(person => {
if (data.manualData[person.type] === undefined) {
data.manualData[person.type] = [{ family: person.family, given: person.given }];
return;
}
data.manualData[person.type]!.push({
family: person.family,
given: person.given,
});
});

// Process date fields
['accessed', 'event-date', 'issued'].forEach(dateType => {
if (!data.manualData[dateType]) return;
data.manualData[dateType] = parseCSLDate(data.manualData[dateType], 'RIS');
export function parseManualData(data: ABT.ManualData): [CSL.Data[], string] {
data.people.forEach(person => {
if (data.manualData[person.type] === undefined) {
data.manualData[person.type] = [{ family: person.family, given: person.given }];
return;
}
data.manualData[person.type]!.push({
family: person.family,
given: person.given,
});
});

// Create a unique ID if one doesn't exist
if (!data.manualData.id) data.manualData.id = generateID();
// Process date fields
['accessed', 'event-date', 'issued'].forEach(dateType => {
if (!data.manualData[dateType]) return;
data.manualData[dateType] = parseCSLDate(data.manualData[dateType], 'RIS');
});

Object.keys(data.manualData).forEach(key => {
if (data.manualData[key] === '') {
delete data.manualData[key];
return;
}
});
// Create a unique ID if one doesn't exist
if (!data.manualData.id) data.manualData.id = generateID();

resolve([data.manualData]);
Object.keys(data.manualData).forEach(key => {
if (data.manualData[key] === '') {
delete data.manualData[key];
return;
}
});

return [[data.manualData], ''];
}
13 changes: 7 additions & 6 deletions src/js/reference-list/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,30 +83,31 @@ class CitationStore {
}

/**
* Given an array of CSL citation IDs, delete all matching CSL from this.CSL and prune this.byIndex
* Given an array of CSL citation IDs, delete all matching CSL from this.CSL and prune this.byIndex.
* @param idList - String of CSL IDs to be removed
* @param doc - TinyMCE editor document
* @return Array of HTML element IDs to remove from the document
*/
@action
removeItems(idList: string[], doc: HTMLDocument): void {
removeItems(idList: string[]): string[] {
idList.forEach(id => {
if (this.citedIDs.indexOf(id) === -1) this.CSL.delete(id);
});
let toRemove: string[] = [];
const byIndex = this.citationByIndex
.map(i => ({
...i,
citationItems: i.citationItems.filter(j => idList.indexOf(j.id) === -1),
sortedItems: i.sortedItems!.filter(j => idList.indexOf(j[1].id) === -1),
}))
.reduce((prev, curr) => {
if (curr.citationItems.length === 0) {
const el = doc.getElementById(curr.citationID!)!;
el.parentNode!.removeChild(el);
if (curr.citationItems.length === 0 && curr.citationID) {
toRemove = [...toRemove, curr.citationID];
return prev;
}
return [...prev, curr];
}, []);
this.init(byIndex);
return toRemove;
}

/**
Expand Down
Loading

0 comments on commit f105652

Please sign in to comment.