The paragraphs of the license, each as a LicenseParagraph
consisting of
a string and some formatting information. Paragraphs can include newline
characters, but this is discouraged as it results in ugliness.
Source
@override Iterable<LicenseParagraph> get paragraphs sync* { int lineStart = 0; int currentPosition = 0; int lastLineIndent = 0; int currentLineIndent = 0; int currentParagraphIndentation; _LicenseEntryWithLineBreaksParserState state = _LicenseEntryWithLineBreaksParserState.beforeParagraph; List<String> lines = <String>[]; void addLine() { assert(lineStart < currentPosition); lines.add(text.substring(lineStart, currentPosition)); } LicenseParagraph getParagraph() { assert(lines.isNotEmpty); assert(currentParagraphIndentation != null); final LicenseParagraph result = new LicenseParagraph(lines.join(' '), currentParagraphIndentation); assert(result.text.trimLeft() == result.text); assert(result.text.isNotEmpty); lines.clear(); return result; } while (currentPosition < text.length) { switch (state) { case _LicenseEntryWithLineBreaksParserState.beforeParagraph: assert(lineStart == currentPosition); switch (text[currentPosition]) { case ' ': lineStart = currentPosition + 1; currentLineIndent += 1; state = _LicenseEntryWithLineBreaksParserState.beforeParagraph; break; case '\n': case '\f': if (lines.isNotEmpty) yield getParagraph(); lastLineIndent = 0; currentLineIndent = 0; currentParagraphIndentation = null; lineStart = currentPosition + 1; state = _LicenseEntryWithLineBreaksParserState.beforeParagraph; break; case '[': // This is a bit of a hack for the LGPL 2.1, which does something like this: // // [this is a // single paragraph] // // ...near the top. currentLineIndent += 1; continue startParagraph; startParagraph: default: if (lines.isNotEmpty && currentLineIndent > lastLineIndent) { yield getParagraph(); currentParagraphIndentation = null; } // The following is a wild heuristic for guessing the indentation level. // It happens to work for common variants of the BSD and LGPL licenses. if (currentParagraphIndentation == null) { if (currentLineIndent > 10) currentParagraphIndentation = LicenseParagraph.centeredIndent; else currentParagraphIndentation = currentLineIndent ~/ 3; } state = _LicenseEntryWithLineBreaksParserState.inParagraph; } break; case _LicenseEntryWithLineBreaksParserState.inParagraph: switch (text[currentPosition]) { case '\n': addLine(); lastLineIndent = currentLineIndent; currentLineIndent = 0; lineStart = currentPosition + 1; state = _LicenseEntryWithLineBreaksParserState.beforeParagraph; break; case '\f': addLine(); yield getParagraph(); lastLineIndent = 0; currentLineIndent = 0; currentParagraphIndentation = null; lineStart = currentPosition + 1; state = _LicenseEntryWithLineBreaksParserState.beforeParagraph; break; default: state = _LicenseEntryWithLineBreaksParserState.inParagraph; } break; } currentPosition += 1; } switch (state) { case _LicenseEntryWithLineBreaksParserState.beforeParagraph: if (lines.isNotEmpty) yield getParagraph(); break; case _LicenseEntryWithLineBreaksParserState.inParagraph: addLine(); yield getParagraph(); break; } }