Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hal-browser

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hal-browser - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

assets/css/.main.css.swp

8

changelog.md

@@ -0,1 +1,9 @@

0.4.0 (2018-08-09)
==================
* Support for `text/markdown`
* Support for `text/csv`
* Added default `code-repository` link to navigation.
0.3.0 (2018-07-08)

@@ -2,0 +10,0 @@ ==================

2

dist/html-index.d.ts
import { Context } from '@curveball/core';
import { SureOptions } from './types';
export default function generateHtmlIndex(ctx: Context, body: any, options: SureOptions): void;
export default function generateHtmlIndex(ctx: Context, body: any, options: SureOptions): Promise<void>;

@@ -6,16 +6,23 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const highlight_js_1 = __importDefault(require("highlight.js"));
const querystring_1 = __importDefault(require("querystring"));
const url_1 = __importDefault(require("url"));
function generateHtmlIndex(ctx, body, options) {
const links = fetchLinks(body, options);
const navHtml = generateNavigation(links, options);
const pagerHtml = generatePager(links, options);
const linksHtml = generateLinks(links, options);
const csv_body_1 = __importDefault(require("./components/csv-body"));
const hal_body_1 = __importDefault(require("./components/hal-body"));
const links_table_1 = __importDefault(require("./components/links-table"));
const markdown_body_1 = __importDefault(require("./components/markdown-body"));
const navigation_1 = __importDefault(require("./components/navigation"));
const pager_1 = __importDefault(require("./components/pager"));
const search_1 = __importDefault(require("./components/search"));
const util_1 = require("./util");
async function generateHtmlIndex(ctx, body, options) {
const links = util_1.fetchLinks(body, options);
const navHtml = navigation_1.default(links, options);
const pagerHtml = pager_1.default(links, options);
const linksHtml = links_table_1.default(links, options);
const [headTitle, bodyTitle] = generateTitle(links, ctx, options);
const bodyHtml = generateBody(body);
const searchHtml = generateSearch(links, options);
const bodyHtml = await parseBody(ctx);
const searchHtml = search_1.default(links, options);
const stylesheets = options.stylesheets.map(ss => {
return ` <link rel="stylesheet" href="${h(url_1.default.resolve(options.assetBaseUrl, ss))}" type="text/css" />\n`;
return ` <link rel="stylesheet" href="${util_1.h(url_1.default.resolve(options.assetBaseUrl, ss))}" type="text/css" />\n`;
}).join('');
ctx.response.type = 'text/html; charset=utf-8';
ctx.response.body = `

@@ -40,8 +47,4 @@ <!DOCTYPE html>

${linksHtml}
<h2>Contents</h2>
<code class="hljs"><pre>${bodyHtml}</pre></code>
${bodyHtml}
${pagerHtml}
</main>

@@ -54,117 +57,2 @@

exports.default = generateHtmlIndex;
function h(input) {
const map = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot'
};
return input.replace(/&<>"/g, s => map[s]);
}
function syntaxHighlightJson(body) {
return highlight_js_1.default.highlight('json', JSON.stringify(body, undefined, ' ')).value;
}
function generateBody(body) {
const tmpBody = Object.assign(body);
delete tmpBody._links;
return syntaxHighlightJson(tmpBody);
}
function generateLinks(links, options) {
let linkHtml = '';
// Grouping links by rel.
const groups = {};
for (const link of links) {
if (options.hiddenRels.includes(link.rel) || link.rel in options.navigationLinks) {
continue;
}
if (groups[link.rel]) {
groups[link.rel].push(link);
}
else {
groups[link.rel] = [link];
}
}
for (const group of Object.values(groups)) {
const linkCount = group.length;
let first = true;
for (const link of group) {
linkHtml += '<tr>';
if (first) {
linkHtml += `<td rowspan="${linkCount}">${h(link.rel)}</td>`;
first = false;
}
linkHtml += `<td><a href="${h(link.href)}">${h(link.href)}</a></td>`;
linkHtml += '<td>' + (link.title ? h(link.title) : '') + '</td>';
linkHtml += '</tr>\n';
}
}
if (!linkHtml) {
// No links
return '';
}
return `
<h2>Links</h2>
<table>
<tr>
<th>Relationship</th><th>Url</th><th>Title</th>
</tr>
${linkHtml}
</table>
`;
}
/**
* Returns the list of links for a section.
*
* This function sorts and normalizes the link.
*/
function getNavLinks(links, options, position) {
const result = [];
for (const link of links) {
// Don't handle templated links.
if (link.templated) {
continue;
}
if (options.navigationLinks[link.rel] === undefined) {
continue;
}
const nl = options.navigationLinks[link.rel];
if ((typeof nl.position === 'undefined' && position !== 'header') ||
(typeof nl.position !== 'undefined' && nl.position !== position)) {
continue;
}
result.push({
rel: link.rel,
href: link.href,
title: link.title ? link.title : (nl.defaultTitle ? nl.defaultTitle : link.rel),
icon: url_1.default.resolve(options.assetBaseUrl, nl.icon ? nl.icon : 'icon/' + link.rel + '.svg'),
priority: nl.priority ? nl.priority : 0,
showLabel: nl.showLabel,
});
}
return result.sort((a, b) => a.priority - b.priority);
}
function generateNavigation(links, options) {
const html = [];
for (const link of getNavLinks(links, options, 'header')) {
html.push(`<a href="${h(link.href)}" rel="${h(link.rel)}" title="${h(link.title)}">` +
`<img src="${link.icon}" />${link.showLabel ? ' ' + h(link.title) : ''}</a>`);
}
if (!html.length) {
return '';
}
const result = ' <ul>\n <li>' + html.join('</li>\n <li>') + ' </li>\n </ul>\n';
return result;
}
function generatePager(links, options) {
const html = [];
for (const link of getNavLinks(links, options, 'pager')) {
html.push(`<a href="${h(link.href)}" rel="${h(link.rel)}" title="${h(link.title)}">` +
`<img src="${h(link.icon)}" /> ${h(link.title)}</a>`);
}
if (!html.length) {
return '';
}
const result = ' <nav class="pager">\n <ul>\n <li>' + html.join('</li>\n <li>') + ' </li>\n </ul>\n </nav>\n';
return result;
}
function generateTitle(links, ctx, options) {

@@ -191,72 +79,20 @@ const selfLink = links.find(link => link.rel === 'self');

return [
`${h(title)} - ${options.title}`,
`<a href="${h(href)}" rel="self">${h(title)}</a> - ${options.title}`
`${util_1.h(title)} - ${options.title}`,
`<a href="${util_1.h(href)}" rel="self">${util_1.h(title)}</a> - ${options.title}`
];
}
function generateSearch(links, options) {
const searchRel = links.find(link => link.rel === 'search');
if (searchRel === undefined) {
return '';
async function parseBody(ctx) {
switch (ctx.response.type) {
case 'application/json':
case 'application/problem+json':
case 'application/hal+json':
return hal_body_1.default(ctx.response.body);
case 'text/markdown':
return markdown_body_1.default(ctx.response.body);
case 'text/csv':
return csv_body_1.default(ctx.response.body);
default:
return '';
}
if (!searchRel.templated) {
return '';
}
// We only support a very specific format. The link must be
// templated, have at most 1 templated field, and that field must
// appear in the query parameter.
//
// Sample format:
// {
// href: "/search?language=nl{?q}",
// templated: true
// }
//
// This regex might capture invalid templates, but it's not up to us to
// validate it.
const matches = searchRel.href.match(/^([^{]+){\?([a-zA-z0-9]+)}([^{]*)$/);
if (matches === null) {
return '';
}
// Url with the template variable stripped.
const newUrl = matches[1] + matches[3];
const [action, queryStr] = newUrl.split('?');
const query = querystring_1.default.parse(queryStr);
let html = `<form method="GET" action="${h(action)}" class="search">`;
html += '<img src="' + url_1.default.resolve(options.assetBaseUrl, 'icon/search.svg') + '" />';
for (const pair of Object.entries(query)) {
html += `<input type="hidden" name="${h(pair[0])}" value="${h(pair[1])}" />`;
}
html += `<input type="search" placeholder="Search" name="${h(matches[2])}" />`;
html += '</form>';
return html;
}
function fetchLinks(body, options) {
const result = Array.from(options.defaultLinks);
if (!body._links) {
return result;
}
for (const rel of Object.keys(body._links)) {
let linksTmp;
if (Array.isArray(body._links[rel])) {
linksTmp = body._links[rel];
}
else {
linksTmp = [body._links[rel]];
}
for (const link of linksTmp) {
if (!link.href) {
// tslint:disable:no-console
console.warn('Incorrect format for HAL link with rel: ' + rel);
}
result.push({
rel: rel,
href: link.href,
type: link.type,
title: link.title,
templated: link.templated,
});
}
}
return result;
}
//# sourceMappingURL=html-index.js.map

@@ -12,2 +12,4 @@ "use strict";

'application/problem+json',
'text/markdown',
'text/csv',
];

@@ -30,3 +32,2 @@ /*

* http://microformats.org/wiki/existing-rel-values
*
* - icon

@@ -38,3 +39,3 @@ */

},
'core-repository': true,
'code-repository': true,
'create-form': {

@@ -95,4 +96,3 @@ showLabel: true,

if (ctx.request.accepts('text/html', ...parsedContentTypes) === 'text/html') {
ctx.response.headers.set('Content-Type', 'text/html');
html_index_1.default(ctx, ctx.response.body, newOptions);
await html_index_1.default(ctx, ctx.response.body, newOptions);
}

@@ -99,0 +99,0 @@ };

{
"name": "hal-browser",
"version": "0.3.0",
"version": "0.4.0",
"description": "A HAL browser middleware",

@@ -40,2 +40,3 @@ "main": "dist/index.js",

"@types/highlight.js": "^9.12.3",
"@types/markdown-it": "0.0.4",
"@types/mocha": "^5.2.3",

@@ -60,4 +61,6 @@ "@types/node": "^10.3.6",

"@curveball/core": "^0.4.1",
"highlight.js": "^9.12.0"
"csv-parse": "^2.5.0",
"highlight.js": "^9.12.0",
"markdown-it": "^8.4.1"
}
}

@@ -12,3 +12,10 @@ HAL browser

It automatically decorates the following formats:
* `application/json`
* `application/problem+json`
* `application/hal+json`
* `text/markdown`
Screenshot

@@ -150,3 +157,2 @@ ----------

* Add a link to allow the user to see the raw format.
* Support displaying `text/csv` as a table.
* Support HTTP Link headers.

@@ -153,0 +159,0 @@ * A better interface for `_embedded`.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc