diff --git a/engine/Story.js b/engine/Story.js index 3ce71c50..8b24e40b 100644 --- a/engine/Story.js +++ b/engine/Story.js @@ -1045,19 +1045,47 @@ export class Story extends InkObject{ if (typeof this._externals[funcName] === 'undefined') console.warn("Function '" + funcName + "' has not been bound."); delete this._externals[funcName]; } - ValidateExternalBindings(containerOrObject){ + ValidateExternalBindings(containerOrObject, missingExternals){ if (!containerOrObject){ - this.ValidateExternalBindings(this._mainContentContainer); + var missingExternals = []; + this.ValidateExternalBindings(this._mainContentContainer, missingExternals); this._hasValidatedExternals = true; + + // No problem! Validation complete + if( missingExternals.length == 0 ) { + this._hasValidatedExternals = true; + } + + // Error for all missing externals + else { + var message = "Missing function binding for external"; + message += (missingExternals.length > 1) ? "s" : ""; + message += ": '"; + message += missingExternals.join("', '"); + message += "' "; + message += (this.allowExternalFunctionFallbacks) ? ", and no fallback ink function found." : " (ink fallbacks disabled)"; + + var errorPreamble = "ERROR: "; + if (this._mainContentContainer.debugMetadata) { + errorPreamble += "'" + this._mainContentContainer.debugMetadata.fileName + "'"; + errorPreamble += " line "; + errorPreamble += this._mainContentContainer.debugMetadata.startLineNumber; + errorPreamble += ": "; + + message = errorPreamble + message; + } + + this.Error(message); + } } else if (containerOrObject instanceof Container){ var c = containerOrObject; c.content.forEach(innerContent => { - this.ValidateExternalBindings(innerContent); + this.ValidateExternalBindings(innerContent, missingExternals); }); for (var key in c.namedContent){ - this.ValidateExternalBindings(c.namedContent[key]); + this.ValidateExternalBindings(c.namedContent[key], missingExternals); } } else{ @@ -1065,7 +1093,7 @@ export class Story extends InkObject{ //the following code is already taken care of above in this implementation // var container = o as Container; // if (container) { -// ValidateExternalBindings (container); +// ValidateExternalBindings (container, missingExternals); // return; // } @@ -1075,22 +1103,13 @@ export class Story extends InkObject{ var name = divert.targetPathString; if (!this._externals[name]) { - - var fallbackFunction = this.mainContentContainer.namedContent[name]; - var fallbackFound = typeof fallbackFunction !== 'undefined'; - - var message = null; - if (!this.allowExternalFunctionFallbacks) - message = "Missing function binding for external '" + name + "' (ink fallbacks disabled)"; - else if( !fallbackFound ) { - message = "Missing function binding for external '" + name + "', and no fallback ink function found."; - } - - if (message != null){ - var errorPreamble = "ERROR: "; - //misses a bit about metadata, which isn't implemented - - throw new StoryException(errorPreamble + message); + if( this.allowExternalFunctionFallbacks ) { + var fallbackFound = !!this.mainContentContainer.namedContent[name]; + if( !fallbackFound ) { + missingExternals.push(name); + } + } else { + missingExternals.push(name); } } } @@ -1156,15 +1175,18 @@ export class Story extends InkObject{ // Expected to be global story, knot or stitch // var flowContainer = ContentAtPath (path) as Container; var flowContainer = this.ContentAtPath(path); - - // First element of the above constructs is a compiled weave -// var innerWeaveContainer = flowContainer.content [0] as Container; - var innerWeaveContainer = flowContainer.content[0]; + while(true) { + var firstContent = flowContainer.content[0]; + if (firstContent instanceof Container) + flowContainer = firstContent; + else break; + } + // Any initial tag objects count as the "main tags" associated with that story/knot/stitch var tags = null; - innerWeaveContainer.content.every(c => { + flowContainer.content.every(c => { // var tag = c as Runtime.Tag; var tag = c; if (tag instanceof Tag) { diff --git a/engine/Tag.js b/engine/Tag.js index 78fd43ba..5494cd82 100644 --- a/engine/Tag.js +++ b/engine/Tag.js @@ -1,5 +1,8 @@ -export class Tag{ +import {Object as InkObject} from './Object'; + +export class Tag extends InkObject{ constructor(tagText){ + super(); this._text = tagText.toString() || ''; } get text(){ diff --git a/test/simple.js b/test/simple.js index 8db7071e..68682318 100644 --- a/test/simple.js +++ b/test/simple.js @@ -10,6 +10,8 @@ var rl = readline.createInterface({ var inkFile = fs.readFileSync(__dirname + '/stories/test.ink.json', 'UTF-8').replace(/^\uFEFF/, ''); var s = new Story(inkFile); +console.log(s.globalTags); + //console.log(s.BuildStringOfHierarchy()); //console.log(s.EvaluateFunction('describe_health', [50], true));