diff --git a/LICENSE-3RD-PARTY.txt b/LICENSE-3RD-PARTY.txt index 255b6060..fbf4474f 100644 --- a/LICENSE-3RD-PARTY.txt +++ b/LICENSE-3RD-PARTY.txt @@ -1230,6 +1230,38 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================ +================================================================================ + js-yaml + +License name: MIT + License URL: https://github.com/nodeca/js-yaml/blob/master/LICENSE + License applies to files under the folder lib/_npm/js-yaml/ + +Source: https://github.com/nodeca/js-yaml +================================================================================ +(The MIT License) + +Copyright (C) 2011-2015 by Vitaly Puzrin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +================================================================================ + ================================================================================ jsTree diff --git a/Playground.html b/Playground.html index 59556b5f..9a8cabac 100644 --- a/Playground.html +++ b/Playground.html @@ -10,11 +10,11 @@ diff --git a/docs/wiki/3rd-party-libraries.md b/docs/wiki/3rd-party-libraries.md index eec73fca..07620072 100644 --- a/docs/wiki/3rd-party-libraries.md +++ b/docs/wiki/3rd-party-libraries.md @@ -72,6 +72,11 @@ Source: https://github.com/jquery/jquery License: MIT (https://raw.githubusercontent.com/jquery/jquery/master/LICENSE.txt) +## js-yaml +Source: https://github.com/nodeca/js-yaml + +License: MIT (https://github.com/nodeca/js-yaml/blob/master/LICENSE) + ## jsTree Website: https://www.jstree.com/ diff --git a/index.html b/index.html index b2be63d2..3bf7eb68 100644 --- a/index.html +++ b/index.html @@ -25,7 +25,6 @@ - @@ -37,6 +36,7 @@ ["bowser", "jstree", "localforage", "goldenlayout", "vue", "kaitai-struct-compiler", "dateformat"].forEach( name => paths[name] = `../../lib/_npm/${name}/${name}`); paths["big-integer"] = "../../lib/_npm/BigInteger/BigInteger"; + paths["js-yaml"] = "../../lib/_npm/js-yaml/js-yaml.min"; requirejs.config({ baseUrl: "js/v1/", paths: paths }); require(["app.unsupportedBrowser"]); diff --git a/lib/ts-types/js-yaml.d.ts b/lib/ts-types/js-yaml.d.ts new file mode 100644 index 00000000..e39c55d0 --- /dev/null +++ b/lib/ts-types/js-yaml.d.ts @@ -0,0 +1,165 @@ +// Type definitions for js-yaml v4.0.0 +// Project: https://github.com/nodeca/js-yaml + +// Adapted from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/65afafadd93759348909de1cdad5df5789c94326/types/js-yaml/index.d.ts +// 1. fixed compatibility with TypeScript 2 (which we're still +// using at the time of writing) by replacing `unknown` with `any` +// 2. wrap everything in `declare namespace jsyaml { ... }` and export it +// as "js-yaml" module so that it works in our setup + +declare namespace jsyaml { + export function load(str: string, opts?: LoadOptions): any; + + export class Type { + constructor(tag: string, opts?: TypeConstructorOptions); + + kind: "sequence" | "scalar" | "mapping" | null; + + resolve(data: any): boolean; + + construct(data: any, type?: string): any; + + instanceOf: object | null; + predicate: ((data: object) => boolean) | null; + represent: ((data: object) => any) | { [x: string]: (data: object) => any } | null; + representName: ((data: object) => any) | null; + defaultStyle: string | null; + multi: boolean; + styleAliases: { [x: string]: any }; + } + + export class Schema { + constructor(definition: SchemaDefinition | Type[] | Type); + + extend(types: SchemaDefinition | Type[] | Type): Schema; + } + + export function loadAll(str: string, iterator?: null, opts?: LoadOptions): any[]; + export function loadAll(str: string, iterator: (doc: any) => void, opts?: LoadOptions): void; + + export function dump(obj: any, opts?: DumpOptions): string; + + export interface LoadOptions { + /** string to be used as a file path in error/warning messages. */ + filename?: string | undefined; + + /** function to call on warning messages. */ + onWarning?(this: null, e: YAMLException): void; + + /** specifies a schema to use. */ + schema?: Schema | undefined; + /** compatibility with JSON.parse behaviour. */ + json?: boolean | undefined; + + /** listener for parse events */ + listener?(this: State, eventType: EventType, state: State): void; + } + + export type EventType = "open" | "close"; + + export interface State { + input: string; + filename: string | null; + schema: Schema; + onWarning: (this: null, e: YAMLException) => void; + json: boolean; + length: number; + position: number; + line: number; + lineStart: number; + lineIndent: number; + version: null | number; + checkLineBreaks: boolean; + kind: string; + result: any; + implicitTypes: Type[]; + } + + export interface DumpOptions { + /** indentation width to use (in spaces). */ + indent?: number | undefined; + /** when true, will not add an indentation level to array elements */ + noArrayIndent?: boolean | undefined; + /** do not throw on invalid types (like function in the safe schema) and skip pairs and single values with such types. */ + skipInvalid?: boolean | undefined; + /** specifies level of nesting, when to switch from block to flow style for collections. -1 means block style everwhere */ + flowLevel?: number | undefined; + /** Each tag may have own set of styles. - "tag" => "style" map. */ + styles?: { [x: string]: any } | undefined; + /** specifies a schema to use. */ + schema?: Schema | undefined; + /** if true, sort keys when dumping YAML. If a function, use the function to sort the keys. (default: false) */ + sortKeys?: boolean | ((a: any, b: any) => number) | undefined; + /** set max line width. (default: 80) */ + lineWidth?: number | undefined; + /** if true, don't convert duplicate objects into references (default: false) */ + noRefs?: boolean | undefined; + /** if true don't try to be compatible with older yaml versions. Currently: don't quote "yes", "no" and so on, as required for YAML 1.1 (default: false) */ + noCompatMode?: boolean | undefined; + /** + * if true flow sequences will be condensed, omitting the space between `key: value` or `a, b`. Eg. `'[a,b]'` or `{a:{b:c}}`. + * Can be useful when using yaml for pretty URL query params as spaces are %-encoded. (default: false). + */ + condenseFlow?: boolean | undefined; + /** strings will be quoted using this quoting style. If you specify single quotes, double quotes will still be used for non-printable characters. (default: `'`) */ + quotingType?: "'" | "\"" | undefined; + /** if true, all non-key strings will be quoted even if they normally don't need to. (default: false) */ + forceQuotes?: boolean | undefined; + /** callback `function (key, value)` called recursively on each key/value in source object (see `replacer` docs for `JSON.stringify`). */ + replacer?: ((key: string, value: any) => any) | undefined; + } + + export interface TypeConstructorOptions { + kind?: "sequence" | "scalar" | "mapping" | undefined; + resolve?: ((data: any) => boolean) | undefined; + construct?: ((data: any, type?: string) => any) | undefined; + instanceOf?: object | undefined; + predicate?: ((data: object) => boolean) | undefined; + represent?: ((data: object) => any) | { [x: string]: (data: object) => any } | undefined; + representName?: ((data: object) => any) | undefined; + defaultStyle?: string | undefined; + multi?: boolean | undefined; + styleAliases?: { [x: string]: any } | undefined; + } + + export interface SchemaDefinition { + implicit?: Type[] | undefined; + explicit?: Type[] | undefined; + } + + /** only strings, arrays and plain objects: http://www.yaml.org/spec/1.2/spec.html#id2802346 */ + export let FAILSAFE_SCHEMA: Schema; + /** only strings, arrays and plain objects: http://www.yaml.org/spec/1.2/spec.html#id2802346 */ + export let JSON_SCHEMA: Schema; + /** same as JSON_SCHEMA: http://www.yaml.org/spec/1.2/spec.html#id2804923 */ + export let CORE_SCHEMA: Schema; + /** all supported YAML types */ + export let DEFAULT_SCHEMA: Schema; + + export interface Mark { + buffer: string; + column: number; + line: number; + name: string; + position: number; + snippet: string; + } + + export class YAMLException extends Error { + constructor(reason?: string, mark?: Mark); + + toString(compact?: boolean): string; + + name: string; + + reason: string; + + message: string; + + mark: Mark; + } +} + +declare module "js-yaml" { + export = jsyaml; +} diff --git a/package-lock.json b/package-lock.json index d0b958ef..b3c2bf52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "font-awesome": "^4.7.0", "golden-layout": "^1.5.9", "jquery": "^3.5.0", + "js-yaml": "^4.1.0", "jstree": "^3.3.4", "kaitai-struct": "next", "kaitai-struct-compiler": "next", @@ -738,18 +739,21 @@ "dev": true }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/jstree": { "version": "3.3.14", "resolved": "https://registry.npmjs.org/jstree/-/jstree-3.3.14.tgz", @@ -1343,6 +1347,19 @@ "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" } }, + "node_modules/tslint/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/tsutils": { "version": "2.29.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", diff --git a/package.json b/package.json index e4791322..677d671a 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "font-awesome": "^4.7.0", "golden-layout": "^1.5.9", "jquery": "^3.5.0", + "js-yaml": "^4.1.0", "jstree": "^3.3.4", "kaitai-struct": "next", "kaitai-struct-compiler": "next", diff --git a/src/Playground.ts b/src/Playground.ts index 74d25326..09b152a1 100644 --- a/src/Playground.ts +++ b/src/Playground.ts @@ -1,6 +1,6 @@ import KaitaiStructCompiler = require("kaitai-struct-compiler"); import KaitaiStream = require("KaitaiStream"); -import { YAML } from "yamljs"; +import * as jsyaml from "js-yaml"; import { TemplateCompiler, ITemplateSchema } from "./worker/TemplateCompiler"; import { ExpressionParser } from "./worker/ExpressionLanguage/ExpressionParser"; @@ -31,8 +31,8 @@ async function run() { const ksyContent = await (await fetch("template_compiler/test.ksy")).text(); const templateContent = await (await fetch("template_compiler/test.kcy.yaml")).text(); - const ksy = YAML.parse(ksyContent, null, null, true); - const kcy = YAML.parse(templateContent); + const ksy = jsyaml.load(ksyContent, { schema: jsyaml.CORE_SCHEMA }); + const kcy = jsyaml.load(templateContent, { schema: jsyaml.CORE_SCHEMA }); const compiledTemplate = TemplateCompiler.compileTemplateSchema(kcy); console.log("compiledTemplate", compiledTemplate); diff --git a/src/v1/KaitaiServices.ts b/src/v1/KaitaiServices.ts index 1538d6a8..d19aee0d 100644 --- a/src/v1/KaitaiServices.ts +++ b/src/v1/KaitaiServices.ts @@ -1,6 +1,7 @@ import { fss, IFsItem } from "./app.files"; import { performanceHelper } from "./utils/PerformanceHelper"; import KaitaiStructCompiler = require("kaitai-struct-compiler"); +import * as jsyaml from "js-yaml"; class SchemaUtils { static ksyNameToJsName(ksyName: string, isProp: boolean) { @@ -62,7 +63,7 @@ class JsImporter implements IYamlImporter { const sourceAppendix = mode === 'abs' ? 'kaitai.io' : 'local storage'; let ksyContent; try { - ksyContent = await fss[importedFsType].get(`${loadFn}.ksy`); + ksyContent = await fss[importedFsType].get(fn); } catch (e) { const error = new Error(`failed to import spec ${fn} from ${sourceAppendix}${e.message ? ': ' + e.message : ''}`); @@ -78,11 +79,11 @@ class JsImporter implements IYamlImporter { }; throw error; } - const ksyModel = YAML.parse(ksyContent); + const ksyModel = parseYaml(ksyContent, fn); Object.assign(this.ksyTypes, SchemaUtils.collectKsyTypes(ksyModel)); // we have to modify the schema (add typesByJsName for example) before sending into the compiler, so we need a copy - const compilerSchema = YAML.parse(ksyContent); + const compilerSchema = parseYaml(ksyContent, fn); return compilerSchema; } } @@ -100,11 +101,11 @@ export class CompilerService { var perfYamlParse = performanceHelper.measureAction("YAML parsing"); try { - this.ksySchema = YAML.parse(srcYaml); + this.ksySchema = parseYaml(srcYaml, srcYamlFsItem.fn); this.ksyTypes = SchemaUtils.collectKsyTypes(this.ksySchema); // we have to modify the schema (add typesByJsName for example) before sending into the compiler, so we need a copy - var compilerSchema = YAML.parse(srcYaml); + var compilerSchema = parseYaml(srcYaml, srcYamlFsItem.fn); } catch (parseErr) { return Promise.reject(new CompilationError("yaml", parseErr)); } @@ -132,3 +133,11 @@ export class CompilerService { } } } + +function parseYaml(yamlContents: string, filename: string) { + const options = { + schema: jsyaml.CORE_SCHEMA, + filename: filename, + }; + return jsyaml.load(yamlContents, options); +} diff --git a/vendor.yaml b/vendor.yaml index 42f5b253..ec2ad6aa 100644 --- a/vendor.yaml +++ b/vendor.yaml @@ -183,6 +183,15 @@ libs: npmDir: kaitai-struct files: [LICENSE, KaitaiStream.js] + js-yaml: + source: https://github.com/nodeca/js-yaml + licenseName: MIT + licenseUrl: https://github.com/nodeca/js-yaml/blob/master/LICENSE + npmDir: js-yaml + files: [LICENSE, dist/js-yaml.min.js] + + # FIXME: remove when no longer referenced by src/KaitaiSandbox.ts and src/worker/ImportLoader.ts + # (see https://github.com/kaitai-io/kaitai_struct_webide/issues/168) yaml.js: source: https://github.com/jeremyfa/yaml.js licenseName: MIT diff --git a/vendor_build.js b/vendor_build.js index 2c3d515f..f051ded9 100644 --- a/vendor_build.js +++ b/vendor_build.js @@ -1,5 +1,5 @@ -const YAML = require("yamljs"); -const { copyFileSync, readdirSync, statSync, mkdirSync } = require("fs"); +const jsyaml = require("js-yaml"); +const { readFileSync, copyFileSync, readdirSync, statSync, mkdirSync } = require("fs"); const { join, basename, dirname } = require("path"); const firstBy = require("thenby"); @@ -28,7 +28,9 @@ function copyOverwrite(src, dst) { } function main() { - const vendor = YAML.load("vendor.yaml"); + const filename = "vendor.yaml"; + const vendorYaml = readFileSync(filename, "utf8"); + const vendor = jsyaml.load(vendorYaml, { schema: jsyaml.CORE_SCHEMA, filename }); const sortedLibs = Object.entries(vendor["libs"]).sort( firstBy(([, lib]) => lib["priority"]) ); diff --git a/vendor_license.js b/vendor_license.js index 42b1c96b..0f9421a5 100644 --- a/vendor_license.js +++ b/vendor_license.js @@ -1,4 +1,4 @@ -const YAML = require("yamljs"); +const jsyaml = require("js-yaml"); const { readdirSync, readFileSync, writeFileSync, statSync } = require("fs"); const { join, basename } = require("path"); const firstBy = require("thenby"); @@ -15,7 +15,9 @@ function findLicenses(dst) { } function main() { - const vendor = YAML.load("vendor.yaml"); + const filename = "vendor.yaml"; + const vendorYaml = readFileSync(filename, "utf8"); + const vendor = jsyaml.load(vendorYaml, { schema: jsyaml.CORE_SCHEMA, filename }); let licResult = ""; let wikiResult = "# 3rd-party libraries\n\n"; const sortedLibs = Object.entries(vendor["libs"]).sort(