| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /// Convenience methods wrapped up in a class to pull down the docgen viewer for | |
| 6 /// a viewable website, and start up a server for viewing. | |
| 7 library docgen.viewer; | |
| 8 | |
| 9 import 'dart:io'; | |
| 10 | |
| 11 import 'package:path/path.dart' as path; | |
| 12 | |
| 13 import 'generator.dart' as gen; | |
| 14 import 'package_helpers.dart' show rootDirectory; | |
| 15 | |
| 16 final String _dartdocViewerString = | |
| 17 path.join(Directory.current.path, 'dartdoc-viewer'); | |
| 18 | |
| 19 final Directory _dartdocViewerDir = new Directory(_dartdocViewerString); | |
| 20 | |
| 21 Directory _topLevelTempDir; | |
| 22 Directory _webDocsDir; | |
| 23 bool _movedViewerCode = false; | |
| 24 | |
| 25 void createViewer(bool serve) { | |
| 26 _clone(); | |
| 27 _compile(); | |
| 28 if (serve) { | |
| 29 _runServer(); | |
| 30 } | |
| 31 } | |
| 32 | |
| 33 /* | |
| 34 * dartdoc-viewer currently has the web app code under a 'client' directory | |
| 35 * | |
| 36 * This is confusing for folks that want to clone and modify the code. | |
| 37 * It also includes a number of python files and other content related to | |
| 38 * app engine hosting that are not needed. | |
| 39 * | |
| 40 * This logic exists to support the current model and a (future) updated | |
| 41 * dartdoc-viewer repo where the 'client' content exists at the root of the | |
| 42 * project and the other content is removed. | |
| 43 */ | |
| 44 String get _viewerCodePath { | |
| 45 if (_viewerCodePathCache == null) { | |
| 46 var pubspecFileName = 'pubspec.yaml'; | |
| 47 | |
| 48 var thePath = _dartdocViewerDir.path; | |
| 49 | |
| 50 if (!FileSystemEntity.isFileSync(path.join(thePath, pubspecFileName))) { | |
| 51 thePath = path.join(thePath, 'client'); | |
| 52 if (!FileSystemEntity.isFileSync(path.join(thePath, pubspecFileName))) { | |
| 53 throw new StateError('Could not find a pubspec file'); | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 _viewerCodePathCache = thePath; | |
| 58 } | |
| 59 return _viewerCodePathCache; | |
| 60 } | |
| 61 String _viewerCodePathCache; | |
| 62 | |
| 63 /// If our dartdoc-viewer code is already checked out, move it to a temporary | |
| 64 /// directory outside of the package directory, so we don't try to process it | |
| 65 /// for documentation. | |
| 66 void ensureMovedViewerCode() { | |
| 67 // TODO(efortuna): This will need to be modified to run on anyone's package | |
| 68 // outside of the checkout! | |
| 69 if (_dartdocViewerDir.existsSync()) { | |
| 70 _topLevelTempDir = new Directory(rootDirectory).createTempSync(); | |
| 71 _dartdocViewerDir.renameSync(_topLevelTempDir.path); | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 /// Move the dartdoc-viewer code back into place for "webpage deployment." | |
| 76 void addBackViewerCode() { | |
| 77 if (_movedViewerCode) _dartdocViewerDir.renameSync(_dartdocViewerString); | |
| 78 } | |
| 79 | |
| 80 /// Serve up our generated documentation for viewing in a browser. | |
| 81 void _clone() { | |
| 82 // If the viewer code is already there, then don't clone again. | |
| 83 if (_dartdocViewerDir.existsSync()) { | |
| 84 _moveDirectoryAndServe(); | |
| 85 } else { | |
| 86 var processResult = Process.runSync('git', ['clone', '-b', 'master', | |
| 87 'https://github.com/dart-lang/dartdoc-viewer.git'], runInShell: true); | |
| 88 | |
| 89 if (processResult.exitCode == 0) { | |
| 90 /// Move the generated json/yaml docs directory to the dartdoc-viewer | |
| 91 /// directory, to run as a webpage. | |
| 92 var processResult = Process.runSync(gen.pubScript, ['get'], | |
| 93 runInShell: true, workingDirectory: _viewerCodePath); | |
| 94 print('process output: ${processResult.stdout}'); | |
| 95 print('process stderr: ${processResult.stderr}'); | |
| 96 | |
| 97 var dir = new Directory(gen.outputDirectory == null ? 'docs' : | |
| 98 gen.outputDirectory); | |
| 99 _webDocsDir = new Directory(path.join(_viewerCodePath, 'web', 'docs')); | |
| 100 if (dir.existsSync()) { | |
| 101 // Move the docs folder to dartdoc-viewer/client/web/docs | |
| 102 dir.renameSync(_webDocsDir.path); | |
| 103 } | |
| 104 } else { | |
| 105 print('Error cloning git repository:'); | |
| 106 print('process output: ${processResult.stdout}'); | |
| 107 print('process stderr: ${processResult.stderr}'); | |
| 108 } | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 /// Move the generated json/yaml docs directory to the dartdoc-viewer | |
| 113 /// directory, to run as a webpage. | |
| 114 void _moveDirectoryAndServe() { | |
| 115 var processResult = Process.runSync(gen.pubScript, ['upgrade'], runInShell: | |
| 116 true, workingDirectory: path.join(_dartdocViewerDir.path, 'client')); | |
| 117 print('process output: ${processResult.stdout}'); | |
| 118 print('process stderr: ${processResult.stderr}'); | |
| 119 | |
| 120 var dir = new Directory(gen.outputDirectory == null ? 'docs' : | |
| 121 gen.outputDirectory); | |
| 122 var webDocsDir = new Directory(path.join(_dartdocViewerDir.path, 'client', | |
| 123 'web', 'docs')); | |
| 124 if (dir.existsSync()) { | |
| 125 // Move the docs folder to dartdoc-viewer/client/web/docs | |
| 126 dir.renameSync(webDocsDir.path); | |
| 127 } | |
| 128 | |
| 129 if (webDocsDir.existsSync()) { | |
| 130 // Compile the code to JavaScript so we can run on any browser. | |
| 131 print('Compiling the app to JavaScript.'); | |
| 132 var processResult = Process.runSync(gen.dartBinary, ['deploy.dart'], | |
| 133 workingDirectory: path.join(_dartdocViewerDir.path, 'client'), | |
| 134 runInShell: true); | |
| 135 print('process output: ${processResult.stdout}'); | |
| 136 print('process stderr: ${processResult.stderr}'); | |
| 137 _runServer(); | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 void _compile() { | |
| 142 if (_webDocsDir.existsSync()) { | |
| 143 // Compile the code to JavaScript so we can run on any browser. | |
| 144 print('Compiling the app to JavaScript.'); | |
| 145 var processResult = Process.runSync(gen.dartBinary, ['deploy.dart'], | |
| 146 workingDirectory: _viewerCodePath, runInShell: true); | |
| 147 print('process output: ${processResult.stdout}'); | |
| 148 print('process stderr: ${processResult.stderr}'); | |
| 149 var outputDir = path.join(_viewerCodePath, 'out', 'web'); | |
| 150 print('Docs are available at $outputDir'); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 /// A simple HTTP server. Implemented here because this is part of the SDK, | |
| 155 /// so it shouldn't have any external dependencies. | |
| 156 void _runServer() { | |
| 157 // Launch a server to serve out of the directory dartdoc-viewer/client/web. | |
| 158 HttpServer.bind(InternetAddress.ANY_IP_V6, 8080).then((HttpServer httpServer) | |
| 159 { | |
| 160 print('Server launched. Navigate your browser to: ' | |
| 161 'http://localhost:${httpServer.port}'); | |
| 162 httpServer.listen((HttpRequest request) { | |
| 163 var response = request.response; | |
| 164 var basePath = path.join(_viewerCodePath, 'out', 'web'); | |
| 165 var requestPath = path.join(basePath, request.uri.path.substring(1)); | |
| 166 bool found = true; | |
| 167 var file = new File(requestPath); | |
| 168 if (file.existsSync()) { | |
| 169 // Set the correct header type. | |
| 170 if (requestPath.endsWith('.html')) { | |
| 171 response.headers.set('Content-Type', 'text/html'); | |
| 172 } else if (requestPath.endsWith('.js')) { | |
| 173 response.headers.set('Content-Type', 'application/javascript'); | |
| 174 } else if (requestPath.endsWith('.dart')) { | |
| 175 response.headers.set('Content-Type', 'application/dart'); | |
| 176 } else if (requestPath.endsWith('.css')) { | |
| 177 response.headers.set('Content-Type', 'text/css'); | |
| 178 } | |
| 179 } else { | |
| 180 if (requestPath == basePath) { | |
| 181 response.headers.set('Content-Type', 'text/html'); | |
| 182 file = new File(path.join(basePath, 'index.html')); | |
| 183 } else { | |
| 184 print('Path not found: $requestPath'); | |
| 185 found = false; | |
| 186 response.statusCode = HttpStatus.NOT_FOUND; | |
| 187 response.close(); | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 if (found) { | |
| 192 // Serve up file contents. | |
| 193 file.openRead().pipe(response).catchError((e) { | |
| 194 print('HttpServer: error while closing the response stream $e'); | |
| 195 }); | |
| 196 } | |
| 197 }, onError: (e) { | |
| 198 print('HttpServer: an error occured $e'); | |
| 199 }); | |
| 200 }); | |
| 201 } | |
| OLD | NEW |