├── .gitignore ├── .editorconfig ├── .eslintrc.cjs ├── .github └── workflows │ └── main.yml ├── package.json ├── CHANGELOG.md ├── LICENSE ├── README.md └── bin └── jsonld.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw[op] 2 | *~ 3 | .cproject 4 | .project 5 | *.sublime-project 6 | *.sublime-workspace 7 | .DS_Store 8 | .settings 9 | coverage 10 | node_modules 11 | v8.log 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.{js,json,jsonld,yaml,yml}] 12 | indent_style = space 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: [ 7 | 'digitalbazaar', 8 | 'digitalbazaar/module', 9 | 'digitalbazaar/jsdoc' 10 | ], 11 | rules: { 12 | 'unicorn/prefer-node-protocol': 'error' 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 10 9 | strategy: 10 | matrix: 11 | node-version: [20.x] 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: Use Node.js ${{ matrix.node-version }} 15 | uses: actions/setup-node@v4 16 | with: 17 | node-version: ${{ matrix.node-version }} 18 | - name: Install 19 | run: npm install 20 | - name: Lint 21 | run: npm run lint 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonld-cli", 3 | "version": "2.0.1-0", 4 | "description": "A JSON-LD command line interface tool.", 5 | "homepage": "https://github.com/digitalbazaar/jsonld-cli", 6 | "author": { 7 | "name": "Digital Bazaar, Inc.", 8 | "email": "support@digitalbazaar.com", 9 | "url": "https://digitalbazaar.com/" 10 | }, 11 | "contributors": [ 12 | { 13 | "name": "Dave Longley", 14 | "email": "dlongley@digitalbazaar.com" 15 | }, 16 | { 17 | "name": "David I. Lehn", 18 | "email": "dlehn@digitalbazaar.com" 19 | } 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/digitalbazaar/jsonld-cli" 24 | }, 25 | "bugs": { 26 | "url": "https://github.com/digitalbazaar/jsonld-cli/issues", 27 | "email": "support@digitalbazaar.com" 28 | }, 29 | "license": "BSD-3-Clause", 30 | "bin": { 31 | "jsonld": "./bin/jsonld.js" 32 | }, 33 | "type": "module", 34 | "dependencies": { 35 | "commander": "^11.1.0", 36 | "jsonld": "^8.3.2", 37 | "jsonld-request": "^2.0.1" 38 | }, 39 | "devDependencies": { 40 | "eslint": "^8.56.0", 41 | "eslint-config-digitalbazaar": "^5.0.1", 42 | "eslint-plugin-jsdoc": "^48.0.1", 43 | "eslint-plugin-unicorn": "^50.0.1" 44 | }, 45 | "files": [ 46 | "bin/**/*.js" 47 | ], 48 | "engines": { 49 | "node": ">=16" 50 | }, 51 | "keywords": [ 52 | "JSON", 53 | "JSON-LD", 54 | "Linked Data", 55 | "RDF", 56 | "RDFa", 57 | "Semantic Web", 58 | "jsonld" 59 | ], 60 | "scripts": { 61 | "lint": "eslint ." 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # jsonld-cli ChangeLog 2 | 3 | ## 2.0.0 - 2024-01-04 4 | 5 | ## Changed 6 | - Set version from `package.json`. 7 | - **BREAKING**: Update dependencies. 8 | - `commander` requires Node.js >= 16. 9 | 10 | ## 1.0.0 - 2022-09-01 11 | 12 | ## Changed 13 | - **BREAKING**: Update dependencies. Likely behavior changes since last 14 | release. 15 | - **BREAKING**: Change `--nquads` option to `--n-quads`. 16 | - **BREAKING**: Requre Node.js >=14. 17 | - **BREAKING**: `base` now defaults to `null`. Use `-b ` or `--base 18 | ` to set `base` explicitly. Use `-B/--auto-base` to set `base` 19 | automatically based on the source file, URL, or stdin. 20 | - **BREAKING**: Primary input can be stdin, file, HTTP, or HTTPS resources. 21 | Secondary input can only be HTTP or HTTPS for security reasons unless the 22 | `-a/--allow` option is used. 23 | - **BREAKING**: Change `normalize` command to `canonize`. 24 | 25 | ## Added 26 | - Add `toRdf` command. 27 | - Add `lint` command. Note that this uses currently private unstable 28 | [jsonld.js][] APIs. 29 | - Add `-s/--safe` `safe` mode to commands. 30 | - Add `-l/--lint` `lint` mode to commands. 31 | - Add `-a/--allow` option to change allowed secondary resource loaders. 32 | 33 | ## 0.3.0 - 2018-07-06 34 | 35 | ## Changed 36 | - *BREAKING*: Update dependencies. Includes update to jsonld.js 1.x which fixes 37 | bugs but could also cause some behavior changes. Future updates will include 38 | more processing control flags. 39 | 40 | ## 0.2.0 - 2017-12-18 41 | 42 | ## Changed 43 | - Updated dependencies. 44 | 45 | ## 0.1.0 - 2015-09-12 46 | 47 | ### Added 48 | - Command line interface tool from [jsonld.js][]. 49 | 50 | [jsonld.js]: https://github.com/digitalbazaar/jsonld.js 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | You may use the jsonld.js project under the terms of the BSD License. 2 | 3 | You are free to use this project in commercial projects as long as the 4 | copyright header is left intact. 5 | 6 | If you are a commercial entity and use this set of libraries in your 7 | commercial software then reasonable payment to Digital Bazaar, if you can 8 | afford it, is not required but is expected and would be appreciated. If this 9 | library saves you time, then it's saving you money. The cost of developing 10 | JSON-LD was on the order of several months of work and tens of 11 | thousands of dollars. We are attempting to strike a balance between helping 12 | the development community while not being taken advantage of by lucrative 13 | commercial entities for our efforts. 14 | 15 | ------------------------------------------------------------------------------- 16 | New BSD License (3-clause) 17 | Copyright (c) 2010, Digital Bazaar, Inc. 18 | All rights reserved. 19 | 20 | Redistribution and use in source and binary forms, with or without 21 | modification, are permitted provided that the following conditions are met: 22 | * Redistributions of source code must retain the above copyright 23 | notice, this list of conditions and the following disclaimer. 24 | * Redistributions in binary form must reproduce the above copyright 25 | notice, this list of conditions and the following disclaimer in the 26 | documentation and/or other materials provided with the distribution. 27 | * Neither the name of Digital Bazaar, Inc. nor the 28 | names of its contributors may be used to endorse or promote products 29 | derived from this software without specific prior written permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 32 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 33 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 34 | DISCLAIMED. IN NO EVENT SHALL DIGITAL BAZAAR BE LIABLE FOR ANY 35 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 36 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 38 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jsonld-cli 2 | ========== 3 | 4 | Introduction 5 | ------------ 6 | 7 | This module provides a command line tool `jsonld` to manipulate [JSON-LD][] 8 | data. It is written in JavaScript for [Node.js][] and uses the [jsonld.js][] 9 | and [jsonld-request][] libraries. Inputs can be from stdin, URLs, or files. 10 | 11 | ## Requirements 12 | 13 | * [Node.js][] 14 | * [npm][] 15 | 16 | ## Installation 17 | 18 | ### Install from NPM 19 | 20 | ``` 21 | npm install -g jsonld-cli 22 | ``` 23 | 24 | ### Use directly with npx 25 | 26 | ``` 27 | npx jsonld-cli ... 28 | ``` 29 | 30 | ## Usage 31 | 32 | The `jsonld` command line tool can be used to: 33 | 34 | * Check JSON-LD for various problematic data. 35 | * Transform JSON-LD to compact, expanded, flattened, or canonized form. 36 | * Transform [RDFa][] to JSON-LD. 37 | * Canonize JSON-LD/RDFa Datasets to [N-Quads][]. 38 | 39 | To show tool options, a list of commands, or command options: 40 | 41 | jsonld --help 42 | jsonld COMMAND --help 43 | 44 | To check JSON-LD for some common problems: 45 | 46 | jsonld lint "https://example.com/data.json" 47 | 48 | To compact a document on the Web using a JSON-LD context published on 49 | the Web: 50 | 51 | jsonld compact -c "https://w3id.org/payswarm/v1" "http://recipes.payswarm.com/?p=10554" 52 | 53 | The command above will read in a PaySwarm Asset and Listing in [RDFa][] 1.0 54 | format, convert it to JSON-LD expanded form, compact it using the 55 | 'https://w3id.org/payswarm/v1' context, and dump it out to the console in 56 | compacted form. 57 | 58 | jsonld canonize -q "http://recipes.payswarm.com/?p=10554" 59 | 60 | The command above will read in a PaySwarm Asset and Listing in [RDFa][] 1.0 61 | format, canonize the data using the RDF Dataset canonicalization algorithm, and 62 | then dump the output to canonized [N-Quads][] format. The [N-Quads][] can then 63 | be processed via SHA-256, or similar algorithm, to get a deterministic hash of 64 | the contents of the Dataset. 65 | 66 | Security Considerations 67 | ----------------------- 68 | 69 | * This tool is able to read stdin, local files, and remote resources. 70 | * Loading of remote resources may reveal aspects of the data being processed. 71 | * Input data may recursively load remote resources. 72 | * Input data may load arbitrary local files if allowed. 73 | * Processing data that uses untrusted remote resources could result in 74 | unexpected output. 75 | 76 | Commercial Support 77 | ------------------ 78 | 79 | Commercial support for this library is available upon request from 80 | [Digital Bazaar][]: support@digitalbazaar.com 81 | 82 | Source Code 83 | ----------- 84 | 85 | https://github.com/digitalbazaar/jsonld-cli 86 | 87 | [Digital Bazaar]: https://digitalbazaar.com/ 88 | [JSON-LD]: https://json-ld.org/ 89 | [N-Quads]: https://www.w3.org/TR/n-quads/ 90 | [Node.js]: https://nodejs.org/ 91 | [RDFa]: http://www.w3.org/TR/rdfa-core/ 92 | [json-ld.org]: https://github.com/json-ld/json-ld.org 93 | [jsonld-request]: https://github.com/digitalbazaar/jsonld-request 94 | [jsonld.js]: https://github.com/digitalbazaar/jsonld.js 95 | [npm]: https://npmjs.org/ 96 | -------------------------------------------------------------------------------- /bin/jsonld.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * A command line JSON-LD utility. 4 | * 5 | * @author David I. Lehn 6 | * 7 | * BSD 3-Clause License 8 | * Copyright (c) 2013-2022 Digital Bazaar, Inc. 9 | * All rights reserved. 10 | */ 11 | import {fileURLToPath} from 'node:url'; 12 | import https from 'node:https'; 13 | import {inspect} from 'node:util'; 14 | import jsonld from 'jsonld'; 15 | import {jsonldRequest} from 'jsonld-request'; 16 | import path from 'node:path'; 17 | import {program} from 'commander'; 18 | import {readFileSync} from 'node:fs'; 19 | 20 | const version = { 21 | value: undefined, 22 | toString() { 23 | // load version when used 24 | if(this.value === undefined) { 25 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 26 | const pkg = 27 | JSON.parse(readFileSync(path.join(__dirname, '..', 'package.json'))); 28 | this.value = pkg.version; 29 | } 30 | return this.value; 31 | } 32 | }; 33 | 34 | program.version(version); 35 | 36 | // all allowed modes for jsonld-request 37 | const ALLOW_ALL = ['stdin', 'file', 'http', 'https']; 38 | const ALLOW_DEFAULT = ['http', 'https']; 39 | const ALLOW_NONE = []; 40 | 41 | // Parse the string or value and return the boolean value encoded or raise an 42 | // exception. 43 | function boolify(value) { 44 | if(typeof value === 'boolean') { 45 | return value; 46 | } 47 | if(typeof value === 'string' && value) { 48 | switch(value.toLowerCase()) { 49 | case 'true': 50 | case 't': 51 | case '1': 52 | case 'yes': 53 | case 'y': 54 | return true; 55 | case 'false': 56 | case 'f': 57 | case '0': 58 | case 'no': 59 | case 'n': 60 | return false; 61 | } 62 | } 63 | // if here we couldn't parse it 64 | throw new Error('Invalid boolean:' + value); 65 | } 66 | 67 | // common output function 68 | async function _output(data, cmd) { 69 | if(typeof data === 'object') { 70 | const output = JSON.stringify(data, null, cmd.indent); 71 | process.stdout.write(output); 72 | } else if(typeof data === 'string') { 73 | process.stdout.write(data.trim()); 74 | } else { 75 | process.stdout.write(data); 76 | } 77 | if(cmd.newline) { 78 | process.stdout.write('\n'); 79 | } 80 | } 81 | 82 | // lint warning handler 83 | function _warningHandler({event, next}) { 84 | if(event.level === 'warning') { 85 | console.log(`WARNING: ${event.message}`); 86 | console.log(inspect(event, {colors: true, depth: 10})); 87 | } 88 | next(); 89 | } 90 | 91 | // error handler 92 | function _error(err, msg = 'Error:') { 93 | if(err) { 94 | if(err.stack) { 95 | console.log(err.stack); 96 | } else { 97 | console.log(err.toString()); 98 | } 99 | if(typeof err === 'object') { 100 | const {cause, ...options} = err; 101 | if(Object.keys(options).length !== 0) { 102 | console.log(msg, inspect(options, {colors: true, depth: 10})); 103 | } 104 | if(cause) { 105 | _error(cause, 'Error Cause:'); 106 | } 107 | } 108 | process.exit(1); 109 | } 110 | } 111 | 112 | // request wrapper to handle primary/secondary loading access 113 | let _primary = true; 114 | async function _jsonldRequest(url, reqOptions, options) { 115 | const _options = {...reqOptions}; 116 | if(_primary) { 117 | _options.allow = ALLOW_ALL; 118 | } else { 119 | _options.allow = options.allow; 120 | } 121 | _primary = false; 122 | return jsonldRequest(url, _options); 123 | } 124 | 125 | // check for HTTP/HTTPS URL 126 | function _isHTTP(url) { 127 | return (url.indexOf('http://') === 0 || url.indexOf('https://') === 0); 128 | } 129 | 130 | // init common command options 131 | function _jsonLdCommand(command) { 132 | command 133 | .option('-i, --indent ', 'spaces to indent [2]', Number, 2) 134 | .option('-N, --no-newline', 'do not output the trailing newline [newline]') 135 | .option('-k, --insecure', 'allow insecure connections [false]') 136 | .option('-a, --allow ', 137 | 'allowed secondary resource loaders (none,all,stdin,file,http,https) ' + 138 | '[http,https]') 139 | .option('-t, --type ', 'input data type [auto]') 140 | .option('-B, --auto-base', 'use base IRI from source [false]') 141 | .option('-b, --base ', 'base IRI [null]') 142 | .option('-l, --lint', 'show lint warnings [false]') 143 | .option('-s, --safe', 'enable safe mode [false]'); 144 | return command; 145 | } 146 | 147 | // determine source base 148 | function _getSourceBase(command, input) { 149 | // stdin 150 | if(input === '-') { 151 | return 'stdin://'; 152 | } 153 | // use input as base if it looks like a URL 154 | if(_isHTTP(input)) { 155 | return input; 156 | } 157 | // use a file URL otherwise 158 | return 'file://' + path.resolve(process.cwd(), input); 159 | } 160 | 161 | // determine base 162 | function _getBase(command, input) { 163 | // explicit base set 164 | if(command.base) { 165 | return command.base; 166 | } 167 | if(command.sourceBase) { 168 | return _getSourceBase(command, input); 169 | } 170 | return null; 171 | } 172 | 173 | // init common request options 174 | function _requestOptions(command, input) { 175 | const options = {}; 176 | if(command.insecure) { 177 | options.agent = new https.Agent({rejectUnauthorized: false}); 178 | } 179 | if(command.type) { 180 | options.dataType = command.type; 181 | } 182 | options.base = _getBase(command, input); 183 | return options; 184 | } 185 | 186 | // init common jsonld options 187 | function _jsonLdOptions(command, input) { 188 | const options = {}; 189 | 190 | if(command.allow) { 191 | // split allow modes 192 | options.allow = command.allow.split(','); 193 | if(options.allow.includes('all')) { 194 | options.allow = ALLOW_ALL; 195 | } else if(options.allow.includes('none')) { 196 | options.allow = ALLOW_NONE; 197 | } 198 | } else { 199 | // default to only load secondary HTTP/HTTPS resources 200 | options.access = ALLOW_DEFAULT; 201 | } 202 | 203 | if(command.lint) { 204 | options.eventHandler = _warningHandler; 205 | } 206 | 207 | if(command.safe) { 208 | options.safe = true; 209 | } 210 | 211 | options.base = _getBase(command, input); 212 | 213 | // setup documentLoader 214 | // FIXME: should be elsewhere 215 | options.documentLoader = async function documentLoader(url) { 216 | const reqOpts = _requestOptions(command, url); 217 | const reqResult = await _jsonldRequest(url, reqOpts, options); 218 | return { 219 | contextUrl: null, 220 | documentUrl: url, 221 | document: reqResult.data || null 222 | }; 223 | }; 224 | 225 | return options; 226 | } 227 | 228 | program 229 | .on('--help', function() { 230 | console.log(); 231 | console.log( 232 | ' The primary input for all commands can be a filename, a URL\n' + 233 | ' beginning with "http://" or "https://", or "-" for stdin (the\n' + 234 | ' default). Secondary loaded resources can only be HTTP or HTTPS\n' + 235 | ' by default for security reasons unless the "-a/--allow" option\n' + 236 | ' is used.'); 237 | console.log(); 238 | console.log( 239 | ' Input type can be specified as a standard content type or a\n' + 240 | ' simple string for common types. See the "request" extension code\n' + 241 | ' for available types. XML and HTML variations will be converted\n' + 242 | ' with an RDFa processor if available. If the input type is not\n' + 243 | ' specified it will be auto-detected based on file extension, URL\n' + 244 | ' content type, or by guessing with various parsers. Guessing may\n' + 245 | ' not always produce correct results.'); 246 | console.log(); 247 | console.log( 248 | ' Output type can be specified for the "format" command and a\n' + 249 | ' N-Quads shortcut for the "canonize" command. For other commands\n' + 250 | ' you can pipe JSON-LD output to the "format" command.'); 251 | console.log(); 252 | }); 253 | 254 | _jsonLdCommand(program.command('format [filename|URL|-]')) 255 | .description('format and convert JSON-LD') 256 | .option('-f, --format ', 'output format [json]', String) 257 | .option('-q, --n-quads', 'output application/n-quads [false]') 258 | .option('-j, --json', 'output application/json [true]') 259 | .action(async function format(input, cmd) { 260 | input = input || '-'; 261 | const options = _jsonLdOptions(cmd, input); 262 | options.format = cmd.format || 'json'; 263 | if(cmd.nQuads) { 264 | options.format = 'application/n-quads'; 265 | } 266 | if(cmd.json) { 267 | options.format = 'application/json'; 268 | } 269 | 270 | let result; 271 | switch(options.format.toLowerCase()) { 272 | case 'nquads': 273 | case 'n-quads': 274 | case 'application/nquads': 275 | case 'application/n-quads': 276 | // normalize format for toRDF 277 | options.format = 'application/n-quads'; 278 | result = await jsonld.toRDF(input, options); 279 | break; 280 | case 'json': 281 | case 'jsonld': 282 | case 'json-ld': 283 | case 'ld+json': 284 | case 'application/json': 285 | case 'application/ld+json': 286 | // just doing basic JSON formatting 287 | const reqOpts = _requestOptions(cmd, input); 288 | const reqResult = await _jsonldRequest(input, reqOpts, options); 289 | result = reqResult.data; 290 | break; 291 | default: 292 | throw new Error('ERROR: Unknown format: ' + options.format); 293 | } 294 | 295 | await _output(result, cmd); 296 | }); 297 | 298 | _jsonLdCommand(program.command('lint [filename|URL|-]')) 299 | .description('lint JSON-LD') 300 | .action(async function lint(input, cmd) { 301 | input = input || '-'; 302 | const options = _jsonLdOptions(cmd, input); 303 | 304 | await jsonld.expand(input, { 305 | ...options, 306 | eventHandler: _warningHandler 307 | }); 308 | }); 309 | 310 | _jsonLdCommand(program.command('compact [filename|URL]')) 311 | .description('compact JSON-LD') 312 | .option('-c, --context ', 'context filename or URL') 313 | .option('-A, --no-compact-arrays', 314 | 'disable compacting arrays to single values') 315 | .option('-g, --graph', 'always output top-level graph [false]') 316 | .action(async function compact(input, cmd) { 317 | input = input || '-'; 318 | if(!cmd.context) { 319 | throw new Error('ERROR: Context not specified, use -c/--context'); 320 | } 321 | const options = _jsonLdOptions(cmd, input); 322 | options.compactArrays = cmd.compactArrays; 323 | options.graph = !!cmd.graph; 324 | 325 | const result = await jsonld.compact(input, cmd.context, options); 326 | 327 | await _output(result, cmd); 328 | }); 329 | 330 | _jsonLdCommand(program.command('expand [filename|URL|-]')) 331 | .description('expand JSON-LD') 332 | .option(' --keep-free-floating-nodes', 'keep free-floating nodes') 333 | .action(async function expand(input, cmd) { 334 | input = input || '-'; 335 | const options = _jsonLdOptions(cmd, input); 336 | options.keepFreeFloatingNodes = cmd.keepFreeFloatingNodes; 337 | 338 | const result = await jsonld.expand(input, options); 339 | 340 | await _output(result, cmd); 341 | }); 342 | 343 | _jsonLdCommand(program.command('flatten [filename|URL|-]')) 344 | .description('flatten JSON-LD') 345 | .option('-c, --context ', 346 | 'context filename or URL for compaction [none]') 347 | .action(async function flatten(input, cmd) { 348 | input = input || '-'; 349 | const options = _jsonLdOptions(cmd, input); 350 | 351 | const result = await jsonld.flatten(input, cmd.context, options); 352 | 353 | await _output(result, cmd); 354 | }); 355 | 356 | _jsonLdCommand(program.command('frame [filename|URL|-]')) 357 | .description('frame JSON-LD') 358 | .option('-f, --frame ', 'frame to use') 359 | .option(' --embed ', 'default @embed flag [true]', boolify, true) 360 | .option(' --explicit ', 361 | 'default @explicit flag [false]', boolify, false) 362 | .option(' --omit-default ', 363 | 'default @omitDefault flag [false]', boolify, false) 364 | .action(async function frame(input, cmd) { 365 | input = input || '-'; 366 | if(!cmd.frame) { 367 | throw new Error('ERROR: Frame not specified, use -f/--frame'); 368 | } 369 | const options = _jsonLdOptions(cmd, input); 370 | options.embed = cmd.embed; 371 | options.explicit = cmd.explicit; 372 | options.omitDefault = cmd.omitDefault; 373 | 374 | const result = await jsonld.frame(input, cmd.frame, options); 375 | 376 | await _output(result, cmd); 377 | }); 378 | 379 | // TODO: add fromRdf support 380 | //_jsonLdCommand(program.command('fromRdf [filename|URL|-]')) 381 | // ... 382 | 383 | _jsonLdCommand(program.command('toRdf [filename|URL|-]')) 384 | .description('convert JSON-LD into an RdfDataset') 385 | .option('-f, --format ', 386 | 'format to output (\'application/n-quads\' for N-Quads') 387 | .option('-q, --n-quads', 'use \'application/n-quads\' format') 388 | .option('-g, --generalized-rdf', 'produce generalized RDF') 389 | .action(async function toRdf(input, cmd) { 390 | input = input || '-'; 391 | const options = _jsonLdOptions(cmd, input); 392 | if(cmd.nQuads) { 393 | options.format = 'application/n-quads'; 394 | } 395 | if(cmd.generalizedRdf) { 396 | options.produceGeneralizedRdf = true; 397 | } 398 | if(cmd.format) { 399 | options.format = cmd.format; 400 | } 401 | 402 | const result = await jsonld.toRDF(input, options); 403 | 404 | await _output(result, cmd); 405 | }); 406 | 407 | _jsonLdCommand(program.command('canonize [filename|URL|-]')) 408 | .description('canonize JSON-LD') 409 | .option('-f, --format ', 410 | 'format to output (\'application/n-quads\' for N-Quads') 411 | .option('-q, --n-quads', 'use \'application/n-quads\' format') 412 | .action(async function canonize(input, cmd) { 413 | input = input || '-'; 414 | const options = _jsonLdOptions(cmd, input); 415 | if(cmd.nQuads) { 416 | options.format = 'application/n-quads'; 417 | } 418 | if(cmd.format) { 419 | options.format = cmd.format; 420 | } 421 | 422 | const result = await jsonld.canonize(input, options); 423 | 424 | await _output(result, cmd); 425 | }); 426 | 427 | program 428 | .parseAsync(process.argv) 429 | .catch(e => { 430 | _error(e); 431 | }); 432 | --------------------------------------------------------------------------------