jodit
Version:
Jodit is an awesome and useful wysiwyg editor with filebrowser
458 lines (457 loc) • 14.6 kB
JavaScript
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if (d = decorators[i])
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { IS_PROD } from "../../core/constants.js";
import { autobind } from "../../core/decorators/autobind/autobind.js";
import { isFunction } from "../../core/helpers/checker/is-function.js";
import { normalizeRelativePath } from "../../core/helpers/normalize/normalize-relative-path.js";
import { ConfigProto } from "../../core/helpers/utils/config-proto.js";
import { abort, error } from "../../core/helpers/utils/error/index.js";
import { set } from "../../core/helpers/utils/set.js";
import { Ajax } from "../../core/request/ajax.js";
import { FileBrowserItem } from "./builders/item.js";
export const DEFAULT_SOURCE_NAME = 'default';
const possibleRules = new Set([
'allowFiles',
'allowFileMove',
'allowFileUpload',
'allowFileUploadRemote',
'allowFileRemove',
'allowFileRename',
'allowFolders',
'allowFolderMove',
'allowFolderCreate',
'allowFolderRemove',
'allowFolderRename',
'allowImageResize',
'allowImageCrop'
]);
export default class DataProvider {
constructor(parent, options) {
this.parent = parent;
this.options = options;
this.__currentPermissions = null;
this.__ajaxInstances = new Map();
this.progressHandler = (ignore) => { };
}
/**
* Alias for options
*/
get o() {
return this.options;
}
get(name) {
const instances = this.__ajaxInstances;
if (instances.has(name)) {
const ajax = instances.get(name);
ajax === null || ajax === void 0 ? void 0 : ajax.abort();
instances.delete(name);
}
const opts = ConfigProto(this.options[name] !== undefined
? this.options[name]
: {}, ConfigProto({
onProgress: this.progressHandler
}, this.o.ajax));
if (opts.prepareData) {
opts.data = opts.prepareData.call(this, opts.data);
}
const ajax = new Ajax(opts);
instances.set(name, ajax);
const promise = ajax.send();
promise
.finally(() => {
ajax.destruct();
instances.delete(name);
this.progressHandler(100);
})
.catch(() => null);
return promise
.then(resp => resp.json())
.then(resp => {
if (resp && !this.isSuccess(resp)) {
throw new Error(this.getMessage(resp));
}
return resp;
});
}
onProgress(callback) {
this.progressHandler = callback;
}
/**
* Load permissions for path and source
*/
async permissions(path, source) {
if (!this.o.permissions) {
return null;
}
this.o.permissions.data.path = path;
this.o.permissions.data.source = source;
if (this.o.permissions.url) {
return this.get('permissions').then(resp => {
if (this.parent.isInDestruct) {
throw abort();
}
let process = this.o.permissions.process;
if (!process) {
process = this.o.ajax.process;
}
if (process) {
const respData = process.call(self, resp);
if (respData.data.permissions) {
this.parent.events.fire(this, 'changePermissions', this.__currentPermissions, respData.data.permissions);
this.__currentPermissions = respData.data.permissions;
}
}
return this.__currentPermissions;
});
}
return null;
}
canI(action) {
const rule = 'allow' + action;
if (!IS_PROD) {
if (!possibleRules.has(rule)) {
throw error('Wrong action ' + action);
}
}
const presetValue = this.o.permissionsPresets[rule];
if (presetValue !== undefined) {
return presetValue;
}
return (this.__currentPermissions == null ||
this.__currentPermissions[rule] === undefined ||
this.__currentPermissions[rule]);
}
__items(path, source, mods, onResult) {
const opt = this.options;
if (!opt.items) {
return Promise.reject(Error('Set Items api options'));
}
opt.items.data.path = path;
opt.items.data.source = source;
opt.items.data.mods = mods;
return this.get('items').then(resp => {
let process = this.o.items.process;
if (!process) {
process = this.o.ajax.process;
}
if (process) {
resp = process.call(self, resp);
}
return onResult(resp);
});
}
/**
* Load items list by path and source
*/
items(path, source, mods = {}) {
return this.__items(path, source, mods, resp => this.__generateItemsList(resp.data.sources, mods));
}
/**
* Load items list by path and source
*/
itemsEx(path, source, mods = {}) {
const calcTotal = (sources) => sources.reduce((acc, source) => acc + source.files.length, 0);
return this.__items(path, source, mods, resp => ({
items: this.__generateItemsList(resp.data.sources, mods),
loadedTotal: calcTotal(resp.data.sources)
}));
}
__generateItemsList(sources, mods = {}) {
const elements = [];
const canBeFile = (item) => item.type === 'folder' ||
!mods.onlyImages ||
item.isImage === undefined ||
item.isImage;
const inFilter = (item) => {
var _a;
return !((_a = mods.filterWord) === null || _a === void 0 ? void 0 : _a.length) ||
this.o.filter === undefined ||
this.o.filter(item, mods.filterWord);
};
sources.forEach(source => {
if (source.files && source.files.length) {
const { sort } = this.o;
if (isFunction(sort) && mods.sortBy) {
source.files.sort((a, b) => sort(a, b, mods.sortBy));
}
source.files.forEach((item) => {
if (inFilter(item) && canBeFile(item)) {
elements.push(FileBrowserItem.create({
...item,
sourceName: source.name,
source
}));
}
});
}
});
return elements;
}
async tree(path, source) {
path = normalizeRelativePath(path);
if (!this.o.folder) {
return Promise.reject(Error('Set Folder Api options'));
}
await this.permissions(path, source);
this.o.folder.data.path = path;
this.o.folder.data.source = source;
return this.get('folder').then(resp => {
let process = this.o.folder.process;
if (!process) {
process = this.o.ajax.process;
}
if (process) {
resp = process.call(self, resp);
}
return resp.data.sources;
});
}
/**
* Get path by url. You can use this method in another modules
*/
getPathByUrl(url) {
set('options.getLocalFileByUrl.data.url', url, this);
return this.get('getLocalFileByUrl').then(resp => {
if (this.isSuccess(resp)) {
return resp.data;
}
throw error(this.getMessage(resp));
});
}
/**
* Create a directory on the server
*
* @param name - Name the new folder
* @param path - Relative directory in which you want create a folder
* @param source - Server source key
*/
createFolder(name, path, source) {
const { create } = this.o;
if (!create) {
throw error('Set Create api options');
}
create.data.source = source;
create.data.path = path;
create.data.name = name;
return this.get('create').then(resp => {
if (this.isSuccess(resp)) {
return true;
}
throw error(this.getMessage(resp));
});
}
/**
* Move a file / directory on the server
*
* @param filepath - The relative path to the file / folder source
* @param path - Relative to the directory where you want to move the file / folder
*/
move(filepath, path, source, isFile) {
const mode = isFile
? 'fileMove'
: 'folderMove';
const option = this.options[mode];
if (!option) {
throw error('Set Move api options');
}
option.data.from = filepath;
option.data.path = path;
option.data.source = source;
return this.get(mode).then(resp => {
if (this.isSuccess(resp)) {
return true;
}
throw error(this.getMessage(resp));
});
}
/**
* Deleting item
*
* @param path - Relative path
* @param file - The filename
* @param source - Source
*/
__remove(action, path, file, source) {
const fr = this.o[action];
if (!fr) {
throw error(`Set "${action}" api options`);
}
fr.data.path = path;
fr.data.name = file;
fr.data.source = source;
return this.get(action).then(resp => {
if (fr.process) {
resp = fr.process.call(this, resp);
}
return this.getMessage(resp);
});
}
/**
* Deleting a file
*
* @param path - Relative path
* @param file - The filename
* @param source - Source
*/
fileRemove(path, file, source) {
return this.__remove('fileRemove', path, file, source);
}
/**
* Deleting a folder
*
* @param path - Relative path
* @param file - The filename
* @param source - Source
*/
folderRemove(path, file, source) {
return this.__remove('folderRemove', path, file, source);
}
/**
* Rename action
*
* @param path - Relative path
* @param name - Old name
* @param newname - New name
* @param source - Source
*/
__rename(action, path, name, newname, source) {
const fr = this.o[action];
if (!fr) {
throw error(`Set "${action}" api options`);
}
fr.data.path = path;
fr.data.name = name;
fr.data.newname = newname;
fr.data.source = source;
return this.get(action).then(resp => {
if (fr.process) {
resp = fr.process.call(self, resp);
}
return this.getMessage(resp);
});
}
/**
* Rename folder
*/
folderRename(path, name, newname, source) {
return this.__rename('folderRename', path, name, newname, source);
}
/**
* Rename file
*/
fileRename(path, name, newname, source) {
return this.__rename('fileRename', path, name, newname, source);
}
__changeImage(type, path, source, name, newname, box) {
if (!this.o[type]) {
this.o[type] = {
data: {}
};
}
const query = this.o[type];
if (query.data === undefined) {
query.data = {
action: type
};
}
query.data.newname = newname || name;
if (box) {
query.data.box = box;
}
query.data.path = path;
query.data.name = name;
query.data.source = source;
return this.get(type).then(resp => {
return resp.data.newPath || true;
});
}
/**
* Send command to server to crop image
*/
crop(path, source, name, newname, box) {
return this.__changeImage('crop', path, source, name, newname, box);
}
/**
* Send command to server to resize image
*/
resize(path, source, name, newname, box) {
return this.__changeImage('resize', path, source, name, newname, box);
}
getMessage(resp) {
return this.options.getMessage(resp);
}
isSuccess(resp) {
return this.options.isSuccess(resp);
}
destruct() {
this.__ajaxInstances.forEach(a => a.destruct());
this.__ajaxInstances.clear();
}
}
__decorate([
autobind
], DataProvider.prototype, "onProgress", null);
__decorate([
autobind
], DataProvider.prototype, "permissions", null);
__decorate([
autobind
], DataProvider.prototype, "canI", null);
__decorate([
autobind
], DataProvider.prototype, "items", null);
__decorate([
autobind
], DataProvider.prototype, "itemsEx", null);
__decorate([
autobind
], DataProvider.prototype, "tree", null);
__decorate([
autobind
], DataProvider.prototype, "getPathByUrl", null);
__decorate([
autobind
], DataProvider.prototype, "createFolder", null);
__decorate([
autobind
], DataProvider.prototype, "move", null);
__decorate([
autobind
], DataProvider.prototype, "fileRemove", null);
__decorate([
autobind
], DataProvider.prototype, "folderRemove", null);
__decorate([
autobind
], DataProvider.prototype, "folderRename", null);
__decorate([
autobind
], DataProvider.prototype, "fileRename", null);
__decorate([
autobind
], DataProvider.prototype, "crop", null);
__decorate([
autobind
], DataProvider.prototype, "resize", null);
__decorate([
autobind
], DataProvider.prototype, "getMessage", null);
__decorate([
autobind
], DataProvider.prototype, "isSuccess", null);
__decorate([
autobind
], DataProvider.prototype, "destruct", null);