-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Introducing Plotly.validate(data, layout) #697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e94eec3
9814edf
0b3040b
a5bc7fe
6c1938c
d304864
877077b
1958dc6
f620a22
a2c52fe
ad8db59
09ed024
a2f2160
54a6ed0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,16 +99,14 @@ exports.valObjects = { | |
// TODO 'values shouldn't be in there (edge case: 'dash' in Scatter) | ||
otherOpts: ['dflt', 'noBlank', 'strict', 'arrayOk', 'values'], | ||
coerceFunction: function(v, propOut, dflt, opts) { | ||
if(opts.strict === true && typeof v !== 'string') { | ||
propOut.set(dflt); | ||
return; | ||
} | ||
if(typeof v !== 'string') { | ||
var okToCoerce = (typeof v === 'number'); | ||
|
||
var s = String(v); | ||
if(v === undefined || (opts.noBlank === true && !s)) { | ||
propOut.set(dflt); | ||
if(opts.strict === true || !okToCoerce) propOut.set(dflt); | ||
else propOut.set(String(v)); | ||
} | ||
else propOut.set(s); | ||
else if(opts.noBlank && !v) propOut.set(dflt); | ||
else propOut.set(v); | ||
} | ||
}, | ||
color: { | ||
|
@@ -162,11 +160,11 @@ exports.valObjects = { | |
subplotid: { | ||
description: [ | ||
'An id string of a subplot type (given by dflt), optionally', | ||
'followed by an integer >1. e.g. if dflt=\'geo\', we can have', | ||
'followed by an integer >1. e.g. if dflt=\'geo\', we can have', | ||
'\'geo\', \'geo2\', \'geo3\', ...' | ||
].join(' '), | ||
requiredOpts: [], | ||
otherOpts: ['dflt'], | ||
requiredOpts: ['dflt'], | ||
otherOpts: [], | ||
coerceFunction: function(v, propOut, dflt) { | ||
var dlen = dflt.length; | ||
if(typeof v === 'string' && v.substr(0, dlen) === dflt && | ||
|
@@ -175,6 +173,18 @@ exports.valObjects = { | |
return; | ||
} | ||
propOut.set(dflt); | ||
}, | ||
validateFunction: function(v, opts) { | ||
var dflt = opts.dflt, | ||
dlen = dflt.length; | ||
|
||
if(v === dflt) return true; | ||
if(typeof v !== 'string') return false; | ||
if(v.substr(0, dlen) === dflt && idRegex.test(v.substr(dlen))) { | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
}, | ||
flaglist: { | ||
|
@@ -239,6 +249,22 @@ exports.valObjects = { | |
} | ||
|
||
propOut.set(vOut); | ||
}, | ||
validateFunction: function(v, opts) { | ||
if(!Array.isArray(v)) return false; | ||
|
||
var items = opts.items; | ||
|
||
if(v.length !== items.length) return false; | ||
|
||
// valid when all items are valid | ||
for(var i = 0; i < items.length; i++) { | ||
var isItemValid = exports.validate(v[i], opts.items[i]); | ||
|
||
if(!isItemValid) return false; | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
}; | ||
|
@@ -309,3 +335,22 @@ exports.coerceFont = function(coerce, attr, dfltObj) { | |
|
||
return out; | ||
}; | ||
|
||
exports.validate = function(value, opts) { | ||
var valObject = exports.valObjects[opts.valType]; | ||
|
||
if(opts.arrayOk && Array.isArray(value)) return true; | ||
|
||
if(valObject.validateFunction) { | ||
return valObject.validateFunction(value, opts); | ||
} | ||
|
||
var failed = {}, | ||
out = failed, | ||
propMock = { set: function(v) { out = v; } }; | ||
|
||
// 'failed' just something mutable that won't be === anything else | ||
|
||
valObject.coerceFunction(value, propMock, failed, opts); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so the failed = {}
out = failed
coerce(() => out = v)
out !== failed dance is just checking to see if if propMock is fired by checking to see if the exising There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would something like
also work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. Because we want coerced values to be considered valid. For example, Lib.validate('1', { valType: 'number' }); // => true even though In other words, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right makes sense |
||
return out !== failed; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexcjohnson I chose to write a
validateFunction
for the'subplotid'
val type (only'subplotid'
and'info_array'
now havevalidateFunction
).This felt like (1) less of a hassle than adding a
base
option and (2) less hacky than trying to patch intoLib.validate
. I hope you're ok with ⏫ .There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you made the right call. As long as there are good tests, which it looks like you added 🎉