From 105e6533e1cd3d86322238c6c08361fd5a6c12b4 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 16 Sep 2019 09:32:58 -0400 Subject: [PATCH 1/3] Tooling is now portable and the linter passes --- .gitignore | 3 ++- assets/grid.js | 4 ++-- build.js | 5 +++-- package.json | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 28f1ba75..f854f3fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -.DS_Store \ No newline at end of file +.DS_Store +package-lock.json diff --git a/assets/grid.js b/assets/grid.js index 0bede361..396a6600 100644 --- a/assets/grid.js +++ b/assets/grid.js @@ -7,11 +7,11 @@ $.getJSON('assets/data.json', function (data) { var img = $('', { 'class': 'hex', 'src': val.raster, - 'alt': val.description, + 'alt': val.description }) $('', { - 'href': "http://hexb.in/" + val.filename, + 'href': 'http://hexb.in/' + val.filename, 'target': '_blank' }).append(img).appendTo('#grid') }) diff --git a/build.js b/build.js index 5c04bd6c..5f71e7b0 100644 --- a/build.js +++ b/build.js @@ -10,6 +10,7 @@ glob('meta/*.json', function (err, files) { file.filename = f data.push(file) }) - + fs.writeFileSync(__dirname + '/assets/data.json', JSON.stringify(data, null, ' ')) -}) \ No newline at end of file +}) + diff --git a/package.json b/package.json index 32d6df16..77b9c54b 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "description": "hexagon directory", "main": "grid.js", "scripts": { - "build": "node build.js && browserify assets/grid.js -o assets/bundle.js", - "test": "standard", - "start": "wzrd assets/grid.js:assets/bundle.js" + "build": "node build.js && ./node_modules/.bin/browserify assets/grid.js -o assets/bundle.js", + "test": "./node_modules/.bin/standard", + "start": "./node_module/.bin/wzrd assets/grid.js:assets/bundle.js" }, "author": "max ogden", "license": "BSD", From 380a5cf00c96fb8ab9727a055d2e84edb218904f Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 16 Sep 2019 13:17:14 -0400 Subject: [PATCH 2/3] metadata verification script created - needs cleanup before switching to error over warning --- verify.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 verify.js diff --git a/verify.js b/verify.js new file mode 100644 index 00000000..f38b1385 --- /dev/null +++ b/verify.js @@ -0,0 +1,31 @@ +var fs = require('fs'); +var glob = require('glob'); +var assert = require('assert'); + +var REQUIRED_FIELDS = ['name', 'author', 'license', 'vector', 'raster']; +var OPTIONAL_FIELDS = ['description', 'order_online_url'] + +glob('meta/*.json', function (err, files) { + if (err) throw err + files.forEach(function (f) { + var file = JSON.parse(fs.readFileSync(f)); + var fields = Object.keys(file); + REQUIRED_FIELDS.forEach(function (requiredField) { + if(fields.indexOf(requiredField) === -1) { + console.warn(`Warning: Missing required field ${requiredField} in ${f}`) + } + // assert.ok(fields.indexOf(requiredField) !== -1, `Missing required field ${requiredField} in ${f}`) + }) + fields.forEach(function (field) { + if (REQUIRED_FIELDS.indexOf(field) === -1) { + if (OPTIONAL_FIELDS.indexOf(field) === -1) { + console.warn(`Warning: ${field} is not a required or optional field: ${f}`) + } + } + }) + if (file['name'].match(/[^a-z\d-]/) !== null) { + console.warn(`Warning: Invalid 'name' field value '${file['name']}' in ${f}, only alphanumeric characters and hyphens are allowed`); + } + // assert.ok(fields['name'].match(/[^\w\d-]/) !== null, `Invalid 'name' field value '${fields['name']}' in ${f}, only alphanumeric characters and hyphens are allowed`) + }) +}) From fc82a362c5b494483f159982fdcdedf78c0b9773 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 16 Sep 2019 14:02:25 -0400 Subject: [PATCH 3/3] finish verification script --- verify.js | 66 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/verify.js b/verify.js index f38b1385..c2d09451 100644 --- a/verify.js +++ b/verify.js @@ -1,31 +1,73 @@ -var fs = require('fs'); -var glob = require('glob'); -var assert = require('assert'); +var fs = require('fs') +var glob = require('glob') -var REQUIRED_FIELDS = ['name', 'author', 'license', 'vector', 'raster']; +var REQUIRED_FIELDS = ['name', 'author', 'license', 'vector', 'raster'] var OPTIONAL_FIELDS = ['description', 'order_online_url'] glob('meta/*.json', function (err, files) { if (err) throw err files.forEach(function (f) { - var file = JSON.parse(fs.readFileSync(f)); - var fields = Object.keys(file); + var file = JSON.parse(fs.readFileSync(f)) + var fields = Object.keys(file) + + /** + * Rule: all required fields must be defined + */ REQUIRED_FIELDS.forEach(function (requiredField) { - if(fields.indexOf(requiredField) === -1) { - console.warn(`Warning: Missing required field ${requiredField} in ${f}`) + if (fields.indexOf(requiredField) === -1) { + console.warn(`Warning: ${f}: Missing required field ${requiredField}`) } - // assert.ok(fields.indexOf(requiredField) !== -1, `Missing required field ${requiredField} in ${f}`) + // FIXME: Some entries lack required fields (particularly `vector`) }) + + /** + * Rule: only required and optional fields may appear + */ fields.forEach(function (field) { if (REQUIRED_FIELDS.indexOf(field) === -1) { if (OPTIONAL_FIELDS.indexOf(field) === -1) { - console.warn(`Warning: ${field} is not a required or optional field: ${f}`) + console.warn(`Warning: ${f}: ${field} is not a required or optional field.`) + // FIXME: Some entries have extra fields (particularly `filename`) } } }) + + /** + * Rule: `name` must be a slug: lowercase alphanumeric plus hyphen only + */ if (file['name'].match(/[^a-z\d-]/) !== null) { - console.warn(`Warning: Invalid 'name' field value '${file['name']}' in ${f}, only alphanumeric characters and hyphens are allowed`); + var properSlug = file['name'].toLowerCase().replace(/[^a-z\d-]+/g, '-') + console.warn(`Warning: ${f}: Invalid 'name' field value '${file['name']}', only alphanumeric characters and hyphens are allowed. Suggested value: '${properSlug}'`) + // FIXME: Many entries have improper `name` fields. + } + + /** + * Rule: `vector` and `raster` images should exist and be relative to `hexb.in` + * FIXME: Maybe make this hosting-neutral + * FIXME: Vectors are missing, some are invalid. + */ + // 'http://hexb.in/hexagons/' == 24 characters + // 'http://hexb.in/vector/' == 22 characters + // 'http://hexb.in/' == 15 characters + var rasterUrl = file.raster ? file.raster.slice(0, 24) : '' + var vectorUrl = file.vector ? file.vector.slice(0, 22) : '' + var rasterPath = file.raster ? file.raster.slice(15) : '' + var vectorPath = file.vector ? file.vector.slice(15) : '' + if (rasterUrl !== 'http://hexb.in/hexagons/') { + console.warn(`Warning: ${f}: 'raster' image '${file.raster}' must begin with 'http://hexb.in/hexagons/'`) + } + try { + fs.statSync(rasterPath) + } catch (e) { + console.warn(`Warning: ${f}: Couldn't find raster image at '${rasterPath}': ${e}`) + } + if (vectorUrl !== 'http://hexb.in/vector/') { + console.warn(`Warning: ${f}: 'vector' image '${file.vector}' must begin with 'http://hexb.in/vector/'`) + } + try { + fs.statSync(vectorPath) + } catch (e) { + console.warn(`Warning: ${f}: Couldn't find vector image at '${vectorPath}': ${e}`) } - // assert.ok(fields['name'].match(/[^\w\d-]/) !== null, `Invalid 'name' field value '${fields['name']}' in ${f}, only alphanumeric characters and hyphens are allowed`) }) })