Given a normalized list with component names and params like: ['user', {id: 3 }]
generates a url with a leading slash relative to the provided parentComponent
.
If the optional param _aux
is true
, then we generate starting at an auxiliary
route boundary.
Source
Instruction generate( List<dynamic> linkParams, List<Instruction> ancestorInstructions, [_aux = false]) { var params = splitAndFlattenLinkParams(linkParams); var prevInstruction; // The first segment should be either '.' (generate from parent) or '' (generate from root). // When we normalize above, we strip all the slashes, './' becomes '.' and '/' becomes ''. if (params.first == "") { params.removeAt(0); prevInstruction = ancestorInstructions.first; ancestorInstructions = []; } else { prevInstruction = ancestorInstructions.length > 0 ? ancestorInstructions.removeLast() : null; if (params.first == ".") { params.removeAt(0); } else if (params.first == "..") { while (params.first == "..") { if (ancestorInstructions.length <= 0) { throw new BaseException( '''Link "$linkParams" has too many "../" segments.'''); } prevInstruction = ancestorInstructions.removeLast(); params = params.sublist(1); } } else { // we must only peak at the link param, and not consume it var routeName = params.first; var parentComponentType = this._rootComponent; var grandparentComponentType; if (ancestorInstructions.length > 1) { var parentComponentInstruction = ancestorInstructions[ancestorInstructions.length - 1]; var grandComponentInstruction = ancestorInstructions[ancestorInstructions.length - 2]; parentComponentType = parentComponentInstruction.component.componentType; grandparentComponentType = grandComponentInstruction.component.componentType; } else if (ancestorInstructions.length == 1) { parentComponentType = ancestorInstructions[0].component.componentType; grandparentComponentType = this._rootComponent; } // For a link with no leading `./`, `/`, or `../`, we look for a sibling and child. // If both exist, we throw. Otherwise, we prefer whichever exists. var childRouteExists = this.hasRoute(routeName, parentComponentType); var parentRouteExists = grandparentComponentType != null && this.hasRoute(routeName, grandparentComponentType); if (parentRouteExists && childRouteExists) { var msg = '''Link "$linkParams" is ambiguous, use "./" or "../" to disambiguate.'''; throw new BaseException(msg); } if (parentRouteExists) { prevInstruction = ancestorInstructions.removeLast(); } } } if (params[params.length - 1] == "") { params.removeLast(); } if (params.length > 0 && params[0] == "") { params.removeAt(0); } if (params.length < 1) { var msg = '''Link "$linkParams" must include a route name.'''; throw new BaseException(msg); } var generatedInstruction = this._generate( params, ancestorInstructions, prevInstruction, _aux, linkParams); // we don't clone the first (root) element for (var i = ancestorInstructions.length - 1; i >= 0; i--) { var ancestorInstruction = ancestorInstructions[i]; if (ancestorInstruction == null) { break; } generatedInstruction = ancestorInstruction.replaceChild(generatedInstruction); } return generatedInstruction; }