From eacbf38fabaa2f86fb65877fd97f8a473bb8db96 Mon Sep 17 00:00:00 2001 From: Lars Trieloff Date: Fri, 6 Dec 2019 07:33:28 +0000 Subject: [PATCH] feat(proxy): generate slugs --- lib/schemaProxy.js | 25 +++++++++++++++++++++++-- test/schemaProxy.test.js | 27 +++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/lib/schemaProxy.js b/lib/schemaProxy.js index c2c693d5..aad374ef 100644 --- a/lib/schemaProxy.js +++ b/lib/schemaProxy.js @@ -9,16 +9,21 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ +const ghslugger = require('github-slugger'); + const symbols = { pointer: Symbol('pointer'), filename: Symbol('filename'), id: Symbol('id'), titles: Symbol('titles'), resolve: Symbol('resolve'), + slug: Symbol('slug'), }; +const myslug = Symbol('myslug'); + const handler = ({ - root = '', filename = '.', schemas, parent, + root = '', filename = '.', schemas, parent, slugger, }) => { const meta = {}; @@ -56,6 +61,19 @@ const handler = ({ } }; + meta[symbols.slug] = (target, prop, receiver) => { + if (!receiver[myslug] && !parent && receiver[symbols.filename]) { + receiver[myslug] = slugger.slug(receiver[symbols.filename].replace(/\..*$/, '')); + } + if (!receiver[myslug]) { + const parentslug = parent[symbols.slug]; + const title = receiver.title; + const name = receiver[symbols.pointer].split('/').pop(); + receiver[myslug] = slugger.slug(parentslug + '-' + (title ? title : name)); + } + return receiver[myslug]; + }; + return { ownKeys: target => Reflect.ownKeys(target), @@ -84,6 +102,7 @@ const handler = ({ parent: receiver, filename, schemas, + slugger, })); if (subschema.$id) { @@ -108,8 +127,10 @@ module.exports.loader = () => { known: {}, }; + const slugger = ghslugger(); + return (schema, filename) => { - const proxied = new Proxy(schema, handler({ filename, schemas })); + const proxied = new Proxy(schema, handler({ filename, schemas, slugger })); schemas.loaded.push(proxied); if (proxied.$id) { // stow away the schema for lookup diff --git a/test/schemaProxy.test.js b/test/schemaProxy.test.js index 91fbbb63..baeef083 100644 --- a/test/schemaProxy.test.js +++ b/test/schemaProxy.test.js @@ -13,7 +13,7 @@ const assert = require('assert'); const { - loader, pointer, filename, id, titles, resolve, + loader, pointer, filename, id, titles, resolve, slug, } = require('../lib/schemaProxy'); const example = { @@ -48,6 +48,10 @@ const example = { type: 'object', title: 'An object', }, + zup: { + type: 'object', + title: 'An object', + }, baz: { anyOf: [ { $ref: '#/properties/foo' }, @@ -60,6 +64,7 @@ const example = { const referencing = { $schema: 'http://json-schema.org/draft-06/schema#', $id: 'https://example.com/schemas/referencing', + title: 'Referencing', properties: { $ref: 'https://example.com/schemas/example#/properties', zap: { @@ -142,7 +147,25 @@ describe('Testing Schema Proxy', () => { assert.deepStrictEqual(new Set(Object.keys(proxied2.properties)), new Set([ '$ref', 'zap', // the two properties from the original declaration - 'foo', 'bar', 'zip', 'baz', // plus all the referenced properties + 'foo', 'bar', 'zip', 'zup', 'baz', // plus all the referenced properties ])); }); + + it('Schema proxy generates unique names', () => { + const myloader = loader(); + const proxied1 = myloader(example, 'example.schema.json'); + const proxied2 = myloader(referencing, 'referencing.schema.json'); + const proxied3 = myloader({ + title: 'Referencing' + }, 'anotherreference.schema.json'); + + assert.equal(proxied1[slug], 'example'); + + assert.equal(proxied1.properties.zip[slug], 'example-properties-an-object'); + assert.equal(proxied1.properties.zup[slug], 'example-properties-an-object-1'); //avoid duplicates + + assert.equal(proxied2[slug], 'referencing'); + assert.equal(proxied2[slug], 'referencing'); // make sure the slug stays stable + assert.equal(proxied3[slug], 'anotherreference'); + }); });