Skip to content

Commit 1935a9e

Browse files
committed
Support client-side markdown rendering and link to markdown docs
1 parent bc11943 commit 1935a9e

File tree

4 files changed

+175
-13
lines changed

4 files changed

+175
-13
lines changed

markdown/index.html

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<!doctype html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<title>Documentation | Eclipse Project</title>
7+
<link rel="preconnect stylesheet" href="../project.css" />
8+
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
9+
<script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js"></script>
10+
<script src="https://cdn.jsdelivr.net/npm/marked-gfm-heading-id/lib/index.umd.js"></script>
11+
<script src="../project.js"></script>
12+
</head>
13+
14+
<body>
15+
<div data-generate="generateDefaultBreadcrumb(this)">
16+
<a href="../index.html">Eclipse</a>
17+
</div>
18+
19+
<div data-generate="generateDefaults(this)">
20+
</div>
21+
22+
<main>
23+
<div id="markdown-target"></div>
24+
</main>
25+
26+
<script>
27+
generate();
28+
29+
const targetElement = document.getElementById('markdown-target');
30+
const file = new URLSearchParams(window.location.search).get('file');
31+
const parts = /(?<org>[^/]+)\/(?<repo>[^/]+)\/(?<branch>[^/]+)\/(?<path>.*)/.exec(file);
32+
const repoNames = {
33+
"eclipse-platform/eclipse.platform": "Platform",
34+
"eclipse-platform/eclipse.platform.ui": "Platform UI",
35+
"eclipse-pde/eclipse.pde": "PDE",
36+
"eclipse-equinox/p2": "Equinox p2",
37+
"eclipse-ide/.github": "Eclipse IDE",
38+
};
39+
40+
function niceName(name) {
41+
return name.replaceAll(/[_-]/g, ' ').replaceAll(/([a-z])([A-Z])/g, '$1 $2').replace(/^([a-z])/, letter => letter.toLocaleUpperCase())
42+
}
43+
44+
function fixHash(hash) {
45+
return hash.toLowerCase();
46+
}
47+
48+
function generateFileList(files) {
49+
const fileElements = files.map(file => {
50+
const fileURL = new URL(file.url);
51+
const fileName = fileURL.pathname.endsWith('/docs') || fileURL.pathname.endsWith('/profile') ?
52+
/(?<filename>[^/]+)$/.exec(fileURL.pathname) :
53+
/(?<filename>[^/]+)\.md$/.exec(fileURL.pathname);
54+
if (fileName == null) {
55+
return '';
56+
}
57+
const branch = fileURL.searchParams.get('ref');
58+
const parts = /\/repos\/(?<org>[^/]+)\/(?<repo>[^/]+)\/contents\/(?<path>.*)/.exec(fileURL.pathname);
59+
const url = new URL(window.location);
60+
url.hash = '';
61+
url.search = `?file=${parts.groups.org}/${parts.groups.repo}/${branch}/${parts.groups.path}`;
62+
const label = niceName(fileName.groups.filename);
63+
return `<div><a href="${url}">${label}<a/></div>\n`;
64+
});
65+
66+
const folder = parts.groups.path.replace(/\/$/, '');
67+
const heading = `<h2>Contents of ${parts.groups.org}/${parts.groups.repo}${folder.length == 0 ? '' : ` - ${folder}`}</h2>\n`;
68+
69+
targetElement.innerHTML = heading + fileElements.join('');
70+
}
71+
72+
if (parts == null || parts.length == 0) {
73+
targetElement.innerHTML = 'No well-formed query parameter of the form <code>?file=org/repo/branch/path</code> has been specified.';
74+
} else {
75+
const org = parts.groups.org;
76+
const repo = parts.groups.repo;
77+
const repoName = repoNames[`${org}/${repo}`];
78+
if (repoName == null) {
79+
targetElement.innerHTML = `The repository ${org}/${repo} is not on the allowed list.`;
80+
} else {
81+
document.title = `${repoName} Documentation | Eclipse Project`;
82+
83+
const branch = parts.groups.branch;
84+
const path = parts.groups.path;
85+
86+
const breadcrumb = document.querySelector(".breadcrumb");
87+
const normalizedPath = path.replace(/\/$/, '');
88+
const segments = normalizedPath == '' ? [''] : ['', ...normalizedPath.split('/')];
89+
let crumbPath = '';
90+
for (const segment of segments) {
91+
crumbPath = (crumbPath == '/' ? '/' : crumbPath + '/') + segment;
92+
breadcrumb.append(...toElements(`<li><a href="?file=${org}/${repo}/${branch}${crumbPath}">${segment.length == 0 ? repoName : niceName(segment.replace(/\.md$/, ''))}</a></li>`));
93+
}
94+
95+
const logicalBaseURL = new URL(`https://api.github.com/repos/${org}/${repo}/contents/${path}`);
96+
const mdLocation = `${logicalBaseURL}?ref=${branch}`;
97+
98+
sendRequest(mdLocation, request => {
99+
const response = JSON.parse(request.responseText);
100+
if (response instanceof Array) {
101+
generateFileList(response)
102+
} else {
103+
const text = blobToText(response.content);
104+
const editLink = `<a id="edit-markdown-link" href=""><span class="orange">\u270E Improve this page</span></a>\n`;
105+
targetElement.innerHTML = editLink + marked.use(markedGfmHeadingId.gfmHeadingId()).parse(text);
106+
107+
const imgs = targetElement.querySelectorAll("img[src]");
108+
for (const img of imgs) {
109+
const src = img.getAttribute('src');
110+
if (!src.startsWith('http')) {
111+
img.src = `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${src}`;
112+
}
113+
}
114+
115+
const as = targetElement.querySelectorAll("a[href]");
116+
for (const a of as) {
117+
const href = a.getAttribute('href');
118+
if (href == null) {
119+
continue;
120+
}
121+
122+
if (href.startsWith('#')) {
123+
a.setAttribute('href', fixHash(href));
124+
continue;
125+
}
126+
127+
const logicalHref = new URL(href, logicalBaseURL);
128+
const url = new URL(window.location);
129+
url.hash = fixHash(logicalHref.hash);
130+
if (logicalHref.hostname == 'api.github.com') {
131+
const parts = /\/repos\/(?<org>[^/]+)\/(?<repo>[^/]+)\/contents\/(?<path>.*)/.exec(logicalHref.pathname);
132+
if (parts != null) {
133+
url.search = `?file=${parts.groups.org}/${parts.groups.repo}/${branch}/${parts.groups.path}`;
134+
a.href = url;
135+
}
136+
} else if (logicalHref.hostname == 'github.com') {
137+
const parts = /(?<org>[^/]+)\/(?<repo>[^/]+)\/blob\/(?<branch>[^/]+)\/(?<path>.*)/.exec(logicalHref.pathname);
138+
if (parts != null) {
139+
url.search = `?file=${parts.groups.org}/${parts.groups.repo}/${parts.groups.branch}/${parts.groups.path}`;
140+
a.href = url;
141+
}
142+
}
143+
}
144+
145+
document.getElementById('edit-markdown-link').href = `https://github.com/${org}/${repo}/blob/${branch}/${path}`;
146+
}
147+
});
148+
}
149+
}
150+
</script>
151+
152+
</body>

news/4.36/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
1+
<!DOCTYPE html>
22
<html>
33

44
<head>

news/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
1+
<!DOCTYPE html>
22
<html>
33
<head>
44
<meta name="copyright" content="Copyright (c) Eclipse contributors and others 2020. This page is made available under license. For full details see: https://www.eclipse.org/legal/notice.html">

project.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,20 @@ let defaultAside = toElements(`
5353
<a class="separator" href="https://projects.eclipse.org/projects/eclipse"><i class='fa fa-cube'></i> Eclipse Project</a>
5454
<a href="https://projects.eclipse.org/projects/eclipse.equinox">Equinox</a>
5555
<a href="https://projects.eclipse.org/projects/eclipse.platform">Platform</a>
56-
<a href="swt/index.html">&nbsp;&nbsp;&bullet;&nbsp;SWT</a>
56+
<a href="${scriptBase}swt/index.html">&nbsp;&nbsp;&bullet;&nbsp;SWT</a>
5757
<a href="https://projects.eclipse.org/projects/eclipse.jdt">Java Development Tools</a>
5858
<a href="https://projects.eclipse.org/projects/eclipse.pde">Plug-in Development Environment</a>
5959
<span class="separator"><i class='fa fa-github'></i> GitHub</span>
6060
<a href="https://github.com/eclipse-equinox/">Equinox</a>
6161
<a href="https://github.com/eclipse-platform/">Platform</a>
6262
<a href="https://github.com/eclipse-jdt/">Java Development Tools</a>
6363
<a href="https://github.com/eclipse-pde/">Plug-in Development Environment</a>
64+
<span class="separator"><i class='fa fa-edit'></i> Markdown</span>
65+
<a href="${scriptBase}markdown/index.html?file=eclipse-platform/eclipse.platform/master/docs">Platform</a>
66+
<a href="${scriptBase}markdown/index.html?file=eclipse-platform/eclipse.platform.ui/master/docs">Platform UI</a>
67+
<a href="${scriptBase}markdown/index.html?file=eclipse-pde/eclipse.pde/master/docs">PDE</a>
68+
<a href="${scriptBase}markdown/index.html?file=eclipse-equinox/p2/master/docs">Equinox p2</a>
69+
<a href="${scriptBase}markdown/index.html?file=eclipse-ide/.github/main/">Eclipse IDE</a>
6470
`);
6571

6672
let selfContent = document.documentElement.outerHTML;
@@ -444,21 +450,25 @@ function sendRequest(location, handler) {
444450

445451
function getHTMLText(request) {
446452
if (request.responseURL.endsWith('.php')) {
447-
const php = JSON.parse(request.responseText);
448-
const binary = window.atob(php.content);
449-
const bytes = new Uint8Array(binary.length);
450-
for (var i = 0; i < binary.length; i++) {
451-
bytes[i] = binary.charCodeAt(i);
452-
}
453-
const decoder = new TextDecoder();
454-
const realText = decoder.decode(bytes);
455-
return realText;
453+
const response = JSON.parse(request.responseText);
454+
return blobToText(response.content);
456455
}
457456

458457
const html = request.responseText;
459458
return html;
460459
}
461460

461+
function blobToText(blob) {
462+
const binary = window.atob(blob);
463+
const bytes = new Uint8Array(binary.length);
464+
for (var i = 0; i < binary.length; i++) {
465+
bytes[i] = binary.charCodeAt(i);
466+
}
467+
const decoder = new TextDecoder();
468+
const realText = decoder.decode(bytes);
469+
return realText;
470+
}
471+
462472
function parseHTML(request, handler) {
463473
const location = request.responseURL;
464474
const xml = request.responseXML;
@@ -474,8 +484,8 @@ function parseHTML(request, handler) {
474484
const resultDocument = xsltProcessor.transformToFragment(xml, htmlDocument);
475485
handler(resultDocument);
476486
});
487+
return;
477488
}
478-
return;
479489
}
480490

481491
const html = getHTMLText(request);

0 commit comments

Comments
 (0)