summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--platform/darwin/scripts/update-examples.js152
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.h17
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.h12
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.h17
-rw-r--r--platform/darwin/src/MGLRasterSource.h15
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.h10
-rw-r--r--platform/darwin/src/MGLShapeSource.h14
-rw-r--r--platform/darwin/src/MGLStyleLayer.h.ejs7
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h17
-rw-r--r--platform/darwin/src/MGLVectorSource.h15
-rw-r--r--platform/darwin/src/MGLVectorStyleLayer.h20
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift (renamed from platform/ios/test/MGLDocumentationExampleTests.swift)123
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.m8
-rw-r--r--platform/darwin/test/MGLStyleTests.mm49
-rw-r--r--platform/darwin/test/one-liner.json1
-rw-r--r--platform/ios/DEVELOPING.md16
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj39
-rw-r--r--platform/ios/jazzy.yml2
-rw-r--r--platform/ios/scripts/add-examples-to-docs.js65
-rwxr-xr-xplatform/ios/scripts/document.sh5
-rw-r--r--platform/macos/DEVELOPING.md26
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj8
23 files changed, 437 insertions, 205 deletions
diff --git a/Makefile b/Makefile
index 29acc367f4..b1ceeb74b6 100644
--- a/Makefile
+++ b/Makefile
@@ -275,6 +275,10 @@ idocument:
style-code-darwin:
node platform/darwin/scripts/generate-style-code.js
+ node platform/darwin/scripts/update-examples.js
+
+darwin-update-examples:
+ node platform/darwin/scripts/update-examples.js
endif
#### Linux targets #####################################################
diff --git a/platform/darwin/scripts/update-examples.js b/platform/darwin/scripts/update-examples.js
new file mode 100644
index 0000000000..2aeb80e139
--- /dev/null
+++ b/platform/darwin/scripts/update-examples.js
@@ -0,0 +1,152 @@
+'use strict';
+
+const fs = require('fs');
+const execFileSync = require('child_process').execFileSync;
+const _ = require('lodash');
+
+const examplesSrc = fs.readFileSync('platform/darwin/test/MGLDocumentationExampleTests.swift', 'utf8');
+
+// Regex extracts the following block
+// /** Front matter to describe the example. **/
+// func testMGLClass$member() {
+// ...
+// //#-example-code
+// let sampleCode: String?
+// //#-end-example-code
+// ...
+// }
+//
+// into the following regex groups:
+// 1 (test method name): "MGLClass" or "MGLClass$member" or "MGLClass$initWithArg_anotherArg_"
+// 2 (indentation): " "
+// 3 (sample code): "let sampleCode: String?"
+const exampleRegex = /func test([\w$]+)\s*\(\)\s*\{[^]*?\n([ \t]+)\/\/#-example-code\n([^]+?)\n\2\/\/#-end-example-code\n/gm;
+
+/**
+ * Returns the given source with example code inserted into the documentation
+ * comment for the symbol at the given one-based line.
+ *
+ * @param {String} src Source code to insert the example code into.
+ * @param {Number} line One-based line number of the symbol being documented.
+ * @param {String} exampleCode Example code to insert.
+ * @returns {String} `src` with `exampleCode` inserted just above `line`.
+ */
+function completeSymbolInSource(src, line, exampleCode) {
+ // Split the file contents right before the symbol declaration (but after its documentation comment).
+ let srcUpToSymbol = src.split('\n', line - 1).join('\n');
+ let srcFromSymbol = src.substr(srcUpToSymbol.length);
+
+ // Match the documentation comment block that is not followed by the beginning or end of a declaration.
+ let commentMatch = srcUpToSymbol.match(/\/\*\*\s*(?:[^*]|\*(?!\/))+?\s*\*\/[^;{}]*?$/);
+
+ // Replace the Swift code block with the test method’s contents.
+ let completedComment = commentMatch[0].replace(/^([ \t]*)```swift\n[^]*?```/m, function (m, indentation) {
+ // Apply the original indentation to each line.
+ return ('```swift\n' + exampleCode + '\n```').replace(/^/gm, indentation);
+ });
+
+ // Splice the modified comment into the overall file contents.
+ srcUpToSymbol = (srcUpToSymbol.substr(0, commentMatch.index) + completedComment +
+ srcUpToSymbol.substr(commentMatch.index + commentMatch[0].length));
+ return srcUpToSymbol + srcFromSymbol;
+}
+
+let examples = {};
+let match;
+while ((match = exampleRegex.exec(examplesSrc)) !== null) {
+ let testMethodName = match[1],
+ indentation = match[2],
+ exampleCode = match[3];
+
+ // Trim leading whitespace from the example code.
+ exampleCode = exampleCode.replace(new RegExp('^' + indentation, 'gm'), '');
+
+ examples[testMethodName] = exampleCode;
+}
+
+function completeExamples(os) {
+ console.log(`Installing ${os} SDK examples…`);
+
+ let sdk = os === 'iOS' ? 'iphonesimulator' : 'macosx';
+ let sysroot = execFileSync('xcrun', ['--show-sdk-path', '--sdk', sdk]).toString().trim();
+ let umbrellaPath = `platform/${os.toLowerCase()}/src/Mapbox.h`;
+ let docArgs = ['doc', '--objc', umbrellaPath, '--',
+ '-x', 'objective-c', '-I', 'platform/darwin/src/', '-isysroot', sysroot];
+ let docStr = execFileSync('sourcekitten', docArgs).toString().trim();
+ let docJson = JSON.parse(docStr);
+ _.forEach(docJson, function (result) {
+ _.forEach(result, function (structure, path) {
+ let src;
+ let newSrc;
+ // Recursively search for code blocks in documentation comments and populate
+ // them with example code from the test methods. Find and replace the code
+ // blocks in reverse to keep the SourceKitten line numbers accurate.
+ _.forEachRight(structure['key.substructure'], function completeSubstructure(substructure, idx, substructures, symbolPath) {
+ if (!symbolPath) {
+ symbolPath = [substructure['key.name']];
+ }
+ _.forEachRight(substructure['key.substructure'], function (substructure, idx, substructures) {
+ completeSubstructure(substructure, idx, substructures, _.concat(symbolPath, substructure['key.name']));
+ });
+
+ let comment = substructure['key.doc.comment'];
+ if (!comment || !comment.match(/^(?:\s*)```swift\n/m)) {
+ return;
+ }
+
+ // Lazily read in the existing file.
+ if (!src) {
+ newSrc = src = fs.readFileSync(path, 'utf8');
+ }
+
+ // Get the contents of the test method whose name matches the symbol path.
+ let testMethodName = symbolPath.join('$').replace(/$[+-]/, '').replace(/:/g, '_');
+ let example = examples[testMethodName];
+ if (!example) {
+ console.error(`MGLDocumentationExampleTests.${testMethodName}() not found.`);
+ process.exit(1);
+ }
+
+ // Resolve conditional compilation blocks.
+ example = example.replace(/^(\s*)#if\s+os\((iOS|macOS)\)\n([^]*?)(?:^\1#else\n([^]*?))?^\1#endif\n/gm,
+ function (m, indentation, ifOs, ifCase, elseCase) {
+ return (os === ifOs ? ifCase : elseCase).replace(new RegExp('^ ', 'gm'), '');
+ });
+
+ // Insert the test method contents into the documentation comment just
+ // above the substructure.
+ let startLine = substructure['key.parsed_scope.start'];
+ newSrc = completeSymbolInSource(newSrc, startLine, example);
+ });
+
+ if (!src) {
+ return;
+ }
+
+ // Write out the modified file contents.
+ if (src === newSrc) {
+ console.log('Skipping', path);
+ } else {
+ console.log('Updating', path);
+ if (['0', 'false'].indexOf(process.env.DRY_RUN || '0') !== -1) {
+ fs.writeFileSync(path, newSrc);
+ }
+ }
+ });
+ });
+}
+
+function ensureSourceKittenIsInstalled() {
+ try {
+ execFileSync('which', ['sourcekitten']);
+ } catch (e) {
+ console.log(`Installing SourceKitten via Homebrew…`);
+ execFileSync('brew', ['install', 'sourcekitten']);
+ }
+}
+
+ensureSourceKittenIsInstalled();
+
+// Where a particular comment is part of both SDKs, prefer the iOS example.
+completeExamples('macOS');
+completeExamples('iOS');
diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h
index b57e245da2..d2e043e22a 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.h
+++ b/platform/darwin/src/MGLCircleStyleLayer.h
@@ -59,8 +59,21 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) {
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new circle style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
- <!--EXAMPLE: MGLCircleStyleLayer-->
+
+ ### Example
+
+ ```swift
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: population)
+ layer.sourceLayerIdentifier = "population"
+ layer.circleColor = MGLStyleValue(rawValue: .green)
+ layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [
+ 12: MGLStyleValue(rawValue: 2),
+ 22: MGLStyleValue(rawValue: 180)
+ ])
+ layer.circleOpacity = MGLStyleValue(rawValue: 0.7)
+ layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married")
+ mapView.style.addLayer(layer)
+ ```
*/
@interface MGLCircleStyleLayer : MGLVectorStyleLayer
diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h
index 2638e85aa5..184f44ef65 100644
--- a/platform/darwin/src/MGLFillStyleLayer.h
+++ b/platform/darwin/src/MGLFillStyleLayer.h
@@ -37,8 +37,16 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) {
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new fill style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
- <!--EXAMPLE: MGLFillStyleLayer-->
+
+ ### Example
+
+ ```swift
+ let layer = MGLFillStyleLayer(identifier: "parks", source: parks)
+ layer.sourceLayerIdentifier = "parks"
+ layer.fillColor = MGLStyleValue(rawValue: .green)
+ layer.predicate = NSPredicate(format: "type == %@", "national-park")
+ mapView.style.addLayer(layer)
+ ```
*/
@interface MGLFillStyleLayer : MGLVectorStyleLayer
diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h
index c3371aa2a7..f049ae1db1 100644
--- a/platform/darwin/src/MGLLineStyleLayer.h
+++ b/platform/darwin/src/MGLLineStyleLayer.h
@@ -87,8 +87,21 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) {
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new line style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
- <!--EXAMPLE: MGLLineStyleLayer-->
+
+ ### Example
+
+ ```swift
+ let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails)
+ layer.sourceLayerIdentifier = "trails"
+ layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [
+ 14: MGLStyleValue(rawValue: 2),
+ 18: MGLStyleValue(rawValue: 20),
+ ])
+ layer.lineColor = MGLStyleValue(rawValue: .brown)
+ layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round))
+ layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking")
+ mapView.style.addLayer(layer)
+ ```
*/
@interface MGLLineStyleLayer : MGLVectorStyleLayer
diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h
index 3efd84f383..cd95e85c5b 100644
--- a/platform/darwin/src/MGLRasterSource.h
+++ b/platform/darwin/src/MGLRasterSource.h
@@ -35,8 +35,19 @@ extern const MGLTileSourceOption MGLTileSourceOptionTileSize;
`MGLRasterSource` object that you can use to initialize new style layers. You
can also add and remove sources dynamically using methods such as
`-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`.
-
- <!--EXAMPLE: MGLRasterSource-->
+
+ ### Example
+
+ ```swift
+ let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
+ .minimumZoomLevel: 9,
+ .maximumZoomLevel: 16,
+ .tileSize: 512,
+ .attributionInfos: [
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ ]
+ ])
+ mapView.style.addSource(source)
```
*/
@interface MGLRasterSource : MGLTileSource
diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h
index 7b53eebf96..45ab25a8f1 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.h
+++ b/platform/darwin/src/MGLRasterStyleLayer.h
@@ -23,8 +23,14 @@ NS_ASSUME_NONNULL_BEGIN
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new raster style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
- <!--EXAMPLE: MGLRasterStyleLayer-->
+
+ ### Example
+
+ ```swift
+ let layer = MGLRasterStyleLayer(identifier: "clouds", source: source)
+ layer.rasterOpacity = MGLStyleValue(rawValue: 0.5)
+ mapView.style.addLayer(layer)
+ ```
*/
@interface MGLRasterStyleLayer : MGLForegroundStyleLayer
diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h
index 0eb454437b..30e299d2b1 100644
--- a/platform/darwin/src/MGLShapeSource.h
+++ b/platform/darwin/src/MGLShapeSource.h
@@ -74,8 +74,18 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
Any vector style layer initialized with a shape source should have a `nil`
value in its `sourceLayerIdentifier` property.
-
- <!--EXAMPLE: MGLShapeSource-->
+
+ ### Example
+
+ ```swift
+ var coordinates: [CLLocationCoordinate2D] = [
+ CLLocationCoordinate2D(latitude: 37.77, longitude: -122.42),
+ CLLocationCoordinate2D(latitude: 38.91, longitude: -77.04),
+ ]
+ let polyline = MGLPolylineFeature(coordinates: &coordinates, count: UInt(coordinates.count))
+ let shape = MGLShapeCollectionFeature(shapes: [polyline])
+ let source = MGLShapeSource(identifier: "lines", shape: shape, options: nil)
+ mapView.style.addSource(source)
```
*/
@interface MGLShapeSource : MGLSource
diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs
index ac95022ea7..17529b8f9d 100644
--- a/platform/darwin/src/MGLStyleLayer.h.ejs
+++ b/platform/darwin/src/MGLStyleLayer.h.ejs
@@ -67,8 +67,11 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) {
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new <%- type %> style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
- <!--EXAMPLE: MGL<%- camelize(type) %>StyleLayer-->
+
+ ### Example
+
+ ```swift
+ ```
*/
<% } -%>
@interface MGL<%- camelize(type) %>StyleLayer : MGL<%-
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index 052d67617a..ca34698159 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -260,8 +260,21 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new symbol style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
- <!--EXAMPLE: MGLSymbolStyleLayer-->
+
+ ### Example
+
+ ```swift
+ let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois)
+ layer.sourceLayerIdentifier = "pois"
+ layer.iconImageName = MGLStyleValue(rawValue: "coffee")
+ layer.iconScale = MGLStyleValue(rawValue: 0.5)
+ layer.textField = MGLStyleValue(rawValue: "{name}")
+ layer.textTranslate = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0)))
+ layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left))
+ layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left))
+ layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee")
+ mapView.style.addLayer(layer)
+ ```
*/
@interface MGLSymbolStyleLayer : MGLVectorStyleLayer
diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h
index ba8f075b5a..aa867adb6c 100644
--- a/platform/darwin/src/MGLVectorSource.h
+++ b/platform/darwin/src/MGLVectorSource.h
@@ -24,8 +24,19 @@ NS_ASSUME_NONNULL_BEGIN
(<var>extent</var>&nbsp;×&nbsp;2)&nbsp;−&nbsp;1, inclusive. Any vector style
layer initialized with a vector source must have a non-`nil` value in its
`sourceLayerIdentifier` property.
-
- <!--EXAMPLE: MGLVectorSource-->
+
+ ### Example
+
+ ```swift
+ let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
+ .minimumZoomLevel: 9,
+ .maximumZoomLevel: 16,
+ .attributionInfos: [
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ ]
+ ])
+ mapView.style.addSource(source)
+ ```
*/
@interface MGLVectorSource : MGLTileSource
diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h
index 50e56d8643..d33494c3e4 100644
--- a/platform/darwin/src/MGLVectorStyleLayer.h
+++ b/platform/darwin/src/MGLVectorStyleLayer.h
@@ -59,7 +59,10 @@ NS_ASSUME_NONNULL_BEGIN
<li><code>NSContainsPredicateOperatorType</code> (<code>CONTAINS</code>)</li>
</ul>
- To test whether a feature has or lacks a specific attribute, compare the attribute to `NULL` or `NIL`. Predicates created using the `+[NSPredicate predicateWithValue:]` method are also supported. String operators and custom operators are not supported.
+ To test whether a feature has or lacks a specific attribute, compare the
+ attribute to `NULL` or `NIL`. Predicates created using the
+ `+[NSPredicate predicateWithValue:]` method are also supported. String
+ operators and custom operators are not supported.
For details about the predicate format string syntax, consult the “Predicate
Format String Syntax” chapter of the
@@ -130,8 +133,19 @@ NS_ASSUME_NONNULL_BEGIN
style attributes and also `hyphen-minus` and `tag:subtag`. However, you must use
`%K` in the format string to represent these variables:
`@"%K == 'LineString'", @"$type"`.
-
- <!--EXAMPLE: MGLVectorStyleLayer.predicate-->
+
+ ### Example
+
+ To filter the layer to include only the features whose `index` attribute is 5
+ or 10 and whose `ele` attribute is at least 1,500, you could create an
+ `NSCompoundPredicate` along these lines:
+
+ ```swift
+ let layer = MGLLineStyleLayer(identifier: "contour", source: terrain)
+ layer.sourceLayerIdentifier = "contours"
+ layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0")
+ mapView.style.addLayer(layer)
+ ```
*/
@property (nonatomic, nullable) NSPredicate *predicate;
diff --git a/platform/ios/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 0d97cfeb35..9243924328 100644
--- a/platform/ios/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -1,42 +1,54 @@
import XCTest
import Mapbox
-import UIKit
+#if os(iOS)
+ import UIKit
+#else
+ import Cocoa
+#endif
/**
Test cases that ensure the inline examples in the project documentation
compile.
- There is a run script build phase for the dynamic & static iOS targets
- that invokes `/platform/ios/scrips/add-examples-to-docs.js`. This script
- will pull example code out of this test file and replace the corresponding
- placeholder comment in the built header files.
-
- Adding examples:
- 1. Add a test case below
+ To add an example:
+ 1. Add a test case named in the form testMGLClass or testMGLClass$method.
2. Wrap the code you'd like to appear in the documentation within the
following comment blocks:
- `/*---BEGIN EXAMPLE: ExampleToken---*/`
+ ```
+ //#-example-code
...
- `/*---END EXAMPLE---*/`
- 3. Insert a comment `<!--EXAMPLE: ExampleToken-->` inside the header file
- where you'd like the example code to be inserted
+ //#-end-example-code
+ ```
+ 3. Insert an empty Swift code block inside the header file where you'd like the
+ example code to be inserted.
+ 4. Run `make darwin-update-examples` to extract example code from the test
+ method below and insert it into the header.
*/
-class MGLDocumentationExampleTests: XCTestCase {
+class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
var mapView: MGLMapView!
+ var styleLoadingExpectation: XCTestExpectation!
override func setUp() {
super.setUp()
- self.mapView = MGLMapView(frame: CGRect(x: 0, y: 0, width: 256, height: 256))
+ let styleURL = Bundle(for: MGLDocumentationExampleTests.self).url(forResource: "one-liner", withExtension: "json")
+ mapView = MGLMapView(frame: CGRect(x: 0, y: 0, width: 256, height: 256), styleURL: styleURL)
+ mapView.delegate = self
+ styleLoadingExpectation = expectation(description: "Map view should finish loading style")
+ waitForExpectations(timeout: 1, handler: nil)
}
override func tearDown() {
- self.mapView = nil
+ mapView = nil
+ styleLoadingExpectation = nil
super.tearDown()
}
+
+ func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {
+ styleLoadingExpectation.fulfill()
+ }
- // MGLShapeSource
- func testMGLShapeSourceExample() {
- /*---BEGIN EXAMPLE: MGLShapeSource---*/
+ func testMGLShapeSource() {
+ //#-example-code
var coordinates: [CLLocationCoordinate2D] = [
CLLocationCoordinate2D(latitude: 37.77, longitude: -122.42),
CLLocationCoordinate2D(latitude: 38.91, longitude: -77.04),
@@ -45,14 +57,13 @@ class MGLDocumentationExampleTests: XCTestCase {
let shape = MGLShapeCollectionFeature(shapes: [polyline])
let source = MGLShapeSource(identifier: "lines", shape: shape, options: nil)
mapView.style.addSource(source)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.source(withIdentifier: "lines"))
}
- // MGLRasterSource
- func testMGLRasterSourceExample() {
- /*---BEGIN EXAMPLE: MGLRasterSource---*/
+ func testMGLRasterSource() {
+ //#-example-code
let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
@@ -62,14 +73,13 @@ class MGLDocumentationExampleTests: XCTestCase {
]
])
mapView.style.addSource(source)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.source(withIdentifier: "clouds"))
}
- // MGLVectorSource
func testMGLVectorSource() {
- /*---BEGIN EXAMPLE: MGLVectorSource---*/
+ //#-example-code
let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
@@ -78,20 +88,19 @@ class MGLDocumentationExampleTests: XCTestCase {
]
])
mapView.style.addSource(source)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.source(withIdentifier: "pois"))
}
- // MGLCircleStyleLayer
- func testMGLCircleStyleLayerExample() {
+ func testMGLCircleStyleLayer() {
let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style.addSource(population)
- /*---BEGIN EXAMPLE: MGLCircleStyleLayer---*/
+ //#-example-code
let layer = MGLCircleStyleLayer(identifier: "circles", source: population)
layer.sourceLayerIdentifier = "population"
- layer.circleColor = MGLStyleValue(rawValue: UIColor.green)
+ layer.circleColor = MGLStyleValue(rawValue: .green)
layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [
12: MGLStyleValue(rawValue: 2),
22: MGLStyleValue(rawValue: 180)
@@ -99,105 +108,101 @@ class MGLDocumentationExampleTests: XCTestCase {
layer.circleOpacity = MGLStyleValue(rawValue: 0.7)
layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married")
mapView.style.addLayer(layer)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.layer(withIdentifier: "circles"))
}
- // MGLLineStyleLayer
- func testMGLLineStyleLayerExample() {
+ func testMGLLineStyleLayer() {
let trails = MGLVectorSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style.addSource(trails)
- /*---BEGIN EXAMPLE: MGLLineStyleLayer---*/
+ //#-example-code
let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails)
layer.sourceLayerIdentifier = "trails"
layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [
14: MGLStyleValue(rawValue: 2),
18: MGLStyleValue(rawValue: 20),
])
- layer.lineColor = MGLStyleValue(rawValue: UIColor.brown)
+ layer.lineColor = MGLStyleValue(rawValue: .brown)
layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round))
layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking")
mapView.style.addLayer(layer)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.layer(withIdentifier: "trails-path"))
}
- // MGLFillStyleLayer
- func testMGLFillStyleLayerExample() {
+ func testMGLFillStyleLayer() {
let parks = MGLVectorSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style.addSource(parks)
- /*---BEGIN EXAMPLE: MGLFillStyleLayer---*/
+ //#-example-code
let layer = MGLFillStyleLayer(identifier: "parks", source: parks)
layer.sourceLayerIdentifier = "parks"
- layer.fillColor = MGLStyleValue(rawValue: UIColor.green)
+ layer.fillColor = MGLStyleValue(rawValue: .green)
layer.predicate = NSPredicate(format: "type == %@", "national-park")
mapView.style.addLayer(layer)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.layer(withIdentifier: "parks"))
}
- // MGLSymbolStyleLayer
- func testMGLSymbolStyleLayerExample() {
+ func testMGLSymbolStyleLayer() {
let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style.addSource(pois)
- /*---BEGIN EXAMPLE: MGLSymbolStyleLayer---*/
+ //#-example-code
let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois)
layer.sourceLayerIdentifier = "pois"
layer.iconImageName = MGLStyleValue(rawValue: "coffee")
layer.iconScale = MGLStyleValue(rawValue: 0.5)
layer.textField = MGLStyleValue(rawValue: "{name}")
- layer.textTranslate = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0)))
+ #if os(macOS)
+ var vector = CGVector(dx: 10, dy: 0)
+ layer.textTranslate = MGLStyleValue(rawValue: NSValue(bytes: &vector, objCType: "{CGVector=dd}"))
+ #else
+ layer.textTranslate = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0)))
+ #endif
layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left))
layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left))
layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee")
mapView.style.addLayer(layer)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.layer(withIdentifier: "coffeeshops"))
}
- // MGLRasterStyleLayer
func testMGLRasterStyleLayer() {
let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.tileSize: 512,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
]
])
mapView.style.addSource(source)
- /*---BEGIN EXAMPLE: MGLRasterStyleLayer---*/
+ //#-example-code
let layer = MGLRasterStyleLayer(identifier: "clouds", source: source)
layer.rasterOpacity = MGLStyleValue(rawValue: 0.5)
mapView.style.addLayer(layer)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.layer(withIdentifier: "clouds"))
}
- // MGLVectorStyleLayer.predicate
- func testMGLVectorStyleLayer() {
+ func testMGLVectorStyleLayer$predicate() {
let terrain = MGLVectorSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style.addSource(terrain)
- /*---BEGIN EXAMPLE: MGLVectorStyleLayer.predicate---*/
- /**
- To create a filter with the logic `(index == 10 || index == 5) && ele >= 200`,
- you could create a predicate using `NSCompoundPredicate` along these lines:
- */
+ //#-example-code
let layer = MGLLineStyleLayer(identifier: "contour", source: terrain)
layer.sourceLayerIdentifier = "contours"
- layer.predicate = NSPredicate(format: "(index == 10 || index == 5) && ele >= 1500.0")
+ layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0")
mapView.style.addLayer(layer)
- /*---END EXAMPLE---*/
+ //#-end-example-code
XCTAssertNotNil(mapView.style.layer(withIdentifier: "contour"))
}
diff --git a/platform/darwin/test/MGLStyleLayerTests.m b/platform/darwin/test/MGLStyleLayerTests.m
index 590d6eda7f..66bdc0df0b 100644
--- a/platform/darwin/test/MGLStyleLayerTests.m
+++ b/platform/darwin/test/MGLStyleLayerTests.m
@@ -10,6 +10,7 @@
- (void)setUp {
[super setUp];
+ [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
#if TARGET_OS_IPHONE
UIApplication *app = [UIApplication sharedApplication];
UIViewController *vc = [[UIViewController alloc] init];
@@ -19,12 +20,17 @@
[vc.view addSubview:_mapView];
_mapView.delegate = self;
#else
- [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:@"MGLStyleLayerTests" owner:self];
[windowController showWindow:nil];
#endif
}
+- (void)tearDown {
+ _mapView = nil;
+
+ [super tearDown];
+}
+
- (void)testPropertyName:(NSString *)name isBoolean:(BOOL)isBoolean {
NS_MUTABLE_ARRAY_OF(NSString *) *components = [name componentsSeparatedByString:@"-"].mutableCopy;
if (isBoolean) {
diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm
index 55a5df08ca..bcad7ab508 100644
--- a/platform/darwin/test/MGLStyleTests.mm
+++ b/platform/darwin/test/MGLStyleTests.mm
@@ -1,3 +1,4 @@
+#import "MGLAccountManager.h"
#import "MGLMapView.h"
#import "MGLStyle_Private.h"
#import "MGLOpenGLStyleLayer.h"
@@ -36,9 +37,19 @@
- (void)setUp {
[super setUp];
-
+
+ [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
self.mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
- self.style = [[MGLStyle alloc] initWithMapView:self.mapView];
+}
+
+- (void)tearDown {
+ self.mapView = nil;
+
+ [super tearDown];
+}
+
+- (MGLStyle *)style {
+ return self.mapView.style;
}
- (void)testUnversionedStyleURLs {
@@ -174,18 +185,18 @@
- (void)testAddingLayersWithDuplicateIdentifiers {
//Just some source
MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
- [self.mapView.style addSource: source];
+ [self.style addSource: source];
//Add initial layer
MGLFillStyleLayer *initial = [[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source];
- [self.mapView.style addLayer:initial];
+ [self.style addLayer:initial];
//Try to add the duplicate
- XCTAssertThrowsSpecificNamed([self.mapView.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException");
- XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException");
- XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException");
- XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException");
- XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"my-layer"] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException");
+ XCTAssertThrowsSpecificNamed([self.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException");
+ XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException");
+ XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException");
+ XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException");
+ XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"my-layer"] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException");
}
- (NSString *)stringWithContentsOfStyleHeader {
@@ -209,8 +220,8 @@
#endif
XCTAssertNotNil(image);
- [self.mapView.style setImage:image forName:imageName];
- MGLImage *styleImage = [self.mapView.style imageForName:imageName];
+ [self.style setImage:image forName:imageName];
+ MGLImage *styleImage = [self.style imageForName:imageName];
XCTAssertNotNil(styleImage);
XCTAssertEqual(image.size.width, styleImage.size.width);
@@ -218,29 +229,27 @@
}
- (void)testLayersOrder {
- [self.mapView setStyleURL:[MGLStyle streetsStyleURLWithVersion:8]];
-
NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"];
NSURL *url = [NSURL fileURLWithPath:filePath];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil];
- [self.mapView.style addSource:source];
+ [self.style addSource:source];
MGLCircleStyleLayer *layer1 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer1" source:source];
- [self.mapView.style addLayer:layer1];
+ [self.style addLayer:layer1];
MGLCircleStyleLayer *layer3 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer3" source:source];
- [self.mapView.style addLayer:layer3];
+ [self.style addLayer:layer3];
MGLCircleStyleLayer *layer2 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer2" source:source];
- [self.mapView.style insertLayer:layer2 aboveLayer:layer1];
+ [self.style insertLayer:layer2 aboveLayer:layer1];
MGLCircleStyleLayer *layer4 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer4" source:source];
- [self.mapView.style insertLayer:layer4 aboveLayer:layer3];
+ [self.style insertLayer:layer4 aboveLayer:layer3];
MGLCircleStyleLayer *layer0 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer0" source:source];
- [self.mapView.style insertLayer:layer0 belowLayer:layer1];
+ [self.style insertLayer:layer0 belowLayer:layer1];
- NSArray<MGLStyleLayer *> *layers = [self.mapView.style layers];
+ NSArray<MGLStyleLayer *> *layers = [self.style layers];
XCTAssert([[layers[0] identifier] isEqualToString:layer0.identifier]);
XCTAssert([[layers[1] identifier] isEqualToString:layer1.identifier]);
diff --git a/platform/darwin/test/one-liner.json b/platform/darwin/test/one-liner.json
new file mode 100644
index 0000000000..23c546181f
--- /dev/null
+++ b/platform/darwin/test/one-liner.json
@@ -0,0 +1 @@
+{"version":8,"sources":{},"layers":[]} \ No newline at end of file
diff --git a/platform/ios/DEVELOPING.md b/platform/ios/DEVELOPING.md
index 94ff49ee1b..f7bc0cc415 100644
--- a/platform/ios/DEVELOPING.md
+++ b/platform/ios/DEVELOPING.md
@@ -118,6 +118,22 @@ To add a localization to the iOS SDK:
1. In the Project navigator, expand each .strings and .stringsdict file in the project. An additional version for your localization should be listed; translate it. Translate everything on the right side of the equals sign. Leave the left side and any comments unmodified. See Apple’s documentation on the [.strings](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html) and [.stringsdict](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html) formats.
1. You’re already most of the way towards localizing the macOS SDK too – consider [completing that localization](../macos/DEVELOPING.md#adding-a-localization).
+### Adding a code example
+
+To add an example code listing to the documentation for a class or class member:
+
+1. Add a test method named in the form `testMGLClass` or `testMGLClass$method`
+ to [MGLDocumentationExampleTests](test/MGLDocumentationExampleTests.swift).
+ Wrap the code you’d like to appear in the documentation within
+ `//#-example-code` and `//#-end-example-code` comments.
+1. Insert the code listings into the headers:
+
+```bash
+make darwin-update-examples
+```
+
+[SourceKitten](https://github.com/jpsim/SourceKitten/) is required and will be installed automatically using Homebrew.
+
## Testing
`make ios-test` builds and runs unit tests of cross-platform code as well as the SDK.
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index ebcf3a55cb..8d96bcf497 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -228,6 +228,7 @@
DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA35A2CB1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */; };
DA35A2CC1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */; };
+ DA35D0881E1A6309007DED41 /* one-liner.json in Resources */ = {isa = PBXBuildFile; fileRef = DA35D0871E1A6309007DED41 /* one-liner.json */; };
DA6408DB1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA6408DC1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */; };
@@ -617,7 +618,7 @@
554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
55D8C9941D0F133500F42F10 /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/ios/config.xcconfig; sourceTree = "<group>"; };
55D8C9951D0F18CE00F42F10 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
- 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLDocumentationExampleTests.swift; sourceTree = "<group>"; };
+ 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = "<group>"; };
7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolyline+MGLAdditions.h"; sourceTree = "<group>"; };
7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolyline+MGLAdditions.m"; sourceTree = "<group>"; };
7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = "<group>"; };
@@ -669,6 +670,7 @@
DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLAdditions.h"; sourceTree = "<group>"; };
DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+MGLAdditions.m"; sourceTree = "<group>"; };
DA35A2D11CCAB25200E826B2 /* jazzy.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = jazzy.yml; sourceTree = "<group>"; };
+ DA35D0871E1A6309007DED41 /* one-liner.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "one-liner.json"; path = "../../darwin/test/one-liner.json"; sourceTree = "<group>"; };
DA4A26961CB6E795000B7809 /* Mapbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorStyleLayer.h; sourceTree = "<group>"; };
DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLVectorStyleLayer.m; sourceTree = "<group>"; };
@@ -1110,6 +1112,7 @@
DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */,
DA2E88551CC036F400F24E7B /* Info.plist */,
DA2784FB1DF02FF4001D5B8D /* Media.xcassets */,
+ DA35D0871E1A6309007DED41 /* one-liner.json */,
);
name = "SDK Tests";
path = test;
@@ -1706,7 +1709,6 @@
DA8847CE1CBAF91600AB86E3 /* Frameworks */,
DA8847CF1CBAF91600AB86E3 /* Headers */,
DA8847D01CBAF91600AB86E3 /* Resources */,
- 64E5BF321E09D729005223F7 /* Add Examples to Documentation */,
);
buildRules = (
);
@@ -1741,7 +1743,6 @@
DAA4E4101CBB71D400178DFB /* Frameworks */,
DAA4E4111CBB71D400178DFB /* CopyFiles */,
DABFB85C1CBE99DE00D62B32 /* Headers */,
- 6421B07A1E09EA4B00AF169B /* Add Examples to Documentation */,
);
buildRules = (
);
@@ -1869,6 +1870,7 @@
files = (
DA2784FC1DF02FF4001D5B8D /* Media.xcassets in Resources */,
353BAEF71D646370009A8DA9 /* amsterdam.geojson in Resources */,
+ DA35D0881E1A6309007DED41 /* one-liner.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1934,37 +1936,6 @@
};
/* End PBXResourcesBuildPhase section */
-/* Begin PBXShellScriptBuildPhase section */
- 6421B07A1E09EA4B00AF169B /* Add Examples to Documentation */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "Add Examples to Documentation";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "node \"${SRCROOT}/scripts/add-examples-to-docs.js\"";
- };
- 64E5BF321E09D729005223F7 /* Add Examples to Documentation */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "Add Examples to Documentation";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "node \"${SRCROOT}/scripts/add-examples-to-docs.js\"";
- };
-/* End PBXShellScriptBuildPhase section */
-
/* Begin PBXSourcesBuildPhase section */
DA1DC9461CB6C1C2006E619F /* Sources */ = {
isa = PBXSourcesBuildPhase;
diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml
index 1f1e48fce5..0a14cc3792 100644
--- a/platform/ios/jazzy.yml
+++ b/platform/ios/jazzy.yml
@@ -11,6 +11,8 @@ head: |
objc: Yes
skip_undocumented: Yes
hide_documentation_coverage: Yes
+umbrella_header: src/Mapbox.h
+framework_root: ../darwin/src
custom_categories:
- name: Guides
diff --git a/platform/ios/scripts/add-examples-to-docs.js b/platform/ios/scripts/add-examples-to-docs.js
deleted file mode 100644
index 7be755e2c6..0000000000
--- a/platform/ios/scripts/add-examples-to-docs.js
+++ /dev/null
@@ -1,65 +0,0 @@
-'use strict';
-
-const fs = require('fs');
-
-const examples = fs.readFileSync(`${__dirname}/../test/MGLDocumentationExampleTests.swift`, 'utf8');
-
-// Regex extracts the following block
-// /*---BEGIN EXAMPLE: MGLStyleSource---*/
-// /* Frontmatter to describe the example */
-// let sampleCode: String?
-// /*---END EXAMPLE---*/
-//
-// into the following regex groups:
-// 1 (token): " MGLStyleSource"
-// 2 (frontmatter): "/* Frontmatter to describe the example */"
-// 3 (sample code): "let sampleCode: String?"
-const exampleRegex = /\/\*---BEGIN EXAMPLE:(.*)---\*\/\s*(\/\*+[\s\S]*?\*+\/)?([\s\S]*?)\/\*---END EXAMPLE---\*\//gm;
-
-var path = `${process.env.TARGET_BUILD_DIR}/${process.env.PUBLIC_HEADERS_FOLDER_PATH}`;
-
-console.log("Installing examples...");
-
-var match;
-while ((match = exampleRegex.exec(examples)) !== null) {
- const token = match[1].trim();
- const className = token.split('.')[0];
-
- const frontmatter = (match[2] || '')
- .replace(/\/\*+/g, '') // Remove block comment /**
- .replace(/\*+\//g, '') // Remove block comment end */
- .trim()
- .replace(/\n {8,9}/g, '\n'); // Remove leading whitespace (8-9 spaces incl block comment)
-
- const exampleCode = match[3]
- .trim()
- .replace(/\n {8}/g, '\n'); // Remove leading whitespace (8 spaces)
-
- // Generate example text
- var exampleText = "### Example\n\n";
- if (frontmatter.length > 0) {
- exampleText += `${frontmatter}\n\n`;
- }
- exampleText += "```swift\n" + exampleCode + "\n```";
- exampleText = exampleText.replace(/\n/g, '\n ');
-
- const placeholderRegex = new RegExp(`<!--EXAMPLE: ${token}-->`);
-
- // check if file exists at path
- const filename = `${path}/${className}.h`;
-
- if (fs.existsSync(filename)) {
- const file = fs.readFileSync(filename, 'utf8');
- // Check for example placeholder in file & update file if found
- if (placeholderRegex.test(file)) {
- console.log("Updating example:", filename);
- fs.writeFileSync(filename, file.replace(placeholderRegex, exampleText));
- } else if (file.indexOf(exampleText) === -1) {
- console.log(`Placeholder "${token}" missing:`, filename);
- } else {
- console.log(`Example "${token}" already replaced.`);
- }
- } else if (token !== "ExampleToken") {
- console.log("Error file doesn't exist:", filename);
- }
-}
diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh
index 634f4de5dc..ec349d592d 100755
--- a/platform/ios/scripts/document.sh
+++ b/platform/ios/scripts/document.sh
@@ -35,16 +35,11 @@ cp -r platform/ios/docs/img "${OUTPUT}/img"
DEFAULT_THEME="platform/darwin/docs/theme"
THEME=${JAZZY_THEME:-$DEFAULT_THEME}
-DEFAULT_FRAMEWORK_PATH="build/ios/pkg/dynamic/Mapbox.framework"
-FRAMEWORK_PATH=${FRAMEWORK_PATH:-$DEFAULT_FRAMEWORK_PATH}
-
jazzy \
--config platform/ios/jazzy.yml \
--sdk iphonesimulator \
--github-file-prefix https://github.com/mapbox/mapbox-gl-native/tree/${BRANCH} \
--module-version ${SHORT_VERSION} \
- --framework-root ${FRAMEWORK_PATH} \
- --umbrella-header "${FRAMEWORK_PATH}/Headers/Mapbox.h" \
--readme ${README} \
--documentation="platform/ios/docs/guides/*.md" \
--root-url https://www.mapbox.com/ios-sdk/api/${RELEASE_VERSION}/ \
diff --git a/platform/macos/DEVELOPING.md b/platform/macos/DEVELOPING.md
index 71eb7995c8..823ad4656b 100644
--- a/platform/macos/DEVELOPING.md
+++ b/platform/macos/DEVELOPING.md
@@ -95,6 +95,32 @@ To add a localization to the macOS SDK:
1. In the Project navigator, expand each .strings and .stringsdict file in the project. An additional version for your localization should be listed; translate it. Translate everything on the right side of the equals sign. Leave the left side and any comments unmodified. See Apple’s documentation on the [.strings](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html) and [.stringsdict](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html) formats.
1. You’re already most of the way towards localizing the iOS SDK too – consider [completing that localization](../ios/DEVELOPING.md#adding-a-localization).
+### Adding a code example
+
+To add an example code listing to the documentation for a class or class member:
+
+1. Add a test method named in the form `testMGLClass` or `testMGLClass$method`
+ to [MGLDocumentationExampleTests](test/MGLDocumentationExampleTests.swift).
+ Wrap the code you’d like to appear in the documentation within
+ `//#-example-code` and `//#-end-example-code` comments.
+1. Insert the code listings into the headers:
+
+```bash
+make darwin-update-examples
+```
+
+[SourceKitten](https://github.com/jpsim/SourceKitten/) is required and will be installed automatically using Homebrew.
+
+## Testing
+
+`make macos-test` builds and runs unit tests of cross-platform code as well as the SDK.
+
+To instead run the cross-platform tests in Xcode instead of on the command line:
+
+1. Run `make xproj` to set up the workspace.
+1. Change the scheme to “mbgl-test” and press Command-R to run core unit tests.
+1. Change the scheme to “CI” and press Command-U to run SDK integration tests.
+
## Access tokens
The demo applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). You will be prompted for this access token the first time you launch the demo application.
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 56872a1b19..e4657596cf 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -68,6 +68,7 @@
DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */; };
DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */; };
DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA2784FD1DF03060001D5B8D /* Media.xcassets */; };
+ DA29875A1E1A4290002299F5 /* MGLDocumentationExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2987591E1A4290002299F5 /* MGLDocumentationExampleTests.swift */; };
DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */; };
DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */; };
@@ -80,6 +81,7 @@
DA35A2C21CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */; };
DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA35A2D01CCAAED300E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */; };
+ DA35D08A1E1A631B007DED41 /* one-liner.json in Resources */ = {isa = PBXBuildFile; fileRef = DA35D0891E1A631B007DED41 /* one-liner.json */; };
DA551B821DB496AC0009AFAF /* MGLTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA551B831DB496AC0009AFAF /* MGLTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */; };
DA551B841DB496AC0009AFAF /* MGLTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA551B811DB496AC0009AFAF /* MGLTileSource.mm */; };
@@ -321,6 +323,7 @@
DA2207BA1DC076930002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = "<group>"; };
DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLStyleValueTests.swift; sourceTree = "<group>"; };
DA2784FD1DF03060001D5B8D /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = ../../darwin/test/Media.xcassets; sourceTree = "<group>"; };
+ DA2987591E1A4290002299F5 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = "<group>"; };
DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MGLStyleLayerTests.xib; sourceTree = "<group>"; };
DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCoordinateFormatter.h; sourceTree = "<group>"; };
DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCoordinateFormatter.m; sourceTree = "<group>"; };
@@ -333,6 +336,7 @@
DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLClockDirectionFormatterTests.m; path = ../../darwin/test/MGLClockDirectionFormatterTests.m; sourceTree = "<group>"; };
DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLAdditions.h"; sourceTree = "<group>"; };
DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+MGLAdditions.m"; sourceTree = "<group>"; };
+ DA35D0891E1A631B007DED41 /* one-liner.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "one-liner.json"; path = "../../darwin/test/one-liner.json"; sourceTree = "<group>"; };
DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource.h; sourceTree = "<group>"; };
DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource_Private.h; sourceTree = "<group>"; };
DA551B811DB496AC0009AFAF /* MGLTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSource.mm; sourceTree = "<group>"; };
@@ -886,6 +890,7 @@
3526EABC1DF9B19800006B43 /* MGLCodingTests.m */,
DA35A2B51CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m */,
DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */,
+ DA2987591E1A4290002299F5 /* MGLDocumentationExampleTests.swift */,
DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */,
DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */,
DAE6C3C81CC34BD800DB3429 /* MGLGeometryTests.mm */,
@@ -896,6 +901,7 @@
DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */,
DAE6C33A1CC30DB200DB3429 /* Info.plist */,
DA2784FD1DF03060001D5B8D /* Media.xcassets */,
+ DA35D0891E1A631B007DED41 /* one-liner.json */,
);
name = "SDK Tests";
path = test;
@@ -1216,6 +1222,7 @@
35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */,
DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */,
DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */,
+ DA35D08A1E1A631B007DED41 /* one-liner.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1326,6 +1333,7 @@
DA87A99E1DC9DC2100810D09 /* MGLPredicateTests.mm in Sources */,
DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */,
DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.m in Sources */,
+ DA29875A1E1A4290002299F5 /* MGLDocumentationExampleTests.swift in Sources */,
DAE6C3D31CC34C9900DB3429 /* MGLOfflinePackTests.m in Sources */,
DA87A9A51DCACC5000810D09 /* MGLLineStyleLayerTests.m in Sources */,
DA87A9A31DCACC5000810D09 /* MGLRasterStyleLayerTests.m in Sources */,