This commit is contained in:
thosakwe 2017-08-13 00:24:38 -04:00
parent 05a90aee60
commit 1ab6e34449
12 changed files with 315 additions and 1 deletions

44
.gitignore vendored
View file

@ -10,3 +10,47 @@ pubspec.lock
# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
doc/api/
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

17
.idea/markdown.iml Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/packages" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Dart Packages" level="project" />
</component>
</module>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/markdown.iml" filepath="$PROJECT_DIR$/.idea/markdown.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="server.dart" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true" nameIsGenerated="true">
<option name="filePath" value="$PROJECT_DIR$/example/server.dart" />
<option name="workingDirectory" value="$PROJECT_DIR$/example" />
<method />
</configuration>
</component>

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

1
.travis.yml Normal file
View file

@ -0,0 +1 @@
language: dart

View file

@ -1,2 +1,97 @@
# markdown
Markdown view generator for Angel.
[![Pub](https://img.shields.io/pub/v/angel_markdown.svg)](https://pub.dartlang.org/packages/angel_markdown)
Markdown view generator for Angel.
With this plug-in, you can easily serve
static sites without doing more than writing simple Markdown. Thus, it is a friendly
choice for writing API documentation or other tedious HTML-writing tasks.
# Installation
In your `pubspec.yaml`:
```yaml
dependencies:
angel_framework: ^1.0.0
angel_markdown: ^1.0.0
```
# Usage
It's very straightforward to configure an Angel server to use Markdown:
```dart
configureServer(Angel app) async {
await app.configure(markdown(
// The directory where your views are located.
new Directory('views'),
));
}
```
You can then generate HTML on-the-fly in a request handler.
Assuming your view directory contained a file named `hello.md`, the
following would render it as an HTML response:
```dart
configureServer(Angel app) async {
app.get('/hello', (res) => res.render('hello'));
}
```
`package:angel_markdown` by default searches for files with a `.md` extension; however,
you can easily override this.
## Interpolation
`angel_markdown` can interpolate the values of data from `locals` before building the Markdown.
For example, with the following template `species.md`:
```markdown
# Species: {{species.name}}
The species *{{species.genus.name}} {{species.name}}* is fascinating...
```
You can render as follows:
```dart
requestHandler(ResponseContext res) {
return res.render('species', {
'species': new Species('sapiens', genius: 'homo')
});
}
```
To disable interpolation for a single bracket, prefix it with an `@`, ex: `@{{raw | not_interpolated | angular}}`.
## Templates
Markdown is frequently used to build the *content* of sites, but not the templates.
You might want to wrap the content of pages in a custom template to apply pretty
CSS and JS, etc:
```dart
configureServer(Angel app) async {
await app.configure(
markdown(
// The directory where your views are located.
new Directory('views'), template: (content, Map locals) {
return '''<!DOCTYPE html>
<html>
<head>
<title>${locals['title']} - My Site</title>
</head>
<body>
$content
</body>
</html>
''';
}),
);
}
```
The `template` function will have access to whatever values were passed to the renderer,
or an empty `Map`.
## Enhancing Markdown
You can pass an `extensionSet` to add additional features to the Markdown renderer.
By default, this plug-in configures it to enable Github-flavored Markdown.

2
analysis_options.yaml Normal file
View file

@ -0,0 +1,2 @@
analyzer:
strong-mode: true

44
example/server.dart Normal file
View file

@ -0,0 +1,44 @@
import 'dart:async';
import 'dart:io';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_markdown/angel_markdown.dart';
main() async {
var app = await createServer();
var server = await app.startServer(InternetAddress.LOOPBACK_IP_V4, 3000);
print('Listening at http://${server.address.address}:${server.port}');
}
Future<Angel> createServer() async {
// Create a new server, and install the Markdown renderer.
var app = new Angel();
await app
.configure(markdown(new Directory('views'), template: (content, locals) {
return '''
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>${locals['title'] ?? 'Example Site'} - Example Site</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.min.css">
</head>
<body>
<div class="ui top fixed menu">
<a class="header item" href="/">
<i class="home icon"></i>
Home
</a>
</div>
<div class="ui container" style="margin-top: 5em;">
$content
</div>
</body>
</html>
''';
}));
// Compile a landing page
app.get('/', (res) => res.render('hello', {'title': 'Welcome'}));
return app;
}

9
example/views/hello.md Normal file
View file

@ -0,0 +1,9 @@
# Welcome
Welcome to a *simple* Markdown-gen site!
Do you mind **starring** the
[Angel repository](https://github.com/angel-dart/angel)?
```
Look, a code block!!!
```

68
lib/angel_markdown.dart Normal file
View file

@ -0,0 +1,68 @@
import 'dart:async';
import 'dart:io';
import 'dart:mirrors';
import 'package:angel_framework/angel_framework.dart';
import 'package:markdown/markdown.dart';
final RegExp _braces = new RegExp(r'@?{{((\\})|([^}]))+}}');
/// Configures an [Angel] instance to render Markdown templates from the specified [viewsDirectory].
///
/// The default [extension] is `.md`. To search for a different file extension, provide a new one.
/// By default, an [extensionSet] is provided that renders Github-flavored Markdown. This can also be overridden.
///
/// In many cases, Markdown content will be rendered within a larger [template] that styles the entire website.
/// To wrap generated Markdown content in a template, provide a function that accepts a generated HTML String,
/// and returns a String, or a `Future<String>`.
AngelConfigurer markdown(
Directory viewsDirectory, {
String extension,
ExtensionSet extensionSet,
FutureOr<String> template(String content, Map locals),
}) {
extension ??= '.md';
extensionSet ?? ExtensionSet.gitHub;
return (Angel app) async {
app.viewGenerator = (String name, [Map locals]) async {
var file =
new File.fromUri(viewsDirectory.uri.resolve('$name$extension'));
var contents = await file.readAsString();
contents = contents.replaceAllMapped(_braces, (m) {
var text = m[0];
if (text.startsWith('@')) {
// Raw braces
return text.substring(1);
} else {
var expr = m[1];
var split = expr.split('.');
var root = split[0];
if (!locals?.containsKey(root) == true)
throw new UnimplementedError(
'Expected a local named "$root", but none was provided. Expression text: "$text"');
return _resolveDotNotation(split, locals[root]).toString();
}
});
var html = markdownToHtml(contents, extensionSet: extensionSet);
if (template != null) html = await template(html, locals ?? {});
return html;
};
};
}
_resolveDotNotation(List<String> split, target) {
if (split.length == 1) return target;
InstanceMirror mirror = reflect(target);
for (int i = 1; i < split.length; i++) {
mirror = mirror.getField(new Symbol(split[i]));
}
return mirror.reflectee;
}

13
pubspec.yaml Normal file
View file

@ -0,0 +1,13 @@
name: angel_markdown
version: 1.0.0
description: Markdown view generator for Angel.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/markdown
environment:
sdk: ">=1.19.0"
dependencies:
angel_framework: ^1.0.0
markdown: ^0.11.4
dev_dependencies:
angel_test: ^1.0.0
test: ^0.12.0