Skip to content

Commit 851d1b5

Browse files
committed
chore(cli): fetch programming languages names from wikidata
1 parent df179c8 commit 851d1b5

File tree

6 files changed

+189
-49
lines changed

6 files changed

+189
-49
lines changed

catalog-data.ttl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
@prefix owl: <http://www.w3.org/2002/07/owl#> .
55
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
66
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
7+
@prefix wd: <http://www.wikidata.org/entity/> .
8+
@prefix wdt: <http://www.wikidata.org/prop/direct/> .
79
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
810

911
<http://harth.org/andreas/foaf#ah> a ex:Person ;
@@ -13,6 +15,57 @@
1315
ex:name "Andreas Harth" ;
1416
ex:webid <http://harth.org/andreas/foaf#ah> .
1517

18+
wd:Q161053 ex:name "Ruby" ;
19+
wdt:P31 wd:Q9143 .
20+
21+
wd:Q17147733 ex:name "Swift" ;
22+
wdt:P31 wd:Q9143 .
23+
24+
wd:Q2005 ex:name "JavaScript" ;
25+
wdt:P31 wd:Q9143 .
26+
27+
wd:Q2370 ex:name "C#" ;
28+
wdt:P31 wd:Q9143 .
29+
30+
wd:Q251 ex:name "Java" ;
31+
wdt:P31 wd:Q9143 .
32+
33+
wd:Q28865 ex:name "Python" ;
34+
wdt:P31 wd:Q9143 .
35+
36+
wd:Q34010 ex:name "Haskell" ;
37+
wdt:P31 wd:Q9143 .
38+
39+
wd:Q37227 ex:name "Go" ;
40+
wdt:P31 wd:Q9143 .
41+
42+
wd:Q3816639 ex:name "Kotlin" ;
43+
wdt:P31 wd:Q9143 .
44+
45+
wd:Q406009 ex:name "Dart" ;
46+
wdt:P31 wd:Q9143 .
47+
48+
wd:Q42478 ex:name "Perl" ;
49+
wdt:P31 wd:Q9143 .
50+
51+
wd:Q460584 ex:name "Scala" ;
52+
wdt:P31 wd:Q9143 .
53+
54+
wd:Q51885456 ex:name "Zig" ;
55+
wdt:P31 wd:Q9143 .
56+
57+
wd:Q5362035 ex:name "Elixir" ;
58+
wdt:P31 wd:Q9143 .
59+
60+
wd:Q575650 ex:name "Rust" ;
61+
wdt:P31 wd:Q9143 .
62+
63+
wd:Q59 ex:name "PHP" ;
64+
wdt:P31 wd:Q9143 .
65+
66+
wd:Q978185 ex:name "TypeScript" ;
67+
wdt:P31 wd:Q9143 .
68+
1669
<https://45h.inrupt.net/profile/card#me> a ex:Person ;
1770
ex:name "Luc" ;
1871
ex:webid <https://45h.inrupt.net/profile/card#me> .

cli/aggregations/wikidata.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { DataFactory, Store } from 'n3'
2+
import { dereferenceToStore } from 'rdf-dereference-store'
3+
import { queryDataset, prefixes, ex, schema } from '../util.ts'
4+
import type { NamedNode } from '@rdfjs/types'
5+
6+
export async function aggregateWikidata(dataset: Store): Promise<Store> {
7+
return aggregateProgrammingLanguages(dataset)
8+
}
9+
10+
async function getName(store: Store, language: NamedNode, tag: string): Promise<string | undefined> {
11+
const query = `
12+
SELECT ?s ?name
13+
WHERE {
14+
<${language.value}> <${schema.name}> ?name
15+
FILTER ( LANG(?name) = "${tag}" )
16+
}`
17+
18+
let bindings = await queryDataset(store, query)
19+
return bindings[0]?.get('name')?.value
20+
}
21+
22+
export async function aggregateProgrammingLanguages(dataset: Store): Promise<Store> {
23+
const instanceOf = `${prefixes.wdt}P31`
24+
const ProgrammingLanguage = `${prefixes.wd}Q9143`
25+
const langQuery = `
26+
SELECT ?s ?name
27+
WHERE {
28+
?s <${instanceOf}> <${ProgrammingLanguage}> .
29+
OPTIONAL { ?s <${ex.name}> ?name . }
30+
}`
31+
const lbindings = await queryDataset(dataset, langQuery)
32+
const withoutNames = lbindings.filter(b => !b.get('name')).map(b => b.get('s') as NamedNode)
33+
console.info(`Fetching names for programming langages: ${withoutNames.length}`)
34+
for (const language of withoutNames) {
35+
const { store } = await dereferenceToStore(language.value.replace('http', 'https'))
36+
let name = await getName(store, language, 'en')
37+
if (!name) name = await getName(store, language, 'mul')
38+
if (!name) {
39+
console.warn(`Couldn't find name for ${language.value}`)
40+
continue
41+
}
42+
const quad = DataFactory.quad(language, ex.terms.name, DataFactory.literal(name))
43+
dataset.add(quad)
44+
}
45+
return dataset
46+
}
47+

cli/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { validateWebid } from './validations/webid.ts'
66
import { migrateWebid } from './migrations/webid.ts'
77
import { aggregateW3C } from './aggregations/w3c.ts'
88
import { aggregateGithub } from './aggregations/github.ts'
9+
import { aggregateWikidata } from './aggregations/wikidata.ts'
910

1011
const dataPath = getPath(import.meta.url, '../catalog-data.ttl')
1112
const dataset = await loadData(dataPath)
@@ -58,4 +59,12 @@ aggregate.command('github')
5859
await saveData(updated, dataPath)
5960
})
6061

62+
aggregate.command('wikidata')
63+
.description('Adds data from Wikidata')
64+
.action(async () => {
65+
console.info('Fetching data Wikiadta')
66+
const updated = await aggregateWikidata(dataset)
67+
await saveData(updated, dataPath)
68+
})
69+
6170
program.parse(process.argv)

cli/util.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,16 @@ import { QueryEngine } from '@comunica/query-sparql-rdfjs'
1010
import { Store } from 'n3'
1111
import { write } from '@jeswr/pretty-turtle'
1212

13-
const prefixes = {
13+
export const prefixes = {
1414
rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
1515
xsd: 'http://www.w3.org/2001/XMLSchema#',
16+
wd: 'http://www.wikidata.org/entity/',
17+
wdt: 'http://www.wikidata.org/prop/direct/',
1618
con: 'https://solidproject.solidcommunity.net/catalog/taxonomy#',
1719
cdata: 'https://solidproject.solidcommunity.net/catalog/data#',
1820
ex: 'http://example.org#',
1921
}
2022

21-
export async function formatData(filePath: string): Promise<void> {
22-
const fromStream = await readQuadStream(filePath)
23-
const fromQuads = await arrayifyStream(fromStream)
24-
const outString = await write(fromQuads, { prefixes, ordered: true })
25-
fs.writeFileSync(filePath, outString)
26-
}
27-
2823
export async function loadData(filePath: string): Promise<Store> {
2924
const fromStream = await readQuadStream(filePath)
3025
return new Store(await arrayifyStream(fromStream))
@@ -35,7 +30,9 @@ export async function saveData(dataset: Store, filePath: string): Promise<void>
3530
fs.writeFileSync(filePath, outString)
3631
}
3732

38-
export const ex = createVocabulary('http://example.org#', 'webid', 'siloId', 'member', 'siloUsername', 'Person', 'Organization')
33+
export const ex = createVocabulary('http://example.org#', 'name', 'webid', 'siloId', 'member', 'siloUsername', 'Person', 'Organization')
34+
export const schema = createVocabulary('http://schema.org/', 'name')
35+
export const rdfs = createVocabulary('http://www.w3.org/2000/01/rdf-schema#', 'label')
3936

4037
export function getPath(from: string, to: string): string {
4138
const __filename = fileURLToPath(from)

0 commit comments

Comments
 (0)