Skip to content

Commit

Permalink
feat: backport helpers from project into library (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
kptdobe committed Jan 20, 2022
1 parent 8fb886f commit 3c93126
Show file tree
Hide file tree
Showing 4 changed files with 441 additions and 80 deletions.
96 changes: 96 additions & 0 deletions src/utils/Blocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright 2021 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import DOMUtils from './DOMUtils.js';

const DEFAULT_COLSPAN = 2;

export default class Blocks {
static getMetadataBlock(document, metadata) {
const table = document.createElement('table');

let row = document.createElement('tr');
table.append(row);

const hCell = document.createElement('th');
row.append(hCell);

hCell.innerHTML = 'Metadata';
hCell.setAttribute('colspan', DEFAULT_COLSPAN);

// eslint-disable-next-line no-restricted-syntax, guard-for-in
for (const key in metadata) {
row = document.createElement('tr');
table.append(row);
const keyCell = document.createElement('td');
row.append(keyCell);
keyCell.textContent = key;
const valueCell = document.createElement('td');
row.append(valueCell);
const value = metadata[key];
if (value) {
if (Array.isArray(value)) {
let list = '';
value.forEach((v) => {
// p tags in table are stripped out
// list must receive special hlx_replaceTag command to be post-processed
list += `hlx_replaceTag(p)${v}hlx_replaceTag(/p)`;
});
valueCell.textContent = list;
} else if (typeof value === 'string') {
valueCell.textContent = value;
} else {
valueCell.append(value);
}
}
}

return table;
}

static computeBlockName(str) {
return str
.replace(/-/g, ' ')
.replace(/\s(.)/g, (s) => s.toUpperCase())
.replace(/^(.)/g, (s) => s.toUpperCase());
}

static convertBlocksToTables(element, document) {
element.querySelectorAll('main > div:nth-child(4) > div[class]').forEach((block) => {
const name = Blocks.computeBlockName(block.className);
const data = [[name]];
const divs = block.querySelectorAll(':scope > div');
if (divs) {
divs.forEach((div) => {
const subDivs = div.querySelectorAll(':scope > div');
if (subDivs && subDivs.length > 0) {
const rowData = [];
subDivs.forEach((cell) => {
if (cell.nodeName === 'DIV') {
// remove transparent divs
const cellContent = [];
Array.from(cell.childNodes).forEach((c) => cellContent.push(c));
rowData.push(cellContent);
} else {
rowData.push(cell);
}
});
data.push(rowData);
} else {
data.push([div.innerHTML]);
}
});
}
const table = DOMUtils.createTable(data, document);
block.replaceWith(table);
});
}
}
37 changes: 37 additions & 0 deletions src/utils/DOMUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,31 @@ export default class DOMUtils {
});
}

static createTable(data, document) {
const table = document.createElement('table');

data.forEach((row, index) => {
const tr = document.createElement('tr');

row.forEach((cell) => {
const t = document.createElement(index === 0 ? 'th' : 'td');
if (typeof cell === 'string') {
t.innerHTML = cell;
} else if (Array.isArray(cell)) {
cell.forEach((c) => {
t.append(c);
});
} else {
t.append(cell);
}
tr.appendChild(t);
});
table.appendChild(tr);
});

return table;
}

static generateEmbed(url) {
return JSDOM.fragment(`<table><tr><th>Embed</th></tr><tr><td><a href="${url}">${url}</a></td></tr></table>`);
}
Expand Down Expand Up @@ -204,4 +229,16 @@ export default class DOMUtils {
}
});
}

static replaceBackgroundByImg(element, document) {
const url = element?.style?.['background-image'];
if (url) {
const src = url.replace(/url\(/gm, '').replace(/'/gm, '').replace(/\)/gm, '');
const img = document.createElement('img');
img.src = src;
element.replaceWith(img);
return img;
}
return element;
}
}
138 changes: 138 additions & 0 deletions test/utils/Blocks.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright 2010 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import { strictEqual } from 'assert';
import { describe, it } from 'mocha';

import { JSDOM } from 'jsdom';

import Blocks from '../../src/utils/Blocks.js';

describe('Blocks#computeBlockName tests', () => {
it('computeBlockName - can convert', () => {
strictEqual(Blocks.computeBlockName('promotion'), 'Promotion');
strictEqual(Blocks.computeBlockName('hero-animation'), 'Hero Animation');
strictEqual(Blocks.computeBlockName('how-to-carousel'), 'How To Carousel');
});
});

const trim = (html) => html
.replace(/^\s*/gm, '')
.replace(/\s*$/gm, '')
.replace(/\n/gm, '')
.replace(/\/>\s*</gm, '/><');

describe('Blocks#convertBlocksToTables tests', () => {
const test = (input, expected) => {
const { document } = (new JSDOM(input)).window;
Blocks.convertBlocksToTables(document, document);
strictEqual(trim(document.body.innerHTML), trim(expected));
};

const div = '<div></div>'; // ignored div for the tests

it('convertBlocksToTables basic block', () => {
test(
`<main>${div}${div}${div}
<div>
<div class="a-block">
<div>cell11</div>
<div>cell21</div>
</div>
</div>
</main>`,
`<main>${div}${div}${div}
<div>
<table>
<tr><th>A Block</th></tr>
<tr><td>cell11</td></tr>
<tr><td>cell21</td></tr>
</table>
</div>
</main>`,
);
test(
`<main>${div}${div}${div}
<div>
<div class="another-block">
<div>
<div>cell11</div>
<div>cell12</div>
</div>
<div>
<div>cell21</div>
<div>cell22</div>
</div>
<div>
<div><img src="https://www.sample.com/image.jpeg"></div>
<div><a href="https://www.sample.com/">A link</a></div>
</div>
</div>
</div>
</main>`,
`<main>${div}${div}${div}
<div>
<table>
<tr><th>Another Block</th></tr>
<tr><td>cell11</td><td>cell12</td></tr>
<tr><td>cell21</td><td>cell22</td></tr>
<tr><td><img src="https://www.sample.com/image.jpeg"></td><td><a href="https://www.sample.com/">A link</a></td></tr>
</table>
</div>
</main>`,
);
test(
`<main>${div}${div}${div}
<div>
<div class="promotion">
<div>
<div><a href="https://blog.adobe.com/en/promotions/doc-cloud-education.html">https://blog.adobe.com/en/promotions/doc-cloud-education.html</a></div>
</div>
</div>
</main>`,
`<main>${div}${div}${div}
<div>
<table>
<tr><th>Promotion</th></tr>
<tr><td><a href="https://blog.adobe.com/en/promotions/doc-cloud-education.html">https://blog.adobe.com/en/promotions/doc-cloud-education.html</a></td></tr>
</table>
</div>
</main>`,
);
});
});

describe('Blocks#getMetadataBlock tests', () => {
const test = (metadata, expected) => {
const { document } = (new JSDOM()).window;
const table = Blocks.getMetadataBlock(document, metadata);
strictEqual(trim(table.outerHTML), trim(expected));
};

it('getMetadataBlock string meta', () => {
test({ title: 'Some title' }, '<table><tr><th colspan="2">Metadata</th></tr><tr><td>title</td><td>Some title</td></tr></table>');
test({ Author: 'Name of the author', 'Creation Date': '2022/01/01' }, '<table><tr><th colspan="2">Metadata</th></tr><tr><td>Author</td><td>Name of the author</td></tr><tr><td>Creation Date</td><td>2022/01/01</td></tr></table>');
});

it('getMetadataBlock element meta', () => {
const { document } = (new JSDOM()).window;
const img = document.createElement('img');
img.src = 'https://www.sample.com/image.jpeg';
img.title = 'Image title';
img.alt = 'Image alt';
test({ title: 'Some title', Image: img }, '<table><tr><th colspan="2">Metadata</th></tr><tr><td>title</td><td>Some title</td></tr><tr><td>Image</td><td><img src="https://www.sample.com/image.jpeg" title="Image title" alt="Image alt"></td></tr></table>');
});

it('getMetadataBlock lists', () => {
test({ title: 'Some title', Tags: ['Creative', 'Experience Cloud', 'Photography'] }, '<table><tr><th colspan="2">Metadata</th></tr><tr><td>title</td><td>Some title</td></tr><tr><td>Tags</td><td>hlx_replaceTag(p)Creativehlx_replaceTag(/p)hlx_replaceTag(p)Experience Cloudhlx_replaceTag(/p)hlx_replaceTag(p)Photographyhlx_replaceTag(/p)</td></tr></table>');
});
});
Loading

0 comments on commit 3c93126

Please sign in to comment.