diff --git a/client/dom/current-file.js b/client/dom/current-file.js index e009bd59..4e3c36f3 100644 --- a/client/dom/current-file.js +++ b/client/dom/current-file.js @@ -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'; /* global DOM */ /* global CloudCmd */ -const btoa = require('../../common/btoa'); +const {atob, btoa} = require('../../common/base64'); const createElement = require('@cloudcmd/create-element'); const { @@ -41,7 +46,7 @@ module.exports.setCurrentName = (name, current) => { link.href = dir + encoded; link.innerHTML = encoded; - current.setAttribute('data-name', 'js-file-' + btoa(encodeURI(name))); + current.setAttribute('data-name', createNameAttribute(name)); CloudCmd.emit('current-file', current); return link; @@ -58,13 +63,25 @@ module.exports.getCurrentName = (currentFile) => { if (!current) return ''; - const link = DOM.getCurrentLink(current); - - if (!link) - return ''; - - return decode(link.title) - .replace(NBSP_REG, SPACE); + return parseNameAttribute(current.getAttribute('data-name')); +}; + +/** + * Generate a `data-name` attribute for the given filename + * @param name The string name to encode + */ +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)); }; /** diff --git a/client/dom/current-file.spec.js b/client/dom/current-file.spec.js index 5cc683c3..513c3e43 100644 --- a/client/dom/current-file.spec.js +++ b/client/dom/current-file.spec.js @@ -54,6 +54,16 @@ test('current-file: setCurrentName: setAttribute: cyrillic', (t) => { 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) => { const { DOM, diff --git a/common/base64.js b/common/base64.js new file mode 100644 index 00000000..bc73b7f3 --- /dev/null +++ b/common/base64.js @@ -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'); +}; + diff --git a/test/common/btoa.js b/common/base64.spec.js similarity index 52% rename from test/common/btoa.js rename to common/base64.spec.js index 3239ec55..0c8f3ca7 100644 --- a/test/common/btoa.js +++ b/common/base64.spec.js @@ -3,7 +3,7 @@ const test = require('supertape'); const stub = require('@cloudcmd/stub'); -const btoa = require('../../common/btoa'); +const {btoa, atob} = require('./base64'); test('btoa: browser', (t) => { const btoaOriginal = global.btoa; @@ -29,3 +29,27 @@ test('btoa: node', (t) => { 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(); +}); + diff --git a/common/btoa.js b/common/btoa.js deleted file mode 100644 index bf26630b..00000000 --- a/common/btoa.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -module.exports = (str) => { - if (typeof btoa === 'function') - return btoa(str); - - return Buffer - .from(str) - .toString('base64'); -}; - diff --git a/common/cloudfunc.js b/common/cloudfunc.js index 6824be82..ac0cc221 100644 --- a/common/cloudfunc.js +++ b/common/cloudfunc.js @@ -4,7 +4,7 @@ const rendy = require('rendy'); const currify = require('currify'); const store = require('fullstore'); const {encode} = require('./entity'); -const btoa = require('./btoa'); +const {btoa} = require('./base64'); const getHeaderField = currify(_getHeaderField); @@ -177,7 +177,7 @@ module.exports.buildFromJSON = (params) => { name: '..', }); - const dataName = 'data-name="js-file-.." '; + const dataName = getDataName('..'); const attribute = 'draggable="true" ' + dataName; /* Сохраняем путь к каталогу верхнего уровня*/ diff --git a/common/cloudfunc.spec.js b/common/cloudfunc.spec.js index 4e7c2150..8d14b89a 100644 --- a/common/cloudfunc.spec.js +++ b/common/cloudfunc.spec.js @@ -5,14 +5,50 @@ const {readFileSync} = require('fs'); const test = require('supertape'); 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 template = { 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) => { const {pathLink} = template; const result = getPathLink('/', '', pathLink); diff --git a/package.json b/package.json index a6fce841..2fccad08 100644 --- a/package.json +++ b/package.json @@ -188,6 +188,7 @@ "auto-globals": "^2.0.0", "babel-loader": "^8.0.0", "babel-plugin-macros": "^3.0.0", + "cheerio": "^1.0.0-rc.5", "clean-css-loader": "^2.0.0", "codegen.macro": "^4.0.0", "coveralls": "^3.0.0", diff --git a/test/common/cloudfunc.html b/test/common/cloudfunc.html index c5f9a5b2..8db8081a 100644 --- a/test/common/cloudfunc.html +++ b/test/common/cloudfunc.html @@ -5,7 +5,7 @@ date owner mode -