really rough outline for an import inliner
diff --git a/.gitignore b/.gitignore
index e979170..fa7fb67 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
 # Don’t commit the following directories created by pub.
 .pub
-build/
+^build/
 packages
 
 # Or the files created by dart2js.
diff --git a/lib/build/import_inliner.dart b/lib/build/import_inliner.dart
new file mode 100644
index 0000000..a1692d2
--- /dev/null
+++ b/lib/build/import_inliner.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library web_components.build.import_inliner;
+
+import 'dart:async';
+import 'package:html5lib/dom.dart' show Document, Element, Node;
+
+abstract class ImportReader {
+  Future<Document> readImport(Element import);
+}
+
+class ImportInliner {
+  final ImportReader _importReader;
+
+  ImportInliner(this._importReader);
+
+  // TODO(jakemac): Dedupe imports based on location
+  // TODO(jakemac): Normalize paths in attributes when inlining
+  Future<Document> inlineImports(Document document,
+        [Element importsWrapper, bool inPlace = true]) {
+    if (importsWrapper == null) {
+      importsWrapper = new Element.html('<div style="display:none;"></div>');
+    }
+    // Copy document if not editing in place.
+    if (!inPlace) document = document.clone(true);
+
+    var imports = document.querySelectorAll('link[rel="import"]');
+    var done = Future.wait(imports.map(
+        (import) => _inlineImport(document, importsWrapper, import)));
+    return done.then((_) {
+      // Insert the importsWrapper element at top of body if we had any imports.
+      if (importsWrapper.hasChildNodes()) {
+        document.body.insertBefore(importsWrapper, document.body.firstChild);
+      }
+      return document;
+    });
+  }
+
+  Future _inlineImport(Document document, Element importsWrapper,
+                       Element import) {
+    return _importReader.readImport(import).then((importedDocument) {
+      // Create copies of the imports we find, don't modify them in place.
+      return inlineImports(importedDocument, importsWrapper, false).then((_) {
+        for (var node in importedDocument.body.nodes) {
+          importsWrapper.append(node.clone(true));
+        }
+        import.remove();
+      });
+    });
+  }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 4f21a81..591c856 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -9,6 +9,8 @@
   standard tag. Shadow DOM is designed to provide encapsulation for custom
   elements, by hiding DOM subtrees under shadow roots. HTML Imports let authors
   bundle code and HTML as if they were libraries.
+dependencies:
+  html5lib: '>=0.12.0 <0.13.0'
 dev_dependencies:
   unittest: '>0.11.0 <0.12.0'
   browser: '>0.10.0 <0.11.0'
diff --git a/test/build/import_inliner_test.dart b/test/build/import_inliner_test.dart
new file mode 100644
index 0000000..2a3ef17
--- /dev/null
+++ b/test/build/import_inliner_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library web_components.test.build.import_inliner_test;
+
+import 'dart:async';
+import 'package:web_components/build/import_inliner.dart';
+import 'package:unittest/compact_vm_config.dart';
+import 'package:unittest/unittest.dart';
+import 'package:html5lib/parser.dart';
+import 'package:html5lib/dom.dart' show Document, Element;
+
+main() {
+  useCompactVMConfiguration();
+
+  testInline('basic inlining', '''
+      <html>
+        <body>
+          <link rel="import" href="foo.html">
+        </body>
+      </html>''', {
+        'foo.html': '<div>bar</div>'
+      }, '''
+      <html>
+        <head></head>
+        <body>
+          <div style="display:none;">
+              <div>bar</div>
+          </div>
+        </body>
+      </html>'''
+  );
+}
+
+class MapImportReader implements ImportReader {
+  Map<String, Document> _imports;
+  MapImportReader(this._imports);
+
+  Future<Document> readImport(Element import) {
+    return new Future.value(_imports[import.attributes['href']]);
+  }
+}
+
+void testInline(String name, String input, Map<String, String> dependencies,
+                String expectedOutput, {String reason}) {
+  var inputDoc = parse(input);
+  var dependencyDocs = new Map<String, Document>();
+  dependencies.forEach((k, v) => dependencyDocs[k] = parse(v));
+  var importReader = new MapImportReader(dependencyDocs);
+  var importInliner = new ImportInliner(importReader);
+
+  importInliner.inlineImports(inputDoc);
+
+  test(name, () {
+    expect(
+        inputDoc.outerHtml.replaceAll('  ', '').replaceAll('\n', ''),
+        expectedOutput.replaceAll('  ', '').replaceAll('\n', ''),
+        reason: reason);
+  });
+}