Public
Edited
Aug 24, 2023
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dot`digraph "${id}" {
outputorder=edgesfirst
graph[rankdir=LR, center=true]
node[shape=none, fontname="Source Serif Pro", fontsize=13]
edge[arrowsize=0.6, arrowhead=vee, color=gray]
${Array.from(
new Set(edges.map(([i, o]) => i).concat(edges.map(([i, o]) => o)))
)
.map(
id =>
`"${wrapText(id)}"[URL="?id=${cleanId(
id
)}", fontcolor="#3182bd", target="_top"]`
)
.join('\n')}
${edges.map(([i, o]) => `"${wrapText(i)}" -> "${wrapText(o)}"`).join("\n")}
}`
Insert cell
Insert cell
Insert cell
domsToDiv(pick(articles, 'intro'))
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Insert cell
pick = (v, k) => [].concat(...v.map(d => d[k]))
Insert cell
domsToDiv = doms => {
const container = document.createElement('div');
doms.forEach(dom => (dom ? container.appendChild(dom) : null));

return container;
}
Insert cell
cleanId = id => decodeURI(id.replace(`${baseUrl}/wiki/`, '').replace(/ /g, '_'))
Insert cell
lexer = text => text.split(/[_ ]/g)
Insert cell
wrapText = (text, len = 15) => {
const words = lexer(text);
let lines = '';
let count = 0;
for (let word of words) {
if (count + word.length >= len) {
lines += `\n${word} `;
count = word.length;
} else {
lines += `${word} `;
count += word.length;
}
}
return lines.trim();
}
Insert cell
qs = params =>
Object.keys(params)
.map(key => `${key}=${params[key]}`)
.join('&')
Insert cell
loadArticle = id =>
fetch(
`${baseUrl}/w/api.php?${qs({
format: 'json',
origin: '*',
action: 'parse',
prop: 'text',
redirects: true,
page: id,
section: 0
})}`
).then(response => response.json())
Insert cell
loadArticles = links =>
Promise.all(links.map(link => loadArticle(cleanId(link))))
Insert cell
domParser = new DOMParser()
Insert cell
Insert cell
constructDom = text => domParser.parseFromString(text, 'text/html')
Insert cell
Insert cell
selectIntro = dom =>
Array.from(
dom.querySelectorAll('.mw-parser-output > p:not(.mw-empty-elt)')
).find(el => !el.querySelector('#coordinates'))
Insert cell
importNode = dom => document.importNode(dom, true)
Insert cell
Insert cell
processResponse = response => {
if (!response || response.error || !response.parse) {
return {
id: '',
intro: null,
links: []
};
}
try {
const id = cleanId(response.parse.title);
const intro = importNode(
selectIntro(constructDom(addBaseToLinks(response.parse.text['*'])))
);
const links = filterLinks(extractLinks(intro));

return {
id,
intro,
links,
...response.parse
};
} catch (e) {
return {
id: '',
intro: null,
links: []
};
}
}
Insert cell
rootArticle = (await loadArticles([cleanId(id)])).map(processResponse)
Insert cell
secondArticles = (await loadArticles(pick(rootArticle, 'links'))).map(
processResponse
)
Insert cell
thirdArticles = []
//thirdArticles = (await loadArticles(pick(secondArticles, 'links'))).map(
// processResponse
//)
Insert cell
articles = (rootArticle ? rootArticle : []).concat(
secondArticles ? secondArticles : []
//, thirdArticles ? thirdArticles : []
)
Insert cell
redirects = pick(articles, 'redirects').filter(d => d)
Insert cell
edges = []
.concat(
...articles.map(article =>
article.links.map(link => [article.id, cleanId(link)])
)
)
.map(edge =>
edge.map(v =>
cleanId(
(redirects.find(redirect => cleanId(redirect.from) === v) || { to: v })
.to
)
)
)
Insert cell
Insert cell
dot = require("@observablehq/graphviz@0.2")
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more