mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 02:35:49 +00:00
fix(dom) bug in Firefox with Imagus extension enabled: change getCurrentName to read from data-name instead of title (#313)
Separated out name generation/parsing logic. Added test case.
This commit is contained in:
parent
b6f30d1ccb
commit
c057b950c8
9 changed files with 122 additions and 25 deletions
|
|
@ -1,9 +1,14 @@
|
||||||
|
/**
|
||||||
|
* Parse a `data-name` attribute string back into the original filename
|
||||||
|
* @param attribute The string we wish to decode
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* global DOM */
|
/* global DOM */
|
||||||
/* global CloudCmd */
|
/* global CloudCmd */
|
||||||
|
|
||||||
const btoa = require('../../common/btoa');
|
const {atob, btoa} = require('../../common/base64');
|
||||||
const createElement = require('@cloudcmd/create-element');
|
const createElement = require('@cloudcmd/create-element');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
@ -41,7 +46,7 @@ module.exports.setCurrentName = (name, current) => {
|
||||||
link.href = dir + encoded;
|
link.href = dir + encoded;
|
||||||
link.innerHTML = encoded;
|
link.innerHTML = encoded;
|
||||||
|
|
||||||
current.setAttribute('data-name', 'js-file-' + btoa(encodeURI(name)));
|
current.setAttribute('data-name', createNameAttribute(name));
|
||||||
CloudCmd.emit('current-file', current);
|
CloudCmd.emit('current-file', current);
|
||||||
|
|
||||||
return link;
|
return link;
|
||||||
|
|
@ -58,13 +63,25 @@ module.exports.getCurrentName = (currentFile) => {
|
||||||
if (!current)
|
if (!current)
|
||||||
return '';
|
return '';
|
||||||
|
|
||||||
const link = DOM.getCurrentLink(current);
|
return parseNameAttribute(current.getAttribute('data-name'));
|
||||||
|
};
|
||||||
if (!link)
|
|
||||||
return '';
|
/**
|
||||||
|
* Generate a `data-name` attribute for the given filename
|
||||||
return decode(link.title)
|
* @param name The string name to encode
|
||||||
.replace(NBSP_REG, SPACE);
|
*/
|
||||||
|
const createNameAttribute = (name) => {
|
||||||
|
const encoded = btoa(encodeURI(name));
|
||||||
|
return `js-file-${encoded}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a `data-name` attribute string back into the original filename
|
||||||
|
* @param attribute The string we wish to decode
|
||||||
|
*/
|
||||||
|
const parseNameAttribute = (attribute) => {
|
||||||
|
attribute = attribute.replace('js-file-', '');
|
||||||
|
return decodeURI(atob(attribute));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,16 @@ test('current-file: setCurrentName: setAttribute: cyrillic', (t) => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('current-file: getCurrentName', (t) => {
|
||||||
|
const current = create();
|
||||||
|
current.getAttribute.returns('js-file-Ymlu');
|
||||||
|
|
||||||
|
const result = currentFile.getCurrentName(current);
|
||||||
|
|
||||||
|
t.equal(result, 'bin');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
test('current-file: emit', (t) => {
|
test('current-file: emit', (t) => {
|
||||||
const {
|
const {
|
||||||
DOM,
|
DOM,
|
||||||
|
|
|
||||||
20
common/base64.js
Normal file
20
common/base64.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports.btoa = (str) => {
|
||||||
|
if (typeof btoa === 'function')
|
||||||
|
return btoa(str);
|
||||||
|
|
||||||
|
return Buffer
|
||||||
|
.from(str)
|
||||||
|
.toString('base64');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.atob = (str) => {
|
||||||
|
if (typeof atob === 'function')
|
||||||
|
return atob(str);
|
||||||
|
|
||||||
|
return Buffer
|
||||||
|
.from(str, 'base64')
|
||||||
|
.toString('binary');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
const test = require('supertape');
|
const test = require('supertape');
|
||||||
const stub = require('@cloudcmd/stub');
|
const stub = require('@cloudcmd/stub');
|
||||||
|
|
||||||
const btoa = require('../../common/btoa');
|
const {btoa, atob} = require('./base64');
|
||||||
|
|
||||||
test('btoa: browser', (t) => {
|
test('btoa: browser', (t) => {
|
||||||
const btoaOriginal = global.btoa;
|
const btoaOriginal = global.btoa;
|
||||||
|
|
@ -29,3 +29,27 @@ test('btoa: node', (t) => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('atob: browser', (t) => {
|
||||||
|
const atobOriginal = global.atob;
|
||||||
|
const str = 'hello';
|
||||||
|
|
||||||
|
global.atob = stub();
|
||||||
|
|
||||||
|
atob(str);
|
||||||
|
|
||||||
|
t.calledWith(global.atob, [str], 'should call global.btoa');
|
||||||
|
t.end();
|
||||||
|
|
||||||
|
global.atob = atobOriginal;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('atob: node', (t) => {
|
||||||
|
const str = 'aGVsbG8=';
|
||||||
|
const expected = 'hello';
|
||||||
|
|
||||||
|
const result = atob(str);
|
||||||
|
|
||||||
|
t.equal(result, expected, 'should encode base64');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = (str) => {
|
|
||||||
if (typeof btoa === 'function')
|
|
||||||
return btoa(str);
|
|
||||||
|
|
||||||
return Buffer
|
|
||||||
.from(str)
|
|
||||||
.toString('base64');
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -4,7 +4,7 @@ const rendy = require('rendy');
|
||||||
const currify = require('currify');
|
const currify = require('currify');
|
||||||
const store = require('fullstore');
|
const store = require('fullstore');
|
||||||
const {encode} = require('./entity');
|
const {encode} = require('./entity');
|
||||||
const btoa = require('./btoa');
|
const {btoa} = require('./base64');
|
||||||
|
|
||||||
const getHeaderField = currify(_getHeaderField);
|
const getHeaderField = currify(_getHeaderField);
|
||||||
|
|
||||||
|
|
@ -177,7 +177,7 @@ module.exports.buildFromJSON = (params) => {
|
||||||
name: '..',
|
name: '..',
|
||||||
});
|
});
|
||||||
|
|
||||||
const dataName = 'data-name="js-file-.." ';
|
const dataName = getDataName('..');
|
||||||
const attribute = 'draggable="true" ' + dataName;
|
const attribute = 'draggable="true" ' + dataName;
|
||||||
|
|
||||||
/* Сохраняем путь к каталогу верхнего уровня*/
|
/* Сохраняем путь к каталогу верхнего уровня*/
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,50 @@ const {readFileSync} = require('fs');
|
||||||
|
|
||||||
const test = require('supertape');
|
const test = require('supertape');
|
||||||
const montag = require('montag');
|
const montag = require('montag');
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
|
||||||
const {_getSize, getPathLink} = require('./cloudfunc');
|
const {
|
||||||
|
_getSize,
|
||||||
|
getPathLink,
|
||||||
|
buildFromJSON,
|
||||||
|
} = require('./cloudfunc');
|
||||||
|
|
||||||
const templatePath = join(__dirname, '../tmpl/fs');
|
const templatePath = join(__dirname, '../tmpl/fs');
|
||||||
const template = {
|
const template = {
|
||||||
pathLink: readFileSync(`${templatePath}/pathLink.hbs`, 'utf8'),
|
pathLink: readFileSync(`${templatePath}/pathLink.hbs`, 'utf8'),
|
||||||
|
path: readFileSync(`${templatePath}/path.hbs`, 'utf8'),
|
||||||
|
file: readFileSync(`${templatePath}/file.hbs`, 'utf8'),
|
||||||
|
link: readFileSync(`${templatePath}/link.hbs`, 'utf8'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
test('cloudfunc: buildFromJSON: ..', (t) => {
|
||||||
|
const data = {
|
||||||
|
path: '/media/',
|
||||||
|
files: [{
|
||||||
|
date: '30.08.2016',
|
||||||
|
mode: 'rwx rwx rwx',
|
||||||
|
name: 'floppy',
|
||||||
|
owner: 'root',
|
||||||
|
size: '7b',
|
||||||
|
type: 'directory-link',
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
const html = buildFromJSON({
|
||||||
|
prefix: '',
|
||||||
|
template,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
const el = $('[data-name="js-file-Li4="]');
|
||||||
|
const result = el.find('[data-name="js-name"]').text();
|
||||||
|
const expected = '..';
|
||||||
|
|
||||||
|
t.equal(result, expected);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
test('cloudfunc: getPathLink: /', (t) => {
|
test('cloudfunc: getPathLink: /', (t) => {
|
||||||
const {pathLink} = template;
|
const {pathLink} = template;
|
||||||
const result = getPathLink('/', '', pathLink);
|
const result = getPathLink('/', '', pathLink);
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@
|
||||||
"auto-globals": "^2.0.0",
|
"auto-globals": "^2.0.0",
|
||||||
"babel-loader": "^8.0.0",
|
"babel-loader": "^8.0.0",
|
||||||
"babel-plugin-macros": "^3.0.0",
|
"babel-plugin-macros": "^3.0.0",
|
||||||
|
"cheerio": "^1.0.0-rc.5",
|
||||||
"clean-css-loader": "^2.0.0",
|
"clean-css-loader": "^2.0.0",
|
||||||
"codegen.macro": "^4.0.0",
|
"codegen.macro": "^4.0.0",
|
||||||
"coveralls": "^3.0.0",
|
"coveralls": "^3.0.0",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<span data-name="js-date" class="date reduce-text">date</span>
|
<span data-name="js-date" class="date reduce-text">date</span>
|
||||||
<span data-name="js-owner" class="owner reduce-text">owner</span>
|
<span data-name="js-owner" class="owner reduce-text">owner</span>
|
||||||
<span data-name="js-mode" class="mode reduce-text">mode</span>
|
<span data-name="js-mode" class="mode reduce-text">mode</span>
|
||||||
</div><ul data-name="js-files" class="files"><li draggable="true" data-name="js-file-.." class="">
|
</div><ul data-name="js-files" class="files"><li draggable="true" data-name="js-file-Li4=" class="">
|
||||||
<span data-name="js-type" class="mini-icon directory"></span>
|
<span data-name="js-type" class="mini-icon directory"></span>
|
||||||
<span data-name="js-name" class="name reduce-text"><a href="/fs/etc" title=".." draggable="true">..</a></span>
|
<span data-name="js-name" class="name reduce-text"><a href="/fs/etc" title=".." draggable="true">..</a></span>
|
||||||
<span data-name="js-size" class="size reduce-text"><dir></span>
|
<span data-name="js-size" class="size reduce-text"><dir></span>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue