API Reference 1.1.0stream_rspc

stream_rspc library

Properties

final Map<String, Tag> tags #

A map of tags that RSP compiler uses to handle the tags.

The name of tag must start with a lower-case letter (a-z), and it can have only letters (a-z and A-Z).

Map<String, Tag> get tags {
 if (_tags == null) {
   _tags = new HashMap();
   for (Tag tag in [new PageTag(), new DartTag(), new HeaderTag(),
     new IncludeTag(), new ForwardTag(), new VarTag(),
     new JsonTag(), new JsonJsTag(), new ScriptTag(),
     new ForTag(), new WhileTag(), new IfTag(), new ElseTag()])
     _tags[tag.name] = tag;
 }
 return _tags;
}

const String VERSION #

const String VERSION = "1.0.0"

Functions

void outMap(TagContext tc, Map<String, String> map) #

Output the given map to the generated Dart file. It will generate something like the following to the Dart file:

{"key1": "value1", "key2": value2_in_EL}

A value can contain EL expressions, such as [=foo_expression]. However, the keys are output directly, so make sure it does not contain invalid characters.

void outMap(TagContext tc, Map<String, String> map) {
 tc.write("{");
 bool first = true;
 for (final key in map.keys) {
   if (first) first = false;
   else tc.write(", ");

   tc.write("'");
   tc.write(key);
   tc.write("': ");
   tc.write(toEL(map[key])); //Rsp.cat can handle nob-string value
 }
 tc.write("}");
}

void outText(TagContext tc, String text, [int line]) #

Output the given text to the generated Dart file. It will generate something like the following to the Dart file:

response.write("$text");

Of course, it will escape the text properly if necessary.

void outText(TagContext tc, String text, [int line]) {
 if (text.isEmpty)
   return; //nothing to do

 tc.write('\n${tc.pre}response.write("""');

 for (int i = 0, len = text.length; i < len; ++i) {
   final cc = text[i];
   if (i == 0 && cc == '\n') {
     tc.write('\n'); //first linefeed is ignored, so we have add one more
   } else if (cc == '"') {
     if (i == len - 1) { //end with "
       tc.write('\\');
     } else if (i + 2 < len && text[i + 1] == '"' && text[i + 2] == '"') {
       tc.write('""\\');
       i += 2;
     }
   } else if (cc == '\\' || cc == '\$') {
     tc.write('\\');
   }
   tc.write(cc);
 }

 tc.writeln('"""); //#${line != null ? line: tc.line}');
}

Map<String, String> parseArgs(String data) #

Parses the given string into a map of arguments. It assumes the string is in the format of: arg0="value0" arg1="value1"

Map<String, String> parseArgs(String data)
=> MapUtil.parse(data, backslash:false, defaultValue:"");

String toEL(String data, {direct: true}) #

Converts the given value to a valid Dart statement.

  • data - the value to convert. It can be null.
  • direct - whether it is OK to return an expression, if any, directly without enclosing with """/ If true and data contains nothing but a single expression, the expression is output directly

String toEL(String data, {direct: true}) {
 if (data == null)
   return direct ? "null": '""';

 final sb = new StringBuffer();
 for (int i = 0, len = data.length; i < len; ++i) {
   final cc = data[i];
   if (cc == '[' && i + 1 < len && data[i + 1] == '=') { //found
     final j = _skipToELEnd(data, i + 2),
         val = data.substring(i + 2, j).trim();
     if (direct && i == 0 && j + 1 == len) //single EL
       return val;
     if (!val.isEmpty)
       sb..write("\${Rsp.nns(")..write(val)..write(")}");

     i = j;
     continue;
   }

   sb.write(cc);
   if (cc == '\\')
     sb.write(data[++i]);
 }
 final val = sb.toString();
 return val.indexOf('"') >= 0 ?
   val.indexOf("'") >= 0 ? '"""$val"""': "'$val'": '"$val"';
}

bool isEL(String data) #

Test if the given value is enclosed with [= ]. If null, false is returned.

bool isEL(String data) {
 for (int i = 0, len = data != null ? data.length: 0; i < len; ++i) {
   final cc = data[i];
   if (cc == '\\')
     ++i;
   else if (cc == '[' && i + 1 < len && data[i + 1] == '=')
     return true;
 }
 return false;
}

bool isValidVarChar(String cc, bool firstChar) #

Test if the given character can be used in a variable name.

bool isValidVarChar(String cc, bool firstChar)
=> StringUtil.isChar(cc, lower: true, upper: true, digit: !firstChar, match:"_\$");

void build(List<String> arguments, {String filenameMapper(String source), Encoding encoding: UTF8, List<String> imports}) #

Compile changed RSP files. This method shall be called within build.dart, with the arguments passed to main() as its arguments.

Notice that it accepts files ending with .rsp.whatever.

  • filenameMapper - returns the filename of the destination file, which must end with .dart. If omitted, it will be generated under the webapp folder with the same path structure.

  • imports - additional imported packages, such as ["package:foo/foo.dart"].
void build(List<String> arguments, {String filenameMapper(String source),
   Encoding encoding: UTF8, List<String> imports}) {
 final ArgParser argParser = new ArgParser()
   ..addOption("changed", allowMultiple: true)
   ..addOption("removed", allowMultiple: true)
   ..addFlag("clean", negatable: false)
   ..addFlag("machine", negatable: false)
   ..addFlag("full", negatable: false);

 final ArgResults args = argParser.parse(arguments);
 final List<String> changed = args["changed"];
 final List<String> removed = args["removed"];
 final bool clean = args["clean"];
 
 if (clean) { // clean only
   Directory.current.list(recursive: true).listen((fse) {
     if (fse is File && fse.path.endsWith(".rsp.dart"))
       fse.delete();
   });

 } else if (removed.isEmpty && changed.isEmpty) { // full build
   Directory.current.list(recursive: true).listen((fse) {
     if (fse is File && _rspSource(fse.path) >= 0)
       compileFile(fse.path, encoding: encoding,
         destinationName: filenameMapper != null ? filenameMapper(fse.path): null,
         imports: imports);
   });

 } else {
   for (String name in removed) {
     final i = _rspSource(name);
     if (i >= 0) {
       final File gen = new File("${name.substring(0, i)}dart");
       if (gen.existsSync())
         gen.delete();
     }
   }

   for (String name in changed) {
     if (_rspSource(name) >= 0)
       compileFile(name, encoding: encoding,
         destinationName: filenameMapper != null ? filenameMapper(name): null,
         imports: imports);
   }
 }
}

void compileFile(String sourceName, {String destinationName, bool verbose: false, Encoding encoding: UTF8, List<String> imports}) #

Compiles the RSP document of the given sourceName and write the result to the file of given destinationName.

  • imports - additional imported packages, such as ["package:foo/foo.dart"].
void compileFile(String sourceName, {String destinationName, bool verbose : false, 
   Encoding encoding : UTF8, List<String> imports}) {
 final source = new File(sourceName);
 if (!source.existsSync()) {
   print("File not found: ${sourceName}");
   return;
 }

 File dest;
 if (destinationName == null) {
   final int i = sourceName.lastIndexOf('.');
   final int j = sourceName.lastIndexOf('/');
   destinationName = i >= 0 && j < i ? "${sourceName.substring(0, i + 1)}dart" : "${sourceName}.dart";
   dest = _locate(destinationName);
 } else {
   dest = new File(destinationName);
 }

 if (Path.normalize(source.path) == Path.normalize(dest.path)) {
   print("Source and destination are the same file, $source");
   return;
 }

 if (verbose) {
   final int i = dest.path.lastIndexOf('/') + 1;
   print("Compile ${source.path} to ${i > 0 ? dest.path.substring(i) : dest.path}");
 }
 
 source.readAsString(encoding: encoding).then((String text) {
   final out = dest.openWrite(encoding: encoding);
   try {
     compile(text, out, sourceName: sourceName,
         destinationName: _unipath(dest.path), //force to use '/' even in Windows
         encoding: encoding, verbose: verbose, imports: imports);
   } on SyntaxError catch (e) {
     print("${e.message}\nCompilation aborted.");
   } finally {
     out.close();
   }
 });
}

void compile(String source, IOSink out, {String sourceName, String destinationName, Encoding encoding: UTF8, bool verbose: false, List<String> imports}) #

Compiles the given source RSP document to the given output stream out. Notice that the caller has to close the output stream by himself.

  • imports - additional imported packages, such as ["package:foo/foo.dart"].
void compile(String source, IOSink out, {String sourceName, String destinationName,
   Encoding encoding: UTF8, bool verbose: false, List<String> imports}) {
 new Compiler(source, out, sourceName: sourceName, destinationName: destinationName,
     encoding: encoding, verbose: verbose, imports: imports).compile();
}

void main(List<String> arguments) #

The entry point of RSP compiler.

void main(List<String> arguments) {
 final env = new _Environ();
 if (!_parseArgs(arguments, env))
   return;

 for (final String name in env.sources)
   compileFile(name, encoding: env.encoding, verbose: env.verbose);
}

Abstract Classes

Tag

Classes

Exceptions