├── versions.json ├── .prettierrc ├── styles.css ├── jest.config.js ├── .gitignore ├── tests ├── testFiles │ ├── README-test.md │ ├── Obsidian.json │ ├── History.json │ ├── History-subdiv.json │ └── Archaeology.json ├── loc.test.ts └── __snapshots__ │ └── loc.test.ts.snap ├── manifest.json ├── src ├── constants.ts ├── main.ts ├── interfaces.ts ├── methods │ ├── methods-loc.ts │ └── parseJson.ts └── settings.ts ├── .eslintrc.json ├── .github ├── dependabot.yml └── workflows │ ├── test.yml │ └── releases.yml ├── tsconfig.json ├── rollup.config.js ├── LICENSE ├── package.json ├── README.md ├── esbuild.mjs └── CHANGELOG.md /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "0.0.1": "0.12.15" 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "singleQuote": false, 4 | "printWidth": 80 5 | } -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | /* Sets all the text color to red! */ 2 | body { 3 | color: red; 4 | } 5 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | testMatch: ['src/tests/*.[jt]s?(x)', '**/?(*.)+(spec|test).[tj]s?(x)'] 6 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellij 2 | *.iml 3 | .idea 4 | 5 | # npm 6 | node_modules 7 | package-lock.json 8 | 9 | # build 10 | main.js 11 | *.js.map 12 | 13 | # obsidian 14 | data.json 15 | 16 | resources/ 17 | build/ 18 | 19 | *.zip 20 | .vscode/ -------------------------------------------------------------------------------- /tests/testFiles/README-test.md: -------------------------------------------------------------------------------- 1 | # What the test data represents 2 | 3 | The JSON files in this folder are individual lines from the LCSH `jsonld` MADS/RDF file from [here](https://id.loc.gov/download/). They cover multiple scenarios. 4 | 5 | They've been pretty-printed. -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "linked-data-helper", 3 | "name": "Linked Data Helper", 4 | "version": "1.0.0", 5 | "minAppVersion": "0.12.15", 6 | "description": "Parse Linked data for Linked Data Vocabularies.", 7 | "author": "kometenstaub", 8 | "authorUrl": "https://github.com/kometenstaub", 9 | "isDesktopOnly": true 10 | } 11 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | export const PREF_LABEL = "madsrdf:authoritativeLabel"; 2 | export const HAS_VARIANT = "madsrdf:hasVariant"; 3 | export const VARIANT_LABEL = "madsrdf:variantLabel"; 4 | export const BROADER = "madsrdf:hasBroaderAuthority"; 5 | export const RELATED = "madsrdf:hasReciprocalAuthority"; 6 | export const NARROWER = "madsrdf:hasNarrowerAuthority"; 7 | export const NOTE = "madsrdf:note"; 8 | export const CLASSIFICATION = "madsrdf:classification"; 9 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended" 9 | ], 10 | "parser": "@typescript-eslint/parser", 11 | "parserOptions": { 12 | "ecmaVersion": 2021, 13 | "sourceType": "module" 14 | }, 15 | "plugins": [ 16 | "@typescript-eslint" 17 | ], 18 | "rules": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "es2018", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "importsNotUsedAsValues":"error", 13 | "strict": true, 14 | "allowSyntheticDefaultImports": true, 15 | "lib": [ 16 | "dom", 17 | "es5", 18 | "scripthost", 19 | "es2018" 20 | ] 21 | }, 22 | "include": [ 23 | "src/**.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test Linked Data Helper 2 | 3 | on: 4 | push: 5 | pull_request: 6 | branches: 7 | - main 8 | 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Use Node.js 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: '18.x' # You might need to adjust this value to your own version 21 | - name: npm install 22 | id: npm-install 23 | run: | 24 | npm install 25 | - name: Test 26 | id: test 27 | run: | 28 | npm run test 29 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from '@rollup/plugin-typescript'; 2 | import {nodeResolve} from '@rollup/plugin-node-resolve'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | 5 | const isProd = (process.env.BUILD === 'production'); 6 | 7 | const banner = 8 | `/* 9 | THIS IS A GENERATED/BUNDLED FILE BY ROLLUP 10 | if you want to view the source visit the plugins github repository 11 | */ 12 | `; 13 | 14 | export default { 15 | input: 'main.ts', 16 | output: { 17 | dir: '.', 18 | sourcemap: 'inline', 19 | sourcemapExcludeSources: isProd, 20 | format: 'cjs', 21 | exports: 'default', 22 | banner, 23 | }, 24 | external: ['obsidian'], 25 | plugins: [ 26 | typescript(), 27 | nodeResolve({browser: true}), 28 | commonjs(), 29 | ] 30 | }; -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { Plugin } from "obsidian"; 2 | import LiDaHeSettingsTab from "./settings"; 3 | import { SkosMethods } from "./methods/methods-loc"; 4 | import type { LiDaHeSettings } from "./interfaces"; 5 | 6 | const DEFAULT_SETTINGS: LiDaHeSettings = { 7 | lcshInputPath: "", 8 | lcshOutputPath: "", 9 | }; 10 | 11 | export default class LinkedDataHelperPlugin extends Plugin { 12 | methods_loc = new SkosMethods(this.app, this); 13 | settings!: LiDaHeSettings; 14 | 15 | async onload() { 16 | console.log("loading Linked Data Helper plugin"); 17 | 18 | await this.loadSettings(); 19 | 20 | this.addSettingTab(new LiDaHeSettingsTab(this.app, this)); 21 | } 22 | 23 | onunload() { 24 | console.log("unloading Linked Data Helper plugin"); 25 | } 26 | 27 | async loadSettings() { 28 | this.settings = Object.assign( 29 | {}, 30 | DEFAULT_SETTINGS, 31 | await this.loadData() 32 | ); 33 | } 34 | 35 | async saveSettings() { 36 | await this.saveData(this.settings); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2023 kometenstaub 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "linked-data-helper", 3 | "version": "1.0.0", 4 | "description": "Add SKOS heading classification to YAML.", 5 | "main": "src/main.ts", 6 | "scripts": { 7 | "dev": "cross-env BUILD=dev node esbuild.mjs", 8 | "build": "cross-env BUILD=production node esbuild.mjs", 9 | "release": "standard-version", 10 | "lint": "npx eslint src/", 11 | "test": "jest", 12 | "format": "npx prettier --write src/ tests/*.ts" 13 | }, 14 | "standard-version": { 15 | "t": "" 16 | }, 17 | "keywords": [], 18 | "author": "kometenstaub", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "@types/jest": "^29.5.1", 22 | "@types/node": "^18.15.13", 23 | "@types/split2": "^4.2.0", 24 | "@typescript-eslint/eslint-plugin": "^5.59.0", 25 | "@typescript-eslint/parser": "^5.59.0", 26 | "cross-env": "^7.0.3", 27 | "esbuild": "^0.17.17", 28 | "eslint": "^8.39.0", 29 | "jest": "^29.5.0", 30 | "obsidian": "^1.2.5", 31 | "prettier": "2.5.0", 32 | "process": "^0.11.10", 33 | "standard-version": "^9.5.0", 34 | "ts-jest": "^29.1.0", 35 | "tslib": "^2.5.0", 36 | "typescript": "^4.9.5" 37 | }, 38 | "dependencies": { 39 | "split2": "^4.2.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.github/workflows/releases.yml: -------------------------------------------------------------------------------- 1 | # From: https://github.com/argenos/nldates-obsidian/blob/master/.github/workflows/release.yml 2 | name: Release obsidian plugin 3 | 4 | on: 5 | push: 6 | # Sequence of patterns matched against refs/tags 7 | tags: 8 | - '*' # Push events to matching any tag format, i.e. 1.0, 20.15.10 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - name: Use Node.js 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: "18.x" 22 | 23 | - name: Build plugin 24 | run: | 25 | npm install 26 | npm run test --if-present 27 | npm run build --if-present 28 | npx rexreplace "^.*?#(#+\s\[.*?\n.*?)(?=\s*#+\s\[)" "_" -s -M -G -m -o "CHANGELOG.md" > CHANGELOG-LATEST.md 29 | 30 | - name: Create release 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | run: | 34 | tag="${GITHUB_REF#refs/tags/}" 35 | 36 | gh release create "$tag" \ 37 | --title="$tag" \ 38 | -F CHANGELOG-LATEST.md \ 39 | build/main.js build/manifest.json 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linked Data Helper 2 | 3 | > [!important] 4 | > 5 | > This plugin has been updated to work with the new bulk exports from the Library of Congress. 6 | > 7 | > This update also includes some fixes. 8 | 9 | [![Test Linked Data Helper](https://github.com/kometenstaub/linked-data-helper/actions/workflows/test.yml/badge.svg)](https://github.com/kometenstaub/linked-data-helper/actions/workflows/test.yml) 10 | [![Build obsidian plugin](https://github.com/kometenstaub/linked-data-helper/actions/workflows/releases.yml/badge.svg)](https://github.com/kometenstaub/linked-data-helper/actions/workflows/releases.yml) 11 | 12 | This plugin is needed for generating the data that the [Linked Data Vocabularies](https://github.com/kometenstaub/obsidian-linked-data-vocabularies) Obsidian plugin relies on. 13 | 14 | The settings have a step-by-step guide for each implemented dataset. (Currently, LCSH is supported, but there are plans to extend support to other linked data.) 15 | 16 | By default, if possible, the generated files will be stored in the attachments folder, in the `linked-data-vocabularies` subfolder. If this is not possible, the settings will tell you. 17 | 18 | In that case, you will have to input another path. You can also input an alternative output path, if you so wish. 19 | 20 | After the conversion is done, this plugin can be disabled until you want to update the data or add another dataset. 21 | 22 | ## Credits 23 | 24 | This plugin uses the 'split2' npm package (https://www.npmjs.com/package/split2). It is licensed under the 'ISC License'. The license can be found [here](https://github.com/kometenstaub/linked-data-helper/blob/main/esbuild.js). 25 | -------------------------------------------------------------------------------- /src/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface LiDaHeSettings { 2 | lcshInputPath: string; 3 | lcshOutputPath: string; 4 | } 5 | 6 | export interface headings { 7 | pL: string; // prefLabel 8 | uri: string; 9 | aL?: string[]; // altLabel 10 | bt?: string[]; // broader 11 | nt?: string[]; // narrower 12 | rt?: string[]; // related 13 | note?: string; 14 | lcc?: string; 15 | } 16 | 17 | declare module "obsidian" { 18 | interface App { 19 | commands: { 20 | addCommand: any; 21 | removeCommand: any; 22 | }; 23 | settings: LiDaHeSettings; 24 | } 25 | interface Vault { 26 | getAvailablePathForAttachments: ( 27 | fileName: string, 28 | extension?: string, 29 | currentFile?: TFile 30 | ) => Promise; 31 | config: { 32 | attachmentFolderPath: string; 33 | }; 34 | } 35 | } 36 | 37 | export interface uriToHeading { 38 | [key: string]: string; 39 | } 40 | 41 | // prettier-ignore 42 | export interface LcshInterface { 43 | "@context": "http://v3/authorities/subjects/context.json"; 44 | "@graph": Graph[]; 45 | // "/authorities/subjects/sh00000023" 46 | "@id": string; 47 | } 48 | 49 | // prettier-ignore 50 | export interface Graph { 51 | // "http://id.loc.gov/authorities/subjects/sh00000023" 52 | "@id": string; 53 | "madsrdf:authoritativeLabel": LanguageAndValue; 54 | "madsrdf:variantLabel": LanguageAndValue; 55 | "madsrdf:hasVariant"?: Id[] | Id; 56 | "madsrdf:hasBroaderAuthority"?: Id[] | Id; 57 | "madsrdf:hasReciprocalAuthority"?: Id[] | Id; 58 | "madsrdf:hasNarrowerAuthority"?: Id[] | Id; 59 | "madsrdf:note"?: string | string[]; 60 | "madsrdf:classification"?: Id; 61 | } 62 | 63 | // prettier-ignore 64 | export interface SkolemGraphNode extends Graph { 65 | "@id": string; 66 | "madsrdf:code": string; 67 | } 68 | 69 | // prettier-ignore 70 | interface Id { 71 | "@id": string; 72 | } 73 | 74 | // prettier-ignore 75 | interface LanguageAndValue { 76 | "@language": Language; 77 | "@value": string; 78 | } 79 | 80 | // prettier-ignore 81 | enum Language { 82 | En = "en", 83 | } 84 | -------------------------------------------------------------------------------- /esbuild.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from "esbuild"; 2 | import fs from "fs"; 3 | import process from "process"; 4 | 5 | const banner = `/* 6 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD 7 | If you want to view the source, visit the plugins’ github repository. 8 | 9 | This plugin uses the 'split2' npm package (https://www.npmjs.com/package/split2). It is licensed under the 'ISC License': 10 | 11 | Copyright (c) 2014-2021, Matteo Collina hello@matteocollina.com 12 | 13 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | This plugin is licensed as follows: 18 | MIT License 19 | 20 | Copyright (c) 2021-2023 kometenstaub 21 | 22 | Permission is hereby granted, free of charge, to any person obtaining a copy 23 | of this software and associated documentation files (the "Software"), to deal 24 | in the Software without restriction, including without limitation the rights 25 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 | copies of the Software, and to permit persons to whom the Software is 27 | furnished to do so, subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in all 30 | copies or substantial portions of the Software. 31 | 32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 | SOFTWARE. 39 | 40 | */ 41 | `; 42 | 43 | 44 | const copyManifest = { 45 | name: 'copy-manifest', 46 | setup: (build) => { 47 | build.onEnd(() => { 48 | fs.copyFileSync('manifest.json', 'build/manifest.json'); 49 | }); 50 | }, 51 | }; 52 | 53 | const isProd = process.env.BUILD === 'production'; 54 | 55 | const context = await esbuild.context( 56 | { 57 | entryPoints: ['src/main.ts'], 58 | bundle: true, 59 | target: 'es2018', 60 | platform: 'node', 61 | external: ['obsidian'], 62 | format: 'cjs', 63 | banner: { js: banner }, 64 | sourcemap: isProd ? false : 'inline', 65 | minify: isProd, 66 | treeShaking: true, 67 | logLevel: "info", 68 | define: { 69 | 'process.env.NODE_ENV': JSON.stringify(process.env.BUILD), 70 | }, 71 | outfile: 'build/main.js', 72 | plugins: [copyManifest], 73 | }); 74 | 75 | if (isProd) { 76 | await context.rebuild(); 77 | process.exit(0); 78 | } else { 79 | await context.watch(); 80 | } -------------------------------------------------------------------------------- /src/methods/methods-loc.ts: -------------------------------------------------------------------------------- 1 | import { App, normalizePath, Notice } from "obsidian"; 2 | import type LinkedDataHelperPlugin from "../main"; 3 | import type { headings, LcshInterface } from "../interfaces"; 4 | import { createReadStream } from "fs"; 5 | import split2 from "split2"; 6 | import { parseJsonHeading } from "./parseJson"; 7 | import * as fs from "fs"; 8 | 9 | export class SkosMethods { 10 | app: App; 11 | plugin: LinkedDataHelperPlugin; 12 | 13 | constructor(app: App, plugin: LinkedDataHelperPlugin) { 14 | this.app = app; 15 | this.plugin = plugin; 16 | } 17 | 18 | public convertMadsRdfJsonld(outputPath?: string) { 19 | const jsonPrefLabel: headings[] = []; 20 | const subdivisions: headings[] = []; 21 | const jsonUriToPrefLabel = {}; 22 | let inputPath = ""; 23 | if (fs.existsSync(this.plugin.settings.lcshInputPath)) { 24 | inputPath = this.plugin.settings.lcshInputPath; 25 | } else { 26 | const message = 27 | "The file could not be read. Please check the path you provided."; 28 | new Notice(message); 29 | throw Error(message); 30 | } 31 | let newOutputPath = ""; 32 | if (outputPath) { 33 | newOutputPath = outputPath; 34 | } 35 | 36 | createReadStream(inputPath) 37 | .pipe(split2(JSON.parse)) 38 | .on("error", () => { 39 | new Notice("Something went wrong while parsing the file."); 40 | }) 41 | .on("data", (obj: LcshInterface) => { 42 | parseJsonHeading( 43 | obj, 44 | jsonPrefLabel, 45 | subdivisions, 46 | jsonUriToPrefLabel 47 | ); 48 | }) 49 | .on("end", () => { 50 | let jsonPrefPath = ""; 51 | let jsonUriPath = ""; 52 | let jsonSubdivPath = ""; 53 | const { adapter } = this.app.vault; 54 | if (newOutputPath === "") { 55 | const attachmentFolder = normalizePath( 56 | this.app.vault.config.attachmentFolderPath + 57 | "/" + 58 | "linked-data-vocabularies/" 59 | ); 60 | (async () => { 61 | const isDir = await adapter.exists(attachmentFolder); 62 | if (!isDir) { 63 | await adapter.mkdir(attachmentFolder); 64 | } 65 | jsonPrefPath = normalizePath(attachmentFolder + '/' + 'lcshSuggester.json'); 66 | jsonUriPath = normalizePath(attachmentFolder + '/' + 'lcshUriToPrefLabel.json'); 67 | jsonSubdivPath = normalizePath(attachmentFolder + '/' + 'lcshSubdivSuggester.json'); 68 | await adapter.write(jsonPrefPath, JSON.stringify(jsonPrefLabel)); 69 | await adapter.write(jsonUriPath, JSON.stringify(jsonUriToPrefLabel)); 70 | await adapter.write(jsonSubdivPath, JSON.stringify(subdivisions)); 71 | })(); 72 | } else { 73 | jsonPrefPath = normalizePath( 74 | newOutputPath + "/" + "lcshSuggester.json" 75 | ); 76 | jsonUriPath = normalizePath( 77 | newOutputPath + "/" + "lcshUriToPrefLabel.json" 78 | ); 79 | jsonSubdivPath = normalizePath( 80 | newOutputPath + "/" + "lcshSubdivSuggester.json" 81 | ); 82 | (async () => { 83 | await adapter.write( 84 | jsonPrefPath, 85 | JSON.stringify(jsonPrefLabel) 86 | ); 87 | // prettier-ignore 88 | await adapter.write(jsonUriPath, JSON.stringify(jsonUriToPrefLabel)); 89 | // prettier-ignore 90 | await adapter.write(jsonSubdivPath, JSON.stringify(subdivisions)); 91 | })(); 92 | } 93 | 94 | new Notice("The three JSON files have been written."); 95 | }); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [1.0.0](https://github.com/kometenstaub/linked-data-helper/compare/0.1.8...1.0.0) (2023-04-23) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * file writing when folder does not exist ([76836a5](https://github.com/kometenstaub/linked-data-helper/commit/76836a59fe60f85c7b51adeee03ab691541a6e46)) 11 | 12 | ### [0.1.8](https://github.com/kometenstaub/linked-data-helper/compare/0.1.7...0.1.8) (2023-04-21) 13 | 14 | ### [0.1.7](https://github.com/kometenstaub/linked-data-helper/compare/0.1.6...0.1.7) (2023-04-21) 15 | 16 | ### [0.1.6](https://github.com/kometenstaub/linked-data-helper/compare/0.1.5...0.1.6) (2023-04-21) 17 | 18 | ### [0.1.5](https://github.com/kometenstaub/linked-data-helper/compare/0.1.4...0.1.5) (2023-04-21) 19 | 20 | ### [0.1.4](https://github.com/kometenstaub/linked-data-helper/compare/0.1.3...0.1.4) (2023-04-21) 21 | 22 | ### [0.1.3](https://github.com/kometenstaub/linked-data-helper/compare/0.1.2...0.1.3) (2022-07-13) 23 | 24 | ### [0.1.2](https://github.com/kometenstaub/linked-data-helper/compare/0.1.1...0.1.2) (2021-12-20) 25 | 26 | 27 | ### Bug Fixes 28 | 29 | * better error handling ([94a7837](https://github.com/kometenstaub/linked-data-helper/commit/94a78379e5a066f0dc61a21fca27f24d18c2f52a)), closes [#4](https://github.com/kometenstaub/linked-data-helper/issues/4) 30 | * correct Archaeology heading in JSON file ([92081d8](https://github.com/kometenstaub/linked-data-helper/commit/92081d81573b33c194c43e993b2a336691b49f80)) 31 | 32 | ### [0.1.1](https://github.com/kometenstaub/linked-data-helper/compare/0.1.0...0.1.1) (2021-11-27) 33 | 34 | ## [0.1.0](https://github.com/kometenstaub/linked-data-helper/compare/0.0.2...0.1.0) (2021-11-09) 35 | 36 | 37 | ### Bug Fixes 38 | 39 | * :bug: LCC works again ([3eabb4c](https://github.com/kometenstaub/linked-data-helper/commit/3eabb4c230c6c7e3c63d9225f5abd023869b0bb2)) 40 | * :bug: skolem IRIs in relations are now resolved ([778b472](https://github.com/kometenstaub/linked-data-helper/commit/778b472b7608da0ad278a040291cf8279d2bf8b7)) 41 | 42 | ### [0.0.2](https://github.com/kometenstaub/linked-data-helper/compare/0.0.1...0.0.2) (2021-10-30) 43 | 44 | 45 | ### Bug Fixes 46 | 47 | * :bug: make it only installable on desktop ([70518fd](https://github.com/kometenstaub/linked-data-helper/commit/70518fd03c92d7e5ccc42d1501657215588f7393)) 48 | 49 | ### 0.0.1 (2021-10-30) 50 | 51 | 52 | ### Features 53 | 54 | * :sparkles: Added third JSON export ([77976a7](https://github.com/kometenstaub/linked-data-helper/commit/77976a7ecf188c7687d9afa2ac6614435261f708)) 55 | * :sparkles: input and output path ([9208adb](https://github.com/kometenstaub/linked-data-helper/commit/9208adb511b059050db11a2a91c40760ac1e693e)) 56 | * :sparkles: make JSON keys shorter to reduce file size ([5353359](https://github.com/kometenstaub/linked-data-helper/commit/53533599d9ef3d2886480841471c505fad5a6b38)) 57 | * :sparkles: only add fields with information to reduce file size ([c946c25](https://github.com/kometenstaub/linked-data-helper/commit/c946c25db02bc275b88a6222523a5fb3c3ba15bc)) 58 | * :sparkles: parsing relations for LCSH ([a2443a8](https://github.com/kometenstaub/linked-data-helper/commit/a2443a894e2df54eaa2cfc25595692e847c28c91)) 59 | * :sparkles: reduce size of URI to prefLabel JSON file ([60ded90](https://github.com/kometenstaub/linked-data-helper/commit/60ded9042d18b5b9aebeed69d38c26bbba259508)) 60 | * :sparkles: use attachment path instead of plugin dir for files ([bd0c01d](https://github.com/kometenstaub/linked-data-helper/commit/bd0c01d5b34e871d72cb2c7be68501e9507fc8dc)) 61 | * :sparkles: write files to attachment path or specified folder ([7d4014f](https://github.com/kometenstaub/linked-data-helper/commit/7d4014fada46219207e2702655a03c17124aea30)) 62 | * :sparkles: write uri to prefLabel JSON file ([34283ac](https://github.com/kometenstaub/linked-data-helper/commit/34283acff8cd8bf29866f57eac79c8a678554aab)) 63 | 64 | 65 | ### Bug Fixes 66 | 67 | * :bug: change array to object ([7adb74c](https://github.com/kometenstaub/linked-data-helper/commit/7adb74cfa4046753bd12b5a49930646b30c1cba3)) 68 | * :bug: wrong variable names are now correct in export ([a1d1ef6](https://github.com/kometenstaub/linked-data-helper/commit/a1d1ef67d5374301efaba00b7b29000d0b498548)) 69 | * :goal_net: better error handling ([1646371](https://github.com/kometenstaub/linked-data-helper/commit/1646371f5bdf787b5783c8781a24720a136c4c09)) 70 | * :goal_net: catch error ([6b62933](https://github.com/kometenstaub/linked-data-helper/commit/6b62933ab529aeb7ae45ce20bc12e36e6b879ef8)) 71 | -------------------------------------------------------------------------------- /tests/loc.test.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync } from "fs"; 2 | import { parseJsonHeading } from "../src/methods/parseJson"; 3 | import type { headings, LcshInterface, uriToHeading } from "../src/interfaces"; 4 | 5 | function readJson(fileName: string): LcshInterface { 6 | const currentFile = readFileSync(`tests/testFiles/${fileName}`, { 7 | encoding: "utf-8", 8 | }); 9 | return JSON.parse(currentFile); 10 | } 11 | 12 | function jsonOutput(filename: string) { 13 | const obj = readJson(filename); 14 | const jsonPrefLabel: headings[] = []; 15 | const subdivisions: headings[] = []; 16 | const jsonUriToPrefLabel: uriToHeading = {}; 17 | parseJsonHeading(obj, jsonPrefLabel, subdivisions, jsonUriToPrefLabel); 18 | return { jsonPrefLabel, subdivisions, jsonUriToPrefLabel }; 19 | } 20 | 21 | function matchSnapshot( 22 | jsonPrefLabel: headings[], 23 | subdivisions: headings[], 24 | jsonUriToPrefLabel: uriToHeading 25 | ) { 26 | expect(jsonPrefLabel).toMatchSnapshot(); 27 | expect(subdivisions).toMatchSnapshot(); 28 | expect(jsonUriToPrefLabel).toMatchSnapshot(); 29 | } 30 | 31 | function getProperties(jsonPrefLabel: headings[], subdivisions: headings[]) { 32 | let pL, aL, bt, nt, rt, note, lcc, uri; 33 | const heading = jsonPrefLabel[0]; 34 | const subdivs = subdivisions[0]; 35 | if (heading !== undefined) { 36 | ({ pL, aL, bt, nt, rt, note, lcc, uri } = heading); 37 | } else { 38 | ({ pL, aL, bt, nt, rt, note, lcc, uri } = subdivs); 39 | } 40 | return { pL, aL, bt, nt, rt, note, lcc, uri }; 41 | } 42 | /** 43 | * unit test 44 | */ 45 | test("History URI is correct", () => { 46 | const obj = readJson("History.json"); 47 | expect(obj["@id"]).toBe("/authorities/subjects/sh85061227"); 48 | }); 49 | 50 | /** 51 | * Snapshot tests 52 | */ 53 | 54 | test("Snapshot of JSON parsing logic History.json", () => { 55 | const { jsonPrefLabel, subdivisions, jsonUriToPrefLabel } = 56 | jsonOutput("History.json"); 57 | matchSnapshot(jsonPrefLabel, subdivisions, jsonUriToPrefLabel); 58 | }); 59 | 60 | test("Snapshot of JSON parsing logic History-subdiv.json", () => { 61 | const { jsonPrefLabel, subdivisions, jsonUriToPrefLabel } = jsonOutput( 62 | "History-subdiv.json" 63 | ); 64 | matchSnapshot(jsonPrefLabel, subdivisions, jsonUriToPrefLabel); 65 | }); 66 | 67 | test("Snapshot of JSON parsing logic Archaeology.json", () => { 68 | const { jsonPrefLabel, subdivisions, jsonUriToPrefLabel } = 69 | jsonOutput("Archaeology.json"); 70 | matchSnapshot(jsonPrefLabel, subdivisions, jsonUriToPrefLabel); 71 | }); 72 | 73 | test("Snapshot of JSON parsing logic Obsidian.json", () => { 74 | const { jsonPrefLabel, subdivisions, jsonUriToPrefLabel } = 75 | jsonOutput("Obsidian.json"); 76 | matchSnapshot(jsonPrefLabel, subdivisions, jsonUriToPrefLabel); 77 | }); 78 | 79 | /** 80 | * more unit tests 81 | */ 82 | 83 | test("multiple Archaeology properties of JSON objects", () => { 84 | const { jsonPrefLabel, subdivisions, jsonUriToPrefLabel } = 85 | jsonOutput("Archaeology.json"); 86 | const { pL, aL, bt, nt, rt, note, lcc, uri } = getProperties( 87 | jsonPrefLabel, 88 | subdivisions 89 | ); 90 | const expectedPL = "Archaeology"; 91 | expect(pL).toBe(expectedPL); 92 | expect(aL).toStrictEqual(["Archeology"]); 93 | expect(lcc).toBe("CC"); 94 | expect(note).toBe( 95 | "Here are entered works on archaeology as a branch of learning. This heading may be divided geographically for works on this branch of learning in a specific place. Works on the antiquities of particular regions, countries, cities, etc. are entered under the name of the place subdivided by [Antiquities.]" 96 | ); 97 | expect(uri).toBe("sh85006507"); 98 | expect((bt as string[]).length).toEqual(3); 99 | expect((nt as string[]).length).toEqual(64); 100 | expect(rt).toStrictEqual(["sh85005757"]); 101 | expect(subdivisions).toStrictEqual([]); 102 | expect(jsonUriToPrefLabel).toStrictEqual({ sh85006507: expectedPL }); 103 | }); 104 | 105 | test("multiple History-subdiv properties of JSON objects", () => { 106 | const { jsonPrefLabel, subdivisions, jsonUriToPrefLabel } = jsonOutput( 107 | "History-subdiv.json" 108 | ); 109 | const { pL, aL, bt, nt, rt, note, lcc, uri } = getProperties( 110 | jsonPrefLabel, 111 | subdivisions 112 | ); 113 | const expectedPL = "History"; 114 | expect(pL).toBe(expectedPL); 115 | expect(aL).toStrictEqual(["Frontier troubles"]); 116 | expect(lcc).toStrictEqual(undefined); 117 | expect(note).toBe( 118 | "Use as a topical subdivision under names of countries, cities, etc., and individual corporate bodies, uniform titles of sacred works, and under classes of persons, ethnic groups, and topical headings." 119 | ); 120 | expect(uri).toBe("sh99005024"); 121 | expect(jsonUriToPrefLabel).toStrictEqual({ sh99005024: expectedPL }); 122 | }); 123 | 124 | test("broader term is the ID", () => { 125 | const { jsonPrefLabel, subdivisions, jsonUriToPrefLabel } = 126 | jsonOutput("Obsidian.json"); 127 | const { pL, aL, bt, nt, rt, note, lcc, uri } = getProperties( 128 | jsonPrefLabel, 129 | subdivisions 130 | ); 131 | //@ts-expect-error, the object will not be undefined 132 | expect(bt[0]).toBe("sh85144250"); 133 | }); 134 | -------------------------------------------------------------------------------- /tests/__snapshots__/loc.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Snapshot of JSON parsing logic Archaeology.json 1`] = ` 4 | [ 5 | { 6 | "aL": [ 7 | "Archeology", 8 | ], 9 | "bt": [ 10 | "sh85005581", 11 | "sh85010480", 12 | "sh85061212", 13 | ], 14 | "lcc": "CC", 15 | "note": "Here are entered works on archaeology as a branch of learning. This heading may be divided geographically for works on this branch of learning in a specific place. Works on the antiquities of particular regions, countries, cities, etc. are entered under the name of the place subdivided by [Antiquities.]", 16 | "nt": [ 17 | "sh00007440", 18 | "sh2003003476", 19 | "sh2003004186", 20 | "sh2003009064", 21 | "sh2003009199", 22 | "sh2003011000", 23 | "sh2004001262", 24 | "sh2005001576", 25 | "sh2006000287", 26 | "sh2007006623", 27 | "sh2009002956", 28 | "sh2009004421", 29 | "sh2009004470", 30 | "sh2012000959", 31 | "sh2012004635", 32 | "sh2012004636", 33 | "sh2013000143", 34 | "sh2013001302", 35 | "sh2013001303", 36 | "sh2015002234", 37 | "sh2021005077", 38 | "sh2021006222", 39 | "sh85001256", 40 | "sh85004685", 41 | "sh85006703", 42 | "sh85018080", 43 | "sh85027024", 44 | "sh85034228", 45 | "sh85046105", 46 | "sh85048843", 47 | "sh85050977", 48 | "sh85053066", 49 | "sh85060817", 50 | "sh85061115", 51 | "sh85065024", 52 | "sh85065824", 53 | "sh85066643", 54 | "sh85072567", 55 | "sh85079786", 56 | "sh85087721", 57 | "sh85093636", 58 | "sh85097895", 59 | "sh85101308", 60 | "sh85102008", 61 | "sh85107780", 62 | "sh85109300", 63 | "sh85114683", 64 | "sh85116926", 65 | "sh85126368", 66 | "sh85126691", 67 | "sh85127907", 68 | "sh85134099", 69 | "sh85139611", 70 | "sh85144346", 71 | "sh86001404", 72 | "sh87000460", 73 | "sh89000928", 74 | "sh89002313", 75 | "sh91002758", 76 | "sh93006952", 77 | "sh94001190", 78 | "sh94008300", 79 | "sh95000886", 80 | "sh95000887", 81 | ], 82 | "pL": "Archaeology", 83 | "rt": [ 84 | "sh85005757", 85 | ], 86 | "uri": "sh85006507", 87 | }, 88 | ] 89 | `; 90 | 91 | exports[`Snapshot of JSON parsing logic Archaeology.json 2`] = `[]`; 92 | 93 | exports[`Snapshot of JSON parsing logic Archaeology.json 3`] = ` 94 | { 95 | "sh85006507": "Archaeology", 96 | } 97 | `; 98 | 99 | exports[`Snapshot of JSON parsing logic History.json 1`] = ` 100 | [ 101 | { 102 | "aL": [ 103 | "Source material, Historical", 104 | "Primary sources (Historical sources)", 105 | "Historical sources", 106 | "Sources, Historical", 107 | "Historical source material", 108 | ], 109 | "lcc": "D5-D5.5", 110 | "note": "Here are entered collections of documents, records, etc. upon which narrative history is based.", 111 | "nt": [ 112 | "sh2003003039", 113 | "sh85006913", 114 | "sh85022719", 115 | "sh85038194", 116 | "sh85135408", 117 | ], 118 | "pL": "History--Sources", 119 | "uri": "sh85061227", 120 | }, 121 | ] 122 | `; 123 | 124 | exports[`Snapshot of JSON parsing logic History.json 2`] = `[]`; 125 | 126 | exports[`Snapshot of JSON parsing logic History.json 3`] = ` 127 | { 128 | "sh85061227": "History--Sources", 129 | } 130 | `; 131 | 132 | exports[`Snapshot of JSON parsing logic History-subdiv.json 1`] = `[]`; 133 | 134 | exports[`Snapshot of JSON parsing logic History-subdiv.json 2`] = ` 135 | [ 136 | { 137 | "aL": [ 138 | "Frontier troubles", 139 | ], 140 | "note": "Use as a topical subdivision under names of countries, cities, etc., and individual corporate bodies, uniform titles of sacred works, and under classes of persons, ethnic groups, and topical headings.", 141 | "nt": [ 142 | "sh00004047", 143 | "sh00005861", 144 | "sh00005863", 145 | "sh00005865", 146 | "sh00006030", 147 | "sh00006053", 148 | "sh00006054", 149 | "sh00006055", 150 | "sh2002012516", 151 | "sh2005000301", 152 | "sh2005003729", 153 | "sh2007008610", 154 | "sh2008009851", 155 | "sh2014001466", 156 | "sh2018001286", 157 | "sh85006507", 158 | "sh85006513", 159 | "sh85006887", 160 | "sh85007960", 161 | "sh85012434", 162 | "sh85014152", 163 | "sh85025619", 164 | "sh85031299", 165 | "sh85031326", 166 | "sh85033502", 167 | "sh85038179", 168 | "sh85038194", 169 | "sh85038418", 170 | "sh85050144", 171 | "sh85053742", 172 | "sh85061115", 173 | "sh85061208", 174 | "sh85064459", 175 | "sh85074517", 176 | "sh85077565", 177 | "sh85081954", 178 | "sh85085072", 179 | "sh85085207", 180 | "sh85088131", 181 | "sh85090384", 182 | "sh85100124", 183 | "sh85103033", 184 | "sh85107780", 185 | "sh85108672", 186 | "sh85113275", 187 | "sh85113507", 188 | "sh85114172", 189 | "sh85119320", 190 | "sh85120563", 191 | "sh85123948", 192 | "sh85124029", 193 | "sh85133488", 194 | "sh85148201", 195 | "sh88002668", 196 | "sh88004498", 197 | "sh89003666", 198 | "sh91002236", 199 | "sh98002432", 200 | "sh99004871", 201 | "sh99005023", 202 | "sh99005577", 203 | "sh99005617", 204 | "sh99005684", 205 | "sh99014676", 206 | ], 207 | "pL": "History", 208 | "uri": "sh99005024", 209 | }, 210 | ] 211 | `; 212 | 213 | exports[`Snapshot of JSON parsing logic History-subdiv.json 3`] = ` 214 | { 215 | "sh99005024": "History", 216 | } 217 | `; 218 | 219 | exports[`Snapshot of JSON parsing logic Obsidian.json 1`] = ` 220 | [ 221 | { 222 | "aL": [ 223 | "Hyalopsite", 224 | "Iceland agate", 225 | ], 226 | "bt": [ 227 | "sh85144250", 228 | ], 229 | "lcc": "QE462.O28", 230 | "pL": "Obsidian", 231 | "uri": "sh85093752", 232 | }, 233 | ] 234 | `; 235 | 236 | exports[`Snapshot of JSON parsing logic Obsidian.json 2`] = `[]`; 237 | 238 | exports[`Snapshot of JSON parsing logic Obsidian.json 3`] = ` 239 | { 240 | "sh85093752": "Obsidian", 241 | } 242 | `; 243 | -------------------------------------------------------------------------------- /tests/testFiles/Obsidian.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "http://v3/authorities/subjects/context.json", 3 | "@graph": [ 4 | { 5 | "@id": "http://id.loc.gov/authorities/subjects/sh85093752", 6 | "@type": [ 7 | "madsrdf:Authority", 8 | "madsrdf:Topic" 9 | ], 10 | "bflc:marcKey": "150 0$aObsidian", 11 | "identifiers:lccn": "sh 85093752", 12 | "madsrdf:adminMetadata": [ 13 | { 14 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb1" 15 | }, 16 | { 17 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb2" 18 | } 19 | ], 20 | "madsrdf:authoritativeLabel": { 21 | "@language": "en", 22 | "@value": "Obsidian" 23 | }, 24 | "madsrdf:classification": { 25 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb3" 26 | }, 27 | "madsrdf:elementList": { 28 | "@list": [ 29 | { 30 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb4" 31 | } 32 | ] 33 | }, 34 | "madsrdf:hasBroaderAuthority": { 35 | "@id": "http://id.loc.gov/authorities/subjects/sh85144250" 36 | }, 37 | "madsrdf:hasVariant": [ 38 | { 39 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb6" 40 | }, 41 | { 42 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb9" 43 | } 44 | ], 45 | "madsrdf:isMemberOfMADSCollection": [ 46 | { 47 | "@id": "http://id.loc.gov/authorities/subjects/collection_LCSHAuthorizedHeadings" 48 | }, 49 | { 50 | "@id": "http://id.loc.gov/authorities/subjects/collection_LCSH_General" 51 | }, 52 | { 53 | "@id": "http://id.loc.gov/authorities/subjects/collection_SubdivideGeographically" 54 | } 55 | ], 56 | "madsrdf:isMemberOfMADSScheme": { 57 | "@id": "http://id.loc.gov/authorities/subjects" 58 | }, 59 | "owl:sameAs": [ 60 | { 61 | "@id": "http://id.loc.gov/authorities/sh85093752#concept" 62 | }, 63 | { 64 | "@id": "info:lc/authorities/sh85093752" 65 | } 66 | ] 67 | }, 68 | { 69 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb1", 70 | "@type": "ri:RecordInfo", 71 | "ri:recordChangeDate": { 72 | "@type": "xsd:dateTime", 73 | "@value": "1988-06-10T10:57:14" 74 | }, 75 | "ri:recordContentSource": { 76 | "@id": "http://id.loc.gov/vocabulary/organizations/dlc" 77 | }, 78 | "ri:recordStatus": "revised" 79 | }, 80 | { 81 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb2", 82 | "@type": "ri:RecordInfo", 83 | "ri:recordChangeDate": { 84 | "@type": "xsd:dateTime", 85 | "@value": "1986-02-11T00:00:00" 86 | }, 87 | "ri:recordContentSource": { 88 | "@id": "http://id.loc.gov/vocabulary/organizations/dlc" 89 | }, 90 | "ri:recordStatus": "new" 91 | }, 92 | { 93 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb3", 94 | "@type": "lcc:ClassNumber", 95 | "madsrdf:code": "QE462.O28", 96 | "madsrdf:hasExactExternalAuthority": { 97 | "@id": "http://id.loc.gov/authorities/classification/QE462.O28" 98 | } 99 | }, 100 | { 101 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb4", 102 | "@type": "madsrdf:TopicElement", 103 | "madsrdf:elementValue": { 104 | "@language": "en", 105 | "@value": "Obsidian" 106 | } 107 | }, 108 | { 109 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb6", 110 | "@type": [ 111 | "madsrdf:Topic", 112 | "madsrdf:Variant" 113 | ], 114 | "madsrdf:elementList": { 115 | "@list": [ 116 | { 117 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb7" 118 | } 119 | ] 120 | }, 121 | "madsrdf:variantLabel": { 122 | "@language": "en", 123 | "@value": "Hyalopsite" 124 | } 125 | }, 126 | { 127 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb7", 128 | "@type": "madsrdf:TopicElement", 129 | "madsrdf:elementValue": { 130 | "@language": "en", 131 | "@value": "Hyalopsite" 132 | } 133 | }, 134 | { 135 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb9", 136 | "@type": [ 137 | "madsrdf:Topic", 138 | "madsrdf:Variant" 139 | ], 140 | "madsrdf:elementList": { 141 | "@list": [ 142 | { 143 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb10" 144 | } 145 | ] 146 | }, 147 | "madsrdf:variantLabel": { 148 | "@language": "en", 149 | "@value": "Iceland agate" 150 | } 151 | }, 152 | { 153 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb10", 154 | "@type": "madsrdf:TopicElement", 155 | "madsrdf:elementValue": { 156 | "@language": "en", 157 | "@value": "Iceland agate" 158 | } 159 | }, 160 | { 161 | "@id": "http://id.loc.gov/authorities/subjects/sh85144250", 162 | "@type": [ 163 | "madsrdf:Authority", 164 | "madsrdf:Topic" 165 | ], 166 | "madsrdf:authoritativeLabel": { 167 | "@language": "en", 168 | "@value": "Volcanic ash, tuff, etc." 169 | }, 170 | "madsrdf:elementList": { 171 | "@list": [ 172 | { 173 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb12" 174 | } 175 | ] 176 | } 177 | }, 178 | { 179 | "@id": "_:nca615ab5378e42b78fc41d4e8054a2bfb12", 180 | "@type": "madsrdf:TopicElement", 181 | "madsrdf:elementValue": { 182 | "@language": "en", 183 | "@value": "Volcanic ash, tuff, etc." 184 | } 185 | } 186 | ], 187 | "@id": "/authorities/subjects/sh85093752" 188 | } -------------------------------------------------------------------------------- /src/settings.ts: -------------------------------------------------------------------------------- 1 | import { App, Notice, PluginSettingTab, Setting } from "obsidian"; 2 | import type LinkedDataHelperPlugin from "./main"; 3 | 4 | export default class LiDaHeSettingsTab extends PluginSettingTab { 5 | plugin: LinkedDataHelperPlugin; 6 | 7 | constructor(app: App, plugin: LinkedDataHelperPlugin) { 8 | super(app, plugin); 9 | this.plugin = plugin; 10 | } 11 | 12 | display(): void { 13 | const { containerEl } = this; 14 | const { settings } = this.plugin; 15 | 16 | containerEl.empty(); 17 | 18 | containerEl.createEl("h2", { 19 | text: "Linked Data Helper Settings", 20 | }); 21 | 22 | containerEl.createEl("h3", { 23 | text: "Settings for Library of Congress Linked Data", 24 | }); 25 | 26 | containerEl.createEl("h4", { 27 | text: "LCSH Settings", 28 | }); 29 | 30 | const linkDiv = containerEl.createDiv(); 31 | 32 | linkDiv.appendChild( 33 | createFragment((frag) => { 34 | frag.appendText("Please download the "); 35 | frag.createEl("em", { 36 | text: "LC Subject Headings (LCSH) (MADS/RDF)", 37 | }); 38 | frag.appendText(" file (in "); 39 | frag.createEl("em", { 40 | text: "jsonld", 41 | }); 42 | frag.appendText(" format) from "); 43 | frag.createEl( 44 | "a", 45 | { 46 | text: "here", 47 | href: "https://id.loc.gov/download/", 48 | }, 49 | (a) => { 50 | a.setAttr("target", "_blank"); 51 | } 52 | ); 53 | frag.appendText( 54 | " and unzip it. (The file name may be a bit different, since the file also gets updated from time to time.) \ 55 | The unzipped file will be ~1.9GB, therefore it is a good idea to save and unzip it outside of the vault." 56 | ); 57 | }) 58 | ); 59 | 60 | containerEl.createEl("br"); 61 | 62 | new Setting(containerEl) 63 | .setName("Path of the extracted gzip (.gz) file") 64 | .setDesc("Please input the absolute path to the extracted file.") 65 | .addText((text) => 66 | text 67 | .setPlaceholder( 68 | "/home/user/Downloads/subjects.madsrdf.jsonld" 69 | ) 70 | .setValue(this.plugin.settings.lcshInputPath) 71 | .onChange(async (value) => { 72 | this.plugin.settings.lcshInputPath = value.trim(); 73 | await this.plugin.saveSettings(); 74 | }) 75 | ); 76 | 77 | new Setting(containerEl) 78 | .setName( 79 | "Folder where the three generated JSON files should be saved" 80 | ) 81 | .setDesc( 82 | createFragment((frag) => { 83 | frag.appendText( 84 | "Leave empty to save the files automatically in the subfolder 'linked-data-vocabularies' in your attachments folder." 85 | ); 86 | frag.createEl("br"); 87 | frag.createEl("b", { text: "Note: " }); 88 | frag.appendText( 89 | "This will only work when your attachment folder is your vault (default) or when it is a specific folder." 90 | ); 91 | frag.createEl("br"); 92 | frag.appendText( 93 | "The path must start from your vault root." 94 | ); 95 | //frag.appendChild(bolded) 96 | //const not = createEl('em', {text: 'not'}) 97 | //bolded.appendChild(not) 98 | //bolded.appendText(' work if you have selected ') 99 | //bolded.appendChild(createEl('em', {text: '"Same folder as current file."'})) 100 | frag.createEl("br"); 101 | 102 | try { 103 | if ( 104 | this.app.vault.config.attachmentFolderPath.startsWith( 105 | "./" 106 | ) 107 | ) { 108 | frag.createEl("b", { 109 | text: "In your case, you need to specify in which folder the files shall be saved.", 110 | }); 111 | } else { 112 | frag.appendText( 113 | "In your case, you don't need to input a path." 114 | ); 115 | } 116 | } catch { 117 | // catch error 118 | new Notice( 119 | "Please check your attachments setting under Files & Links." 120 | ); 121 | } 122 | }) 123 | ) 124 | .addText((text) => 125 | text 126 | .setPlaceholder("") 127 | .setValue(this.plugin.settings.lcshOutputPath) 128 | .onChange(async (value) => { 129 | this.plugin.settings.lcshOutputPath = value.trim(); //normalizePath( 130 | //); 131 | await this.plugin.saveSettings(); 132 | }) 133 | ); 134 | 135 | new Setting(containerEl) 136 | .setName("Perform the conversion") 137 | .setDesc( 138 | "When clicked, it will generate the three JSON files that the \ 139 | Linked Data Vocabularies plugin needs to work with LCSH." 140 | ) 141 | .addButton((button) => { 142 | button 143 | .setCta() 144 | .setTooltip("Click to start the conversion.") 145 | .setButtonText("Start conversion") 146 | .onClick(() => { 147 | if (this.plugin.settings.lcshInputPath !== "") { 148 | new Notice( 149 | "The conversion will start now. This may take some time. You will be notified when it is done." 150 | ); 151 | if (this.plugin.settings.lcshOutputPath !== "") { 152 | this.plugin.methods_loc.convertMadsRdfJsonld( 153 | this.plugin.settings.lcshOutputPath 154 | ); 155 | } else { 156 | this.plugin.methods_loc.convertMadsRdfJsonld(); 157 | } 158 | } 159 | }); 160 | }); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/methods/parseJson.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | Graph, 3 | headings, 4 | LcshInterface, 5 | SkolemGraphNode, 6 | uriToHeading, 7 | } from "../interfaces"; 8 | 9 | import { 10 | BROADER, 11 | HAS_VARIANT, 12 | NARROWER, 13 | PREF_LABEL, 14 | RELATED, 15 | VARIANT_LABEL, 16 | } from "../constants"; 17 | 18 | export function parseJsonHeading( 19 | obj: LcshInterface, 20 | jsonPrefLabel: headings[], 21 | subdivisions: headings[], 22 | jsonUriToPrefLabel: uriToHeading 23 | ) { 24 | //@ts-expect-error, it needs to be initialised 25 | // and will be populated later on 26 | let currentObj: headings = {}; 27 | const id = "http://id.loc.gov" + obj["@id"]; 28 | for (const element of obj["@graph"]) { 29 | let broaderURLs: string[] = []; 30 | let narrowerURLs: string[] = []; 31 | let relatedURLs: string[] = []; 32 | let prefLabel = ""; 33 | let altLabels: string[] = []; 34 | let lcc = ""; 35 | 36 | let uri = ""; 37 | if (element["madsrdf:authoritativeLabel"]?.["@language"] === "en") { 38 | uri = element["@id"]; 39 | if (uri === id) { 40 | prefLabel = element["madsrdf:authoritativeLabel"]["@value"]; 41 | } else { 42 | continue; 43 | } 44 | } else { 45 | continue; 46 | } 47 | if (element["madsrdf:classification"]) { 48 | const skolemIri: string = element["madsrdf:classification"]["@id"]; 49 | for (const againElement of obj["@graph"]) { 50 | if (againElement["@id"] === skolemIri) { 51 | const skolemNode = againElement as SkolemGraphNode; 52 | lcc = skolemNode["madsrdf:code"]; 53 | break; 54 | } 55 | } 56 | } 57 | const endUri = splitUri(uri); 58 | Object.assign(jsonUriToPrefLabel, { 59 | [endUri]: prefLabel, 60 | }); 61 | const graph = obj["@graph"]; 62 | // there can be multiple altLabels 63 | altLabels = makeArrayAndResolveSkolemIris(element, graph, HAS_VARIANT); 64 | broaderURLs = makeArrayAndResolveSkolemIris(element, graph, BROADER); 65 | // prettier-ignore 66 | narrowerURLs = makeArrayAndResolveSkolemIris(element, graph, NARROWER); 67 | relatedURLs = makeArrayAndResolveSkolemIris(element, graph, RELATED); 68 | currentObj = onlyReturnFull( 69 | prefLabel, 70 | altLabels, 71 | uri, 72 | broaderURLs, 73 | narrowerURLs, 74 | relatedURLs, 75 | lcc 76 | ); 77 | if (element["madsrdf:note"]) { 78 | let note = element["madsrdf:note"]; 79 | if (Array.isArray(note)) { 80 | let newNote = ""; 81 | for (const el of note) { 82 | newNote += el; 83 | } 84 | note = newNote; 85 | } 86 | currentObj.note = note; 87 | if (note.includes("Use as a")) { 88 | subdivisions.push(currentObj); 89 | } else { 90 | jsonPrefLabel.push(currentObj); 91 | } 92 | //} else if (element['skos:editorial']) { 93 | // let editorial = element['skos:editorial']; 94 | // if (Array.isArray(editorial)) { 95 | // let neweditorial = ''; 96 | // for (let el of editorial) { 97 | // neweditorial += el; 98 | // } 99 | // editorial = neweditorial; 100 | // } 101 | // currentObj.note = editorial; 102 | // if (editorial.startsWith('subdivision')) { 103 | // subdivisions.push(currentObj) 104 | // } else { 105 | // jsonPrefLabel.push(currentObj) 106 | // } 107 | } else { 108 | jsonPrefLabel.push(currentObj); 109 | } 110 | break; 111 | } 112 | } 113 | 114 | function splitUri(url: string): string { 115 | const splitUrl = url.split("/"); 116 | return splitUrl[splitUrl.length - 1]; 117 | } 118 | 119 | function reduceUrls( 120 | broaderURLs: string[], 121 | narrowerURLs: string[], 122 | relatedURLs: string[] 123 | ) { 124 | const reducedBroaderURLs: string[] = []; 125 | const reducedNarrowerURLs: string[] = []; 126 | const reducedRelatedURLs: string[] = []; 127 | const intermediateObj = { 128 | broader: [reducedBroaderURLs, broaderURLs], 129 | narrower: [reducedNarrowerURLs, narrowerURLs], 130 | related: [reducedRelatedURLs, relatedURLs], 131 | }; 132 | 133 | // populate the reduced URL arrays with the end of the URLs 134 | for (const value of Object.values(intermediateObj)) { 135 | for (const url of value[1]) { 136 | // normal URI 137 | if (url && url.includes("/")) { 138 | const endUri = splitUri(url); 139 | value[0].push(endUri); 140 | } else { 141 | // heading name because of Skolem IRI 142 | value[0].push(url); 143 | } 144 | } 145 | } 146 | return { reducedBroaderURLs, reducedNarrowerURLs, reducedRelatedURLs }; 147 | } 148 | 149 | /** 150 | * Returns only the properties that are present 151 | * and only uses the ID instead of the full URI for the uri property 152 | */ 153 | function onlyReturnFull( 154 | prefLabel: string, 155 | altLabel: string[], 156 | uri: string, 157 | broaderURLs: string[], 158 | narrowerURLs: string[], 159 | relatedURLs: string[], 160 | lcc: string 161 | ): headings { 162 | //@ts-expect-error, The object needs to be initialised, 163 | // it is populated later on and is what will be returned by the function 164 | const currentObj: headings = {}; 165 | const { reducedBroaderURLs, reducedNarrowerURLs, reducedRelatedURLs } = 166 | reduceUrls(broaderURLs, narrowerURLs, relatedURLs); 167 | 168 | currentObj.pL = prefLabel; 169 | currentObj.uri = splitUri(uri); 170 | if (altLabel.length > 0) { 171 | currentObj.aL = altLabel; 172 | } 173 | if (broaderURLs.length > 0) { 174 | currentObj.bt = reducedBroaderURLs; 175 | } 176 | if (narrowerURLs.length > 0) { 177 | currentObj.nt = reducedNarrowerURLs; 178 | } 179 | if (relatedURLs.length > 0) { 180 | currentObj.rt = reducedRelatedURLs; 181 | } 182 | if (lcc !== "") { 183 | currentObj.lcc = lcc; 184 | } 185 | 186 | return currentObj; 187 | } 188 | 189 | /** 190 | * Gets the URIs (or name, in case of Skolem IRIs) of the relation headings. 191 | * @param element - The current node 192 | * @param graph - The full graph with all the nodes 193 | * @param type - The current relation type 194 | * @returns The full (unreduced) URIs of the relation headings 195 | * 196 | * @remarks - It turns individual headings into an Array and resolves Skolem IRIs. 197 | * 198 | */ 199 | function makeArrayAndResolveSkolemIris( 200 | element: Graph, 201 | graph: Graph[], 202 | type: typeof NARROWER | typeof RELATED | typeof BROADER | typeof HAS_VARIANT 203 | ): string[] { 204 | const urls = []; 205 | const relation = element[type]; 206 | if (relation !== undefined) { 207 | let variant: typeof PREF_LABEL | typeof VARIANT_LABEL = PREF_LABEL; 208 | if (type === HAS_VARIANT) { 209 | variant = VARIANT_LABEL; 210 | } 211 | if (Array.isArray(relation)) { 212 | for (const subElement of relation) { 213 | const id = subElement["@id"]; 214 | if (id.startsWith("_:")) { 215 | const term = getHeadingForSkolemIri(graph, id, variant); 216 | urls.push(term); 217 | } else { 218 | urls.push(id); 219 | } 220 | } 221 | } else { 222 | const id: string = relation["@id"]; 223 | if (id.startsWith("_:")) { 224 | const term = getHeadingForSkolemIri(graph, id, variant); 225 | urls.push(term); 226 | } else { 227 | urls.push(id); 228 | } 229 | } 230 | } 231 | 232 | return urls; 233 | } 234 | 235 | /** 236 | * Resolves the heading to the given Skolem IRI 237 | * @param graph - All nodes of the graph 238 | * @param id - The Skolem IRI that maps to an ID on a node on {@param graph} 239 | * @param type 240 | * @returns - It always returns a non-empty string, because this function is only called if there is a matching result 241 | */ 242 | function getHeadingForSkolemIri( 243 | graph: Graph[], 244 | id: string, 245 | type: typeof PREF_LABEL | typeof VARIANT_LABEL 246 | ): string { 247 | let term = ""; 248 | for (const part of graph) { 249 | if (part["@id"] === id) { 250 | const label = part[type]; 251 | if (label["@language"] === "en") { 252 | term = label["@value"]; 253 | break; 254 | } 255 | } 256 | } 257 | return term; 258 | } 259 | -------------------------------------------------------------------------------- /tests/testFiles/History.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "http://v3/authorities/subjects/context.json", 3 | "@graph": [ 4 | { 5 | "@id": "http://id.loc.gov/authorities/subjects/sh85061212", 6 | "@type": [ 7 | "madsrdf:Authority", 8 | "madsrdf:Topic" 9 | ], 10 | "madsrdf:authoritativeLabel": { 11 | "@language": "en", 12 | "@value": "History" 13 | }, 14 | "madsrdf:elementList": { 15 | "@list": [ 16 | { 17 | "@id": "_:n216494b50fa441c2af01af8233390b64b25" 18 | } 19 | ] 20 | } 21 | }, 22 | { 23 | "@id": "_:n216494b50fa441c2af01af8233390b64b25", 24 | "@type": "madsrdf:TopicElement", 25 | "madsrdf:elementValue": { 26 | "@language": "en", 27 | "@value": "History" 28 | } 29 | }, 30 | { 31 | "@id": "http://id.loc.gov/authorities/subjects/sh85061227", 32 | "@type": [ 33 | "madsrdf:Authority", 34 | "madsrdf:ComplexSubject" 35 | ], 36 | "bflc:marcKey": "150 $aHistory$vSources", 37 | "identifiers:lccn": "sh 85061227", 38 | "madsrdf:adminMetadata": [ 39 | { 40 | "@id": "_:n216494b50fa441c2af01af8233390b64b1" 41 | }, 42 | { 43 | "@id": "_:n216494b50fa441c2af01af8233390b64b2" 44 | } 45 | ], 46 | "madsrdf:authoritativeLabel": { 47 | "@language": "en", 48 | "@value": "History--Sources" 49 | }, 50 | "madsrdf:classification": { 51 | "@id": "_:n216494b50fa441c2af01af8233390b64b3" 52 | }, 53 | "madsrdf:componentList": { 54 | "@list": [ 55 | { 56 | "@id": "http://id.loc.gov/authorities/subjects/sh85061212" 57 | }, 58 | { 59 | "@id": "http://id.loc.gov/authorities/subjects/sh2002012007" 60 | } 61 | ] 62 | }, 63 | "madsrdf:editorialNote": "subdivision [History--Sources] under names of countries, cities, etc., and individual corporate bodies, and under classes of persons, ethnic groups, and topical headings that are not inherently historical; and subdivision [Sources] under historical topics, e.g. [Renaissance--Sources]", 64 | "madsrdf:hasNarrowerAuthority": [ 65 | { 66 | "@id": "http://id.loc.gov/authorities/subjects/sh2003003039" 67 | }, 68 | { 69 | "@id": "http://id.loc.gov/authorities/subjects/sh85006913" 70 | }, 71 | { 72 | "@id": "http://id.loc.gov/authorities/subjects/sh85022719" 73 | }, 74 | { 75 | "@id": "http://id.loc.gov/authorities/subjects/sh85038194" 76 | }, 77 | { 78 | "@id": "http://id.loc.gov/authorities/subjects/sh85135408" 79 | } 80 | ], 81 | "madsrdf:hasSource": [ 82 | { 83 | "@id": "_:n216494b50fa441c2af01af8233390b64b6" 84 | }, 85 | { 86 | "@id": "_:n216494b50fa441c2af01af8233390b64b7" 87 | } 88 | ], 89 | "madsrdf:hasVariant": [ 90 | { 91 | "@id": "_:n216494b50fa441c2af01af8233390b64b8" 92 | }, 93 | { 94 | "@id": "_:n216494b50fa441c2af01af8233390b64b11" 95 | }, 96 | { 97 | "@id": "_:n216494b50fa441c2af01af8233390b64b14" 98 | }, 99 | { 100 | "@id": "_:n216494b50fa441c2af01af8233390b64b17" 101 | }, 102 | { 103 | "@id": "_:n216494b50fa441c2af01af8233390b64b20" 104 | } 105 | ], 106 | "madsrdf:isMemberOfMADSCollection": [ 107 | { 108 | "@id": "http://id.loc.gov/authorities/subjects/collection_LCSHAuthorizedHeadings" 109 | }, 110 | { 111 | "@id": "http://id.loc.gov/authorities/subjects/collection_LCSH_General" 112 | } 113 | ], 114 | "madsrdf:isMemberOfMADSScheme": { 115 | "@id": "http://id.loc.gov/authorities/subjects" 116 | }, 117 | "madsrdf:note": "Here are entered collections of documents, records, etc. upon which narrative history is based.", 118 | "owl:sameAs": [ 119 | { 120 | "@id": "http://id.loc.gov/authorities/sh85061227#concept" 121 | }, 122 | { 123 | "@id": "info:lc/authorities/sh85061227" 124 | } 125 | ] 126 | }, 127 | { 128 | "@id": "_:n216494b50fa441c2af01af8233390b64b1", 129 | "@type": "ri:RecordInfo", 130 | "ri:recordChangeDate": { 131 | "@type": "xsd:dateTime", 132 | "@value": "2005-07-29T12:53:29" 133 | }, 134 | "ri:recordContentSource": { 135 | "@id": "http://id.loc.gov/vocabulary/organizations/dlc" 136 | }, 137 | "ri:recordStatus": "revised" 138 | }, 139 | { 140 | "@id": "_:n216494b50fa441c2af01af8233390b64b2", 141 | "@type": "ri:RecordInfo", 142 | "ri:recordChangeDate": { 143 | "@type": "xsd:dateTime", 144 | "@value": "2005-07-15T00:00:00" 145 | }, 146 | "ri:recordContentSource": { 147 | "@id": "http://id.loc.gov/vocabulary/organizations/dlc" 148 | }, 149 | "ri:recordStatus": "new" 150 | }, 151 | { 152 | "@id": "_:n216494b50fa441c2af01af8233390b64b3", 153 | "@type": "lcc:ClassNumber", 154 | "madsrdf:code": "D5-D5.5", 155 | "madsrdf:hasExactExternalAuthority": { 156 | "@id": "http://id.loc.gov/authorities/classification/D5-D5.5" 157 | } 158 | }, 159 | { 160 | "@id": "_:n216494b50fa441c2af01af8233390b64b6", 161 | "@type": "madsrdf:Source", 162 | "madsrdf:citationNote": { 163 | "@language": "en", 164 | "@value": "(titles: primary sources)" 165 | }, 166 | "madsrdf:citationSource": "LC database, July 15, 2005", 167 | "madsrdf:citationStatus": "found" 168 | }, 169 | { 170 | "@id": "_:n216494b50fa441c2af01af8233390b64b7", 171 | "@type": "madsrdf:Source", 172 | "madsrdf:citationNote": { 173 | "@language": "en", 174 | "@value": "(primary source: original works in various media formats such as photographs, drawings, letters, diaries, documents, books, films, posters, play scripts, speeches, songs, sheet music, and first-person accounts that are recorded at the time of an event.)" 175 | }, 176 | "madsrdf:citationSource": "LC Learning page glossary, July 15, 2005", 177 | "madsrdf:citationStatus": "found" 178 | }, 179 | { 180 | "@id": "_:n216494b50fa441c2af01af8233390b64b8", 181 | "@type": [ 182 | "madsrdf:Topic", 183 | "madsrdf:Variant" 184 | ], 185 | "madsrdf:elementList": { 186 | "@list": [ 187 | { 188 | "@id": "_:n216494b50fa441c2af01af8233390b64b9" 189 | } 190 | ] 191 | }, 192 | "madsrdf:variantLabel": { 193 | "@language": "en", 194 | "@value": "Source material, Historical" 195 | } 196 | }, 197 | { 198 | "@id": "_:n216494b50fa441c2af01af8233390b64b9", 199 | "@type": "madsrdf:TopicElement", 200 | "madsrdf:elementValue": { 201 | "@language": "en", 202 | "@value": "Source material, Historical" 203 | } 204 | }, 205 | { 206 | "@id": "_:n216494b50fa441c2af01af8233390b64b11", 207 | "@type": [ 208 | "madsrdf:Topic", 209 | "madsrdf:Variant" 210 | ], 211 | "madsrdf:elementList": { 212 | "@list": [ 213 | { 214 | "@id": "_:n216494b50fa441c2af01af8233390b64b12" 215 | } 216 | ] 217 | }, 218 | "madsrdf:variantLabel": { 219 | "@language": "en", 220 | "@value": "Primary sources (Historical sources)" 221 | } 222 | }, 223 | { 224 | "@id": "_:n216494b50fa441c2af01af8233390b64b12", 225 | "@type": "madsrdf:TopicElement", 226 | "madsrdf:elementValue": { 227 | "@language": "en", 228 | "@value": "Primary sources (Historical sources)" 229 | } 230 | }, 231 | { 232 | "@id": "_:n216494b50fa441c2af01af8233390b64b14", 233 | "@type": [ 234 | "madsrdf:Topic", 235 | "madsrdf:Variant" 236 | ], 237 | "madsrdf:elementList": { 238 | "@list": [ 239 | { 240 | "@id": "_:n216494b50fa441c2af01af8233390b64b15" 241 | } 242 | ] 243 | }, 244 | "madsrdf:variantLabel": { 245 | "@language": "en", 246 | "@value": "Historical sources" 247 | } 248 | }, 249 | { 250 | "@id": "_:n216494b50fa441c2af01af8233390b64b15", 251 | "@type": "madsrdf:TopicElement", 252 | "madsrdf:elementValue": { 253 | "@language": "en", 254 | "@value": "Historical sources" 255 | } 256 | }, 257 | { 258 | "@id": "_:n216494b50fa441c2af01af8233390b64b17", 259 | "@type": [ 260 | "madsrdf:Topic", 261 | "madsrdf:Variant" 262 | ], 263 | "madsrdf:elementList": { 264 | "@list": [ 265 | { 266 | "@id": "_:n216494b50fa441c2af01af8233390b64b18" 267 | } 268 | ] 269 | }, 270 | "madsrdf:variantLabel": { 271 | "@language": "en", 272 | "@value": "Sources, Historical" 273 | } 274 | }, 275 | { 276 | "@id": "_:n216494b50fa441c2af01af8233390b64b18", 277 | "@type": "madsrdf:TopicElement", 278 | "madsrdf:elementValue": { 279 | "@language": "en", 280 | "@value": "Sources, Historical" 281 | } 282 | }, 283 | { 284 | "@id": "_:n216494b50fa441c2af01af8233390b64b20", 285 | "@type": [ 286 | "madsrdf:Topic", 287 | "madsrdf:Variant" 288 | ], 289 | "madsrdf:elementList": { 290 | "@list": [ 291 | { 292 | "@id": "_:n216494b50fa441c2af01af8233390b64b21" 293 | } 294 | ] 295 | }, 296 | "madsrdf:variantLabel": { 297 | "@language": "en", 298 | "@value": "Historical source material" 299 | } 300 | }, 301 | { 302 | "@id": "_:n216494b50fa441c2af01af8233390b64b21", 303 | "@type": "madsrdf:TopicElement", 304 | "madsrdf:elementValue": { 305 | "@language": "en", 306 | "@value": "Historical source material" 307 | } 308 | }, 309 | { 310 | "@id": "http://id.loc.gov/authorities/subjects/sh2002012007", 311 | "@type": [ 312 | "madsrdf:Authority", 313 | "madsrdf:GenreForm" 314 | ], 315 | "madsrdf:authoritativeLabel": { 316 | "@language": "en", 317 | "@value": "Sources" 318 | }, 319 | "madsrdf:elementList": { 320 | "@list": [ 321 | { 322 | "@id": "_:n216494b50fa441c2af01af8233390b64b23" 323 | } 324 | ] 325 | } 326 | }, 327 | { 328 | "@id": "_:n216494b50fa441c2af01af8233390b64b23", 329 | "@type": "madsrdf:GenreFormElement", 330 | "madsrdf:elementValue": { 331 | "@language": "en", 332 | "@value": "Sources" 333 | } 334 | } 335 | ], 336 | "@id": "/authorities/subjects/sh85061227" 337 | } -------------------------------------------------------------------------------- /tests/testFiles/History-subdiv.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "http://v3/authorities/subjects/context.json", 3 | "@graph": [ 4 | { 5 | "@id": "http://id.loc.gov/authorities/subjects/sh99005024", 6 | "@type": [ 7 | "madsrdf:Authority", 8 | "madsrdf:Topic" 9 | ], 10 | "bflc:marcKey": "180 $xHistory", 11 | "identifiers:lccn": "sh 99005024", 12 | "madsrdf:adminMetadata": [ 13 | { 14 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb1" 15 | }, 16 | { 17 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb2" 18 | } 19 | ], 20 | "madsrdf:authoritativeLabel": { 21 | "@language": "en", 22 | "@value": "History" 23 | }, 24 | "madsrdf:elementList": { 25 | "@list": [ 26 | { 27 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb3" 28 | } 29 | ] 30 | }, 31 | "madsrdf:exampleNote": "Reference under the heading [History]", 32 | "madsrdf:hasEarlierEstablishedForm": { 33 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb5" 34 | }, 35 | "madsrdf:hasNarrowerAuthority": [ 36 | { 37 | "@id": "http://id.loc.gov/authorities/subjects/sh00004047" 38 | }, 39 | { 40 | "@id": "http://id.loc.gov/authorities/subjects/sh00005861" 41 | }, 42 | { 43 | "@id": "http://id.loc.gov/authorities/subjects/sh00005863" 44 | }, 45 | { 46 | "@id": "http://id.loc.gov/authorities/subjects/sh00005865" 47 | }, 48 | { 49 | "@id": "http://id.loc.gov/authorities/subjects/sh00006030" 50 | }, 51 | { 52 | "@id": "http://id.loc.gov/authorities/subjects/sh00006053" 53 | }, 54 | { 55 | "@id": "http://id.loc.gov/authorities/subjects/sh00006054" 56 | }, 57 | { 58 | "@id": "http://id.loc.gov/authorities/subjects/sh00006055" 59 | }, 60 | { 61 | "@id": "http://id.loc.gov/authorities/subjects/sh2002012516" 62 | }, 63 | { 64 | "@id": "http://id.loc.gov/authorities/subjects/sh2005000301" 65 | }, 66 | { 67 | "@id": "http://id.loc.gov/authorities/subjects/sh2005003729" 68 | }, 69 | { 70 | "@id": "http://id.loc.gov/authorities/subjects/sh2007008610" 71 | }, 72 | { 73 | "@id": "http://id.loc.gov/authorities/subjects/sh2008009851" 74 | }, 75 | { 76 | "@id": "http://id.loc.gov/authorities/subjects/sh2014001466" 77 | }, 78 | { 79 | "@id": "http://id.loc.gov/authorities/subjects/sh2018001286" 80 | }, 81 | { 82 | "@id": "http://id.loc.gov/authorities/subjects/sh85006507" 83 | }, 84 | { 85 | "@id": "http://id.loc.gov/authorities/subjects/sh85006513" 86 | }, 87 | { 88 | "@id": "http://id.loc.gov/authorities/subjects/sh85006887" 89 | }, 90 | { 91 | "@id": "http://id.loc.gov/authorities/subjects/sh85007960" 92 | }, 93 | { 94 | "@id": "http://id.loc.gov/authorities/subjects/sh85012434" 95 | }, 96 | { 97 | "@id": "http://id.loc.gov/authorities/subjects/sh85014152" 98 | }, 99 | { 100 | "@id": "http://id.loc.gov/authorities/subjects/sh85025619" 101 | }, 102 | { 103 | "@id": "http://id.loc.gov/authorities/subjects/sh85031299" 104 | }, 105 | { 106 | "@id": "http://id.loc.gov/authorities/subjects/sh85031326" 107 | }, 108 | { 109 | "@id": "http://id.loc.gov/authorities/subjects/sh85033502" 110 | }, 111 | { 112 | "@id": "http://id.loc.gov/authorities/subjects/sh85038179" 113 | }, 114 | { 115 | "@id": "http://id.loc.gov/authorities/subjects/sh85038194" 116 | }, 117 | { 118 | "@id": "http://id.loc.gov/authorities/subjects/sh85038418" 119 | }, 120 | { 121 | "@id": "http://id.loc.gov/authorities/subjects/sh85050144" 122 | }, 123 | { 124 | "@id": "http://id.loc.gov/authorities/subjects/sh85053742" 125 | }, 126 | { 127 | "@id": "http://id.loc.gov/authorities/subjects/sh85061115" 128 | }, 129 | { 130 | "@id": "http://id.loc.gov/authorities/subjects/sh85061208" 131 | }, 132 | { 133 | "@id": "http://id.loc.gov/authorities/subjects/sh85064459" 134 | }, 135 | { 136 | "@id": "http://id.loc.gov/authorities/subjects/sh85074517" 137 | }, 138 | { 139 | "@id": "http://id.loc.gov/authorities/subjects/sh85077565" 140 | }, 141 | { 142 | "@id": "http://id.loc.gov/authorities/subjects/sh85081954" 143 | }, 144 | { 145 | "@id": "http://id.loc.gov/authorities/subjects/sh85085072" 146 | }, 147 | { 148 | "@id": "http://id.loc.gov/authorities/subjects/sh85085207" 149 | }, 150 | { 151 | "@id": "http://id.loc.gov/authorities/subjects/sh85088131" 152 | }, 153 | { 154 | "@id": "http://id.loc.gov/authorities/subjects/sh85090384" 155 | }, 156 | { 157 | "@id": "http://id.loc.gov/authorities/subjects/sh85100124" 158 | }, 159 | { 160 | "@id": "http://id.loc.gov/authorities/subjects/sh85103033" 161 | }, 162 | { 163 | "@id": "http://id.loc.gov/authorities/subjects/sh85107780" 164 | }, 165 | { 166 | "@id": "http://id.loc.gov/authorities/subjects/sh85108672" 167 | }, 168 | { 169 | "@id": "http://id.loc.gov/authorities/subjects/sh85113275" 170 | }, 171 | { 172 | "@id": "http://id.loc.gov/authorities/subjects/sh85113507" 173 | }, 174 | { 175 | "@id": "http://id.loc.gov/authorities/subjects/sh85114172" 176 | }, 177 | { 178 | "@id": "http://id.loc.gov/authorities/subjects/sh85119320" 179 | }, 180 | { 181 | "@id": "http://id.loc.gov/authorities/subjects/sh85120563" 182 | }, 183 | { 184 | "@id": "http://id.loc.gov/authorities/subjects/sh85123948" 185 | }, 186 | { 187 | "@id": "http://id.loc.gov/authorities/subjects/sh85124029" 188 | }, 189 | { 190 | "@id": "http://id.loc.gov/authorities/subjects/sh85133488" 191 | }, 192 | { 193 | "@id": "http://id.loc.gov/authorities/subjects/sh85148201" 194 | }, 195 | { 196 | "@id": "http://id.loc.gov/authorities/subjects/sh88002668" 197 | }, 198 | { 199 | "@id": "http://id.loc.gov/authorities/subjects/sh88004498" 200 | }, 201 | { 202 | "@id": "http://id.loc.gov/authorities/subjects/sh89003666" 203 | }, 204 | { 205 | "@id": "http://id.loc.gov/authorities/subjects/sh91002236" 206 | }, 207 | { 208 | "@id": "http://id.loc.gov/authorities/subjects/sh98002432" 209 | }, 210 | { 211 | "@id": "http://id.loc.gov/authorities/subjects/sh99004871" 212 | }, 213 | { 214 | "@id": "http://id.loc.gov/authorities/subjects/sh99005023" 215 | }, 216 | { 217 | "@id": "http://id.loc.gov/authorities/subjects/sh99005577" 218 | }, 219 | { 220 | "@id": "http://id.loc.gov/authorities/subjects/sh99005617" 221 | }, 222 | { 223 | "@id": "http://id.loc.gov/authorities/subjects/sh99005684" 224 | }, 225 | { 226 | "@id": "http://id.loc.gov/authorities/subjects/sh99014676" 227 | } 228 | ], 229 | "madsrdf:hasVariant": { 230 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb8" 231 | }, 232 | "madsrdf:isMemberOfMADSCollection": [ 233 | { 234 | "@id": "http://id.loc.gov/authorities/subjects/collection_LCSH_General" 235 | }, 236 | { 237 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1095" 238 | }, 239 | { 240 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1100" 241 | }, 242 | { 243 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1103" 244 | }, 245 | { 246 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1105" 247 | }, 248 | { 249 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1140" 250 | }, 251 | { 252 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1149.5" 253 | }, 254 | { 255 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1154" 256 | }, 257 | { 258 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1159" 259 | }, 260 | { 261 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1187" 262 | }, 263 | { 264 | "@id": "http://id.loc.gov/authorities/subjects/collection_PatternHeadingH1188" 265 | }, 266 | { 267 | "@id": "http://id.loc.gov/authorities/subjects/collection_Subdivisions" 268 | }, 269 | { 270 | "@id": "http://id.loc.gov/authorities/subjects/collection_TopicSubdivisions" 271 | } 272 | ], 273 | "madsrdf:isMemberOfMADSScheme": { 274 | "@id": "http://id.loc.gov/authorities/subjects" 275 | }, 276 | "madsrdf:note": "Use as a topical subdivision under names of countries, cities, etc., and individual corporate bodies, uniform titles of sacred works, and under classes of persons, ethnic groups, and topical headings.", 277 | "owl:sameAs": [ 278 | { 279 | "@id": "http://id.loc.gov/authorities/sh99005024#concept" 280 | }, 281 | { 282 | "@id": "info:lc/authorities/sh99005024" 283 | } 284 | ] 285 | }, 286 | { 287 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb1", 288 | "@type": "ri:RecordInfo", 289 | "ri:languageOfCataloging": { 290 | "@id": "http://id.loc.gov/vocabulary/iso639-2/eng" 291 | }, 292 | "ri:recordChangeDate": { 293 | "@type": "xsd:dateTime", 294 | "@value": "2006-05-09T15:15:27" 295 | }, 296 | "ri:recordContentSource": { 297 | "@id": "http://id.loc.gov/vocabulary/organizations/dlc" 298 | }, 299 | "ri:recordStatus": "revised" 300 | }, 301 | { 302 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb2", 303 | "@type": "ri:RecordInfo", 304 | "ri:languageOfCataloging": { 305 | "@id": "http://id.loc.gov/vocabulary/iso639-2/eng" 306 | }, 307 | "ri:recordChangeDate": { 308 | "@type": "xsd:dateTime", 309 | "@value": "1999-07-07T00:00:00" 310 | }, 311 | "ri:recordContentSource": { 312 | "@id": "http://id.loc.gov/vocabulary/organizations/ien" 313 | }, 314 | "ri:recordStatus": "new" 315 | }, 316 | { 317 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb3", 318 | "@type": "madsrdf:TopicElement", 319 | "madsrdf:elementValue": { 320 | "@language": "en", 321 | "@value": "History" 322 | } 323 | }, 324 | { 325 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb5", 326 | "@type": [ 327 | "madsrdf:Topic", 328 | "madsrdf:Variant" 329 | ], 330 | "madsrdf:elementList": { 331 | "@list": [ 332 | { 333 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb6" 334 | } 335 | ] 336 | }, 337 | "madsrdf:variantLabel": { 338 | "@language": "en", 339 | "@value": "Frontier troubles" 340 | } 341 | }, 342 | { 343 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb6", 344 | "@type": "madsrdf:TopicElement", 345 | "madsrdf:elementValue": { 346 | "@language": "en", 347 | "@value": "Frontier troubles" 348 | } 349 | }, 350 | { 351 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb8", 352 | "@type": [ 353 | "madsrdf:Topic", 354 | "madsrdf:Variant" 355 | ], 356 | "madsrdf:elementList": { 357 | "@list": [ 358 | { 359 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb9" 360 | } 361 | ] 362 | }, 363 | "madsrdf:variantLabel": { 364 | "@language": "en", 365 | "@value": "Frontier troubles" 366 | } 367 | }, 368 | { 369 | "@id": "_:n343ae13904244a34bcccef188e7bb02cb9", 370 | "@type": "madsrdf:TopicElement", 371 | "madsrdf:elementValue": { 372 | "@language": "en", 373 | "@value": "Frontier troubles" 374 | } 375 | } 376 | ], 377 | "@id": "/authorities/subjects/sh99005024" 378 | } -------------------------------------------------------------------------------- /tests/testFiles/Archaeology.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "http://v3/authorities/subjects/context.json", 3 | "@graph": [ 4 | { 5 | "@id": "http://id.loc.gov/authorities/subjects/sh85010480", 6 | "@type": [ 7 | "madsrdf:Authority", 8 | "madsrdf:Topic" 9 | ], 10 | "madsrdf:authoritativeLabel": { 11 | "@language": "en", 12 | "@value": "Auxiliary sciences of history" 13 | }, 14 | "madsrdf:elementList": { 15 | "@list": [ 16 | { 17 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb13" 18 | } 19 | ] 20 | } 21 | }, 22 | { 23 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb13", 24 | "@type": "madsrdf:TopicElement", 25 | "madsrdf:elementValue": { 26 | "@language": "en", 27 | "@value": "Auxiliary sciences of history" 28 | } 29 | }, 30 | { 31 | "@id": "http://id.loc.gov/authorities/subjects/sh85061212", 32 | "@type": [ 33 | "madsrdf:Authority", 34 | "madsrdf:Topic" 35 | ], 36 | "madsrdf:authoritativeLabel": { 37 | "@language": "en", 38 | "@value": "History" 39 | }, 40 | "madsrdf:elementList": { 41 | "@list": [ 42 | { 43 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb15" 44 | } 45 | ] 46 | } 47 | }, 48 | { 49 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb15", 50 | "@type": "madsrdf:TopicElement", 51 | "madsrdf:elementValue": { 52 | "@language": "en", 53 | "@value": "History" 54 | } 55 | }, 56 | { 57 | "@id": "http://id.loc.gov/authorities/subjects/sh85006507", 58 | "@type": [ 59 | "madsrdf:Authority", 60 | "madsrdf:Topic" 61 | ], 62 | "bflc:marcKey": "150 0$aArchaeology", 63 | "identifiers:lccn": "sh 85006507", 64 | "madsrdf:adminMetadata": [ 65 | { 66 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb1" 67 | }, 68 | { 69 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb2" 70 | } 71 | ], 72 | "madsrdf:authoritativeLabel": { 73 | "@language": "en", 74 | "@value": "Archaeology" 75 | }, 76 | "madsrdf:classification": { 77 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb3" 78 | }, 79 | "madsrdf:editorialNote": "subdivision [Antiquities] under names of countries, cities, etc., and under individual ethnic groups, e.g. [Egypt--Antiquities; Mayas--Antiquities]", 80 | "madsrdf:elementList": { 81 | "@list": [ 82 | { 83 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb4" 84 | } 85 | ] 86 | }, 87 | "madsrdf:hasBroaderAuthority": [ 88 | { 89 | "@id": "http://id.loc.gov/authorities/subjects/sh85005581" 90 | }, 91 | { 92 | "@id": "http://id.loc.gov/authorities/subjects/sh85010480" 93 | }, 94 | { 95 | "@id": "http://id.loc.gov/authorities/subjects/sh85061212" 96 | } 97 | ], 98 | "madsrdf:hasNarrowerAuthority": [ 99 | { 100 | "@id": "http://id.loc.gov/authorities/subjects/sh00007440" 101 | }, 102 | { 103 | "@id": "http://id.loc.gov/authorities/subjects/sh2003003476" 104 | }, 105 | { 106 | "@id": "http://id.loc.gov/authorities/subjects/sh2003004186" 107 | }, 108 | { 109 | "@id": "http://id.loc.gov/authorities/subjects/sh2003009064" 110 | }, 111 | { 112 | "@id": "http://id.loc.gov/authorities/subjects/sh2003009199" 113 | }, 114 | { 115 | "@id": "http://id.loc.gov/authorities/subjects/sh2003011000" 116 | }, 117 | { 118 | "@id": "http://id.loc.gov/authorities/subjects/sh2004001262" 119 | }, 120 | { 121 | "@id": "http://id.loc.gov/authorities/subjects/sh2005001576" 122 | }, 123 | { 124 | "@id": "http://id.loc.gov/authorities/subjects/sh2006000287" 125 | }, 126 | { 127 | "@id": "http://id.loc.gov/authorities/subjects/sh2007006623" 128 | }, 129 | { 130 | "@id": "http://id.loc.gov/authorities/subjects/sh2009002956" 131 | }, 132 | { 133 | "@id": "http://id.loc.gov/authorities/subjects/sh2009004421" 134 | }, 135 | { 136 | "@id": "http://id.loc.gov/authorities/subjects/sh2009004470" 137 | }, 138 | { 139 | "@id": "http://id.loc.gov/authorities/subjects/sh2012000959" 140 | }, 141 | { 142 | "@id": "http://id.loc.gov/authorities/subjects/sh2012004635" 143 | }, 144 | { 145 | "@id": "http://id.loc.gov/authorities/subjects/sh2012004636" 146 | }, 147 | { 148 | "@id": "http://id.loc.gov/authorities/subjects/sh2013000143" 149 | }, 150 | { 151 | "@id": "http://id.loc.gov/authorities/subjects/sh2013001302" 152 | }, 153 | { 154 | "@id": "http://id.loc.gov/authorities/subjects/sh2013001303" 155 | }, 156 | { 157 | "@id": "http://id.loc.gov/authorities/subjects/sh2015002234" 158 | }, 159 | { 160 | "@id": "http://id.loc.gov/authorities/subjects/sh2021005077" 161 | }, 162 | { 163 | "@id": "http://id.loc.gov/authorities/subjects/sh2021006222" 164 | }, 165 | { 166 | "@id": "http://id.loc.gov/authorities/subjects/sh85001256" 167 | }, 168 | { 169 | "@id": "http://id.loc.gov/authorities/subjects/sh85004685" 170 | }, 171 | { 172 | "@id": "http://id.loc.gov/authorities/subjects/sh85006703" 173 | }, 174 | { 175 | "@id": "http://id.loc.gov/authorities/subjects/sh85018080" 176 | }, 177 | { 178 | "@id": "http://id.loc.gov/authorities/subjects/sh85027024" 179 | }, 180 | { 181 | "@id": "http://id.loc.gov/authorities/subjects/sh85034228" 182 | }, 183 | { 184 | "@id": "http://id.loc.gov/authorities/subjects/sh85046105" 185 | }, 186 | { 187 | "@id": "http://id.loc.gov/authorities/subjects/sh85048843" 188 | }, 189 | { 190 | "@id": "http://id.loc.gov/authorities/subjects/sh85050977" 191 | }, 192 | { 193 | "@id": "http://id.loc.gov/authorities/subjects/sh85053066" 194 | }, 195 | { 196 | "@id": "http://id.loc.gov/authorities/subjects/sh85060817" 197 | }, 198 | { 199 | "@id": "http://id.loc.gov/authorities/subjects/sh85061115" 200 | }, 201 | { 202 | "@id": "http://id.loc.gov/authorities/subjects/sh85065024" 203 | }, 204 | { 205 | "@id": "http://id.loc.gov/authorities/subjects/sh85065824" 206 | }, 207 | { 208 | "@id": "http://id.loc.gov/authorities/subjects/sh85066643" 209 | }, 210 | { 211 | "@id": "http://id.loc.gov/authorities/subjects/sh85072567" 212 | }, 213 | { 214 | "@id": "http://id.loc.gov/authorities/subjects/sh85079786" 215 | }, 216 | { 217 | "@id": "http://id.loc.gov/authorities/subjects/sh85087721" 218 | }, 219 | { 220 | "@id": "http://id.loc.gov/authorities/subjects/sh85093636" 221 | }, 222 | { 223 | "@id": "http://id.loc.gov/authorities/subjects/sh85097895" 224 | }, 225 | { 226 | "@id": "http://id.loc.gov/authorities/subjects/sh85101308" 227 | }, 228 | { 229 | "@id": "http://id.loc.gov/authorities/subjects/sh85102008" 230 | }, 231 | { 232 | "@id": "http://id.loc.gov/authorities/subjects/sh85107780" 233 | }, 234 | { 235 | "@id": "http://id.loc.gov/authorities/subjects/sh85109300" 236 | }, 237 | { 238 | "@id": "http://id.loc.gov/authorities/subjects/sh85114683" 239 | }, 240 | { 241 | "@id": "http://id.loc.gov/authorities/subjects/sh85116926" 242 | }, 243 | { 244 | "@id": "http://id.loc.gov/authorities/subjects/sh85126368" 245 | }, 246 | { 247 | "@id": "http://id.loc.gov/authorities/subjects/sh85126691" 248 | }, 249 | { 250 | "@id": "http://id.loc.gov/authorities/subjects/sh85127907" 251 | }, 252 | { 253 | "@id": "http://id.loc.gov/authorities/subjects/sh85134099" 254 | }, 255 | { 256 | "@id": "http://id.loc.gov/authorities/subjects/sh85139611" 257 | }, 258 | { 259 | "@id": "http://id.loc.gov/authorities/subjects/sh85144346" 260 | }, 261 | { 262 | "@id": "http://id.loc.gov/authorities/subjects/sh86001404" 263 | }, 264 | { 265 | "@id": "http://id.loc.gov/authorities/subjects/sh87000460" 266 | }, 267 | { 268 | "@id": "http://id.loc.gov/authorities/subjects/sh89000928" 269 | }, 270 | { 271 | "@id": "http://id.loc.gov/authorities/subjects/sh89002313" 272 | }, 273 | { 274 | "@id": "http://id.loc.gov/authorities/subjects/sh91002758" 275 | }, 276 | { 277 | "@id": "http://id.loc.gov/authorities/subjects/sh93006952" 278 | }, 279 | { 280 | "@id": "http://id.loc.gov/authorities/subjects/sh94001190" 281 | }, 282 | { 283 | "@id": "http://id.loc.gov/authorities/subjects/sh94008300" 284 | }, 285 | { 286 | "@id": "http://id.loc.gov/authorities/subjects/sh95000886" 287 | }, 288 | { 289 | "@id": "http://id.loc.gov/authorities/subjects/sh95000887" 290 | } 291 | ], 292 | "madsrdf:hasReciprocalAuthority": { 293 | "@id": "http://id.loc.gov/authorities/subjects/sh85005757" 294 | }, 295 | "madsrdf:hasVariant": { 296 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb6" 297 | }, 298 | "madsrdf:isMemberOfMADSCollection": [ 299 | { 300 | "@id": "http://id.loc.gov/authorities/subjects/collection_LCSHAuthorizedHeadings" 301 | }, 302 | { 303 | "@id": "http://id.loc.gov/authorities/subjects/collection_LCSH_General" 304 | }, 305 | { 306 | "@id": "http://id.loc.gov/authorities/subjects/collection_SubdivideGeographically" 307 | } 308 | ], 309 | "madsrdf:isMemberOfMADSScheme": { 310 | "@id": "http://id.loc.gov/authorities/subjects" 311 | }, 312 | "madsrdf:note": "Here are entered works on archaeology as a branch of learning. This heading may be divided geographically for works on this branch of learning in a specific place. Works on the antiquities of particular regions, countries, cities, etc. are entered under the name of the place subdivided by [Antiquities.]", 313 | "owl:sameAs": [ 314 | { 315 | "@id": "http://id.loc.gov/authorities/sh85006507#concept" 316 | }, 317 | { 318 | "@id": "info:lc/authorities/sh85006507" 319 | } 320 | ] 321 | }, 322 | { 323 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb1", 324 | "@type": "ri:RecordInfo", 325 | "ri:recordChangeDate": { 326 | "@type": "xsd:dateTime", 327 | "@value": "1996-09-10T15:07:45" 328 | }, 329 | "ri:recordContentSource": { 330 | "@id": "http://id.loc.gov/vocabulary/organizations/dlc" 331 | }, 332 | "ri:recordStatus": "revised" 333 | }, 334 | { 335 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb2", 336 | "@type": "ri:RecordInfo", 337 | "ri:recordChangeDate": { 338 | "@type": "xsd:dateTime", 339 | "@value": "1986-02-11T00:00:00" 340 | }, 341 | "ri:recordContentSource": { 342 | "@id": "http://id.loc.gov/vocabulary/organizations/dlc" 343 | }, 344 | "ri:recordStatus": "new" 345 | }, 346 | { 347 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb3", 348 | "@type": "lcc:ClassNumber", 349 | "madsrdf:code": "CC" 350 | }, 351 | { 352 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb4", 353 | "@type": "madsrdf:TopicElement", 354 | "madsrdf:elementValue": { 355 | "@language": "en", 356 | "@value": "Archaeology" 357 | } 358 | }, 359 | { 360 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb6", 361 | "@type": [ 362 | "madsrdf:Topic", 363 | "madsrdf:Variant" 364 | ], 365 | "madsrdf:elementList": { 366 | "@list": [ 367 | { 368 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb7" 369 | } 370 | ] 371 | }, 372 | "madsrdf:variantLabel": { 373 | "@language": "en", 374 | "@value": "Archeology" 375 | } 376 | }, 377 | { 378 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb7", 379 | "@type": "madsrdf:TopicElement", 380 | "madsrdf:elementValue": { 381 | "@language": "en", 382 | "@value": "Archeology" 383 | } 384 | }, 385 | { 386 | "@id": "http://id.loc.gov/authorities/subjects/sh85005581", 387 | "@type": [ 388 | "madsrdf:Authority", 389 | "madsrdf:Topic" 390 | ], 391 | "madsrdf:authoritativeLabel": { 392 | "@language": "en", 393 | "@value": "Anthropology" 394 | }, 395 | "madsrdf:elementList": { 396 | "@list": [ 397 | { 398 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb9" 399 | } 400 | ] 401 | } 402 | }, 403 | { 404 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb9", 405 | "@type": "madsrdf:TopicElement", 406 | "madsrdf:elementValue": { 407 | "@language": "en", 408 | "@value": "Anthropology" 409 | } 410 | }, 411 | { 412 | "@id": "http://id.loc.gov/authorities/subjects/sh85005757", 413 | "@type": [ 414 | "madsrdf:Authority", 415 | "madsrdf:Topic" 416 | ], 417 | "madsrdf:authoritativeLabel": { 418 | "@language": "en", 419 | "@value": "Antiquities" 420 | }, 421 | "madsrdf:elementList": { 422 | "@list": [ 423 | { 424 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb11" 425 | } 426 | ] 427 | } 428 | }, 429 | { 430 | "@id": "_:n7eb4def74a2549e9b5fdae71aa4aae6fb11", 431 | "@type": "madsrdf:TopicElement", 432 | "madsrdf:elementValue": { 433 | "@language": "en", 434 | "@value": "Antiquities" 435 | } 436 | } 437 | ], 438 | "@id": "/authorities/subjects/sh85006507" 439 | } --------------------------------------------------------------------------------