summaryrefslogtreecommitdiff
path: root/platform/darwin/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin/scripts')
-rwxr-xr-xplatform/darwin/scripts/check-public-symbols.js83
-rwxr-xr-xplatform/darwin/scripts/generate-style-code.js925
-rw-r--r--platform/darwin/scripts/style-spec-cocoa-conventions-v8.json56
-rw-r--r--platform/darwin/scripts/style-spec-overrides-v8.json148
-rwxr-xr-xplatform/darwin/scripts/update-examples.js148
5 files changed, 0 insertions, 1360 deletions
diff --git a/platform/darwin/scripts/check-public-symbols.js b/platform/darwin/scripts/check-public-symbols.js
deleted file mode 100755
index a2045f81ec..0000000000
--- a/platform/darwin/scripts/check-public-symbols.js
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env node
-
-'use strict';
-
-const fs = require('fs');
-const path = require('path');
-const execFileSync = require('child_process').execFileSync;
-const _ = require('lodash');
-
-const keyword = /\bMGL_EXPORT\b/;
-
-let scanned = [];
-
-function hasMissingSymbols(os) {
- let missing = false;
- 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, { maxBuffer: Infinity }).toString().trim();
- let docJson = JSON.parse(docStr);
- _.forEach(docJson, function (result) {
- _.forEach(result, function (structure, path) {
- // Prevent multiple scans of the same file.
- if (scanned.indexOf(path) >= 0) return;
- scanned.push(path);
-
- const src = fs.readFileSync(path, 'utf8').split('\n');
- _.forEach(structure['key.substructure'], function (substructure) {
- switch (substructure['key.kind']) {
- case 'sourcekitten.source.lang.objc.decl.class':
- if (!(keyword.test(src[substructure['key.doc.line'] - 1]) || keyword.test(src[substructure['key.doc.line'] - 2]))) {
- console.warn(`- missing symbol export for class ${substructure['key.name']} in ${path}:${substructure['key.doc.line']}:${substructure['key.doc.column']}`);
- missing = true;
- }
- break;
- case 'sourcekitten.source.lang.objc.decl.constant':
- if (!keyword.test(src[substructure['key.doc.line'] - 1])) {
- console.warn(`- missing symbol export for constant ${substructure['key.name']} in ${path}:${substructure['key.doc.line']}:${substructure['key.doc.column']}`);
- missing = true;
- }
- break;
- }
- });
- });
- });
-
- return missing;
-}
-
-function ensureSourceKittenIsInstalled() {
- try {
- execFileSync('which', ['sourcekitten']);
- } catch (e) {
- console.log(`Installing SourceKitten via Homebrew…`);
- execFileSync('brew', ['install', 'sourcekitten']);
- }
-}
-
-if (process.argv.length < 3) {
- console.warn(`Usage: ${path.relative(process.cwd(), process.argv[1])} [macOS|iOS] ...`);
- process.exit(1);
-}
-
-ensureSourceKittenIsInstalled();
-
-let missing = false;
-for (var i = 2; i < process.argv.length; i++) {
- let os = process.argv[i];
- if (os == 'iOS' || os == 'macOS') {
- missing |= hasMissingSymbols(os);
- } else {
- console.warn(`Argument must be one of iOS or macOS`);
- process.exit(1);
- }
-}
-
-if (missing) {
- process.exit(1);
-} else {
- console.warn(`All symbols are correctly exported.`);
-}
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
deleted file mode 100755
index bd5adb9685..0000000000
--- a/platform/darwin/scripts/generate-style-code.js
+++ /dev/null
@@ -1,925 +0,0 @@
-#!/usr/bin/env node
-'use strict';
-
-const fs = require('fs');
-const ejs = require('ejs');
-const _ = require('lodash');
-const colorParser = require('csscolorparser');
-const assert = require('assert');
-
-require('../../../scripts/style-code');
-
-const cocoaConventions = require('./style-spec-cocoa-conventions-v8.json');
-const prefix = 'MGL';
-const suffix = 'StyleLayer';
-
-let spec = _.merge(require('../../../scripts/style-spec'), require('./style-spec-overrides-v8.json'));
-
-// FIXME: https://github.com/mapbox/mapbox-gl-native/issues/15008
-delete spec.layout_circle["circle-sort-key"]
-delete spec.layout_line["line-sort-key"]
-delete spec.layout_fill["fill-sort-key"]
-
-class ConventionOverride {
- constructor(val) {
- if (typeof val === 'string') {
- this.name_ = val;
- this.enumName_ = null;
- } else if (val instanceof Object) {
- this.name_ = val.name;
- this.enumName_ = val.enumName;
- } else {
- assert(false);
- }
- }
-
- set name(name_) { this.name_ = name_; }
- get name() { return this.name_; }
- get enumName() { return this.enumName_ || this.name_; }
-}
-
-// Rename properties and keep `original` for use with setters and getters
-_.forOwn(cocoaConventions, function (properties, kind) {
- _.forOwn(properties, function (newConvention, oldName) {
- let conventionOverride = new ConventionOverride(newConvention);
- let property = spec[kind][oldName];
- if (conventionOverride.name.startsWith('is-')) {
- property.getter = conventionOverride.name;
- conventionOverride.name = conventionOverride.name.substr(3);
- }
-
- // Override enum name based on style-spec-cocoa-conventions-v8.json
- property.enumName = conventionOverride.enumName;
-
- if (conventionOverride.name !== oldName) {
- property.original = oldName;
- delete spec[kind][oldName];
- spec[kind][conventionOverride.name] = property;
- }
-
- // Update cross-references to this property in other properties'
- // documentation and requirements.
- let renameCrossReferences = function (property, name) {
- property.doc = property.doc.replace(new RegExp('`' + oldName + '`', 'g'), '`' + conventionOverride.name + '`');
- let requires = property.requires || [];
- for (let i = 0; i < requires.length; i++) {
- if (requires[i] === oldName) {
- property.requires[i] = conventionOverride.name;
- }
- if (typeof requires[i] !== 'string') {
- _.forOwn(requires[i], function (values, name, require) {
- if (name === oldName) {
- require[conventionOverride.name] = values;
- delete require[name];
- }
- });
- }
- }
- };
- _.forOwn(spec[kind.replace(/^layout_/, 'paint_')], renameCrossReferences);
- _.forOwn(spec[kind.replace(/^paint_/, 'layout_')], renameCrossReferences);
- })
-});
-
-String.prototype.wrap = function (cols, indent) {
- let wrapRe = new RegExp(`(.{1,${cols - indent}})(?: +|\n|$)`, "gm");
- return this.replace(wrapRe, "$1\n").replace(/\s+$/, "").indent(indent);
-};
-
-String.prototype.indent = function (cols) {
- return this.replace(/^|\n/g, "$&" + " ".repeat(cols));
-};
-
-global.camelize = function (str) {
- return str.replace(/(?:^|-)(.)/g, function (_, x) {
- return x.toUpperCase();
- });
-};
-
-global.camelizeWithLeadingLowercase = function (str) {
- return str.replace(/-(.)/g, function (_, x) {
- return x.toUpperCase();
- });
-};
-
-// Returns true only if property is an enum or if it is an array
-// property with uniquely defined enum.
-global.definesEnum = function(property, allProperties) {
- if (property.type === "enum") {
- return true;
- }
-
- if (property.type === 'array' && property.value === 'enum') {
- const uniqueArrayEnum = (prop, enums) => {
- if (prop.value !== 'enum') return false;
- const enumsEqual = (val1, val2) => val1.length === val1.length && val1.every((val, i) => val === val2[i]);
- return enums.filter(e => enumsEqual(Object.keys(prop.values).sort(), Object.keys(e.values).sort())).length == 0;
- };
-
- const allEnumProperties = _(allProperties).filter({'type': 'enum'}).value();
- const uniqueArrayEnumProperties = _(allProperties).filter({'type': 'array'}).filter(prop => uniqueArrayEnum(prop, allEnumProperties)).value();
- return _(uniqueArrayEnumProperties).filter({'name': property.name}).value().length != 0;
- }
-
- return false;
-}
-
-global.objCName = function (property) {
- return camelizeWithLeadingLowercase(property.name);
-};
-
-global.objCGetter = function (property) {
- return camelizeWithLeadingLowercase(property.getter || property.name);
-};
-
-global.objCType = function (layerType, propertyName) {
- return `${prefix}${camelize(propertyName)}`;
-};
-
-global.arrayType = function (property) {
- return property.type === 'array' ? originalPropertyName(property).split('-').pop() : false;
-};
-
-global.testImplementation = function (property, layerType, isFunction) {
- let helperMsg = testHelperMessage(property, layerType, isFunction);
- return `layer.${objCName(property)} = [MGLRuntimeStylingHelper ${helperMsg}];`;
-};
-
-global.objCTestValue = function (property, layerType, arraysAsStructs, indent) {
- let propertyName = originalPropertyName(property);
- switch (property.type) {
- case 'boolean':
- return property.default ? '@"false"' : '@"true"';
- case 'number':
- return '@"1"';
- case 'formatted':
- // Special 'string' case to handle constant expression text-field that automatically
- // converts Formatted back to string.
- return layerType === 'string' ?
- `@"'${_.startCase(propertyName)}'"` :
- `@"${_.startCase(propertyName)}"`;
- case 'resolvedImage':
- return layerType === 'string' ?
- `@"${_.startCase(propertyName)}"` :
- `@"MGL_FUNCTION('image', '${_.startCase(propertyName)}')"`;
- case 'string':
- return `@"'${_.startCase(propertyName)}'"`;
- case 'enum':
- return `@"'${_.last(_.keys(property.values))}'"`;
- case 'color':
- return '@"%@", [MGLColor redColor]';
- case 'array':
- switch (arrayType(property)) {
- case 'dasharray':
- return '@"{1, 2}"';
- case 'font':
- return `@"{'${_.startCase(propertyName)}', '${_.startCase(_.reverse(propertyName.split('')).join(''))}'}"`;
- case 'padding': {
- if (arraysAsStructs) {
- let iosValue = '[NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(1, 1, 1, 1)]'.indent(indent * 4);
- let macosValue = '[NSValue valueWithEdgeInsets:NSEdgeInsetsMake(1, 1, 1, 1)]'.indent(indent * 4);
- return `@"%@",\n#if TARGET_OS_IPHONE\n${iosValue}\n#else\n${macosValue}\n#endif\n${''.indent((indent - 1) * 4)}`;
- }
- return '@"{1, 1, 1, 1}"';
- }
- case 'offset':
- case 'translate': {
- if (arraysAsStructs) {
- let iosValue = '[NSValue valueWithCGVector:CGVectorMake(1, 1)]'.indent(indent * 4);
- let macosValue = '[NSValue valueWithMGLVector:CGVectorMake(1, -1)]'.indent(indent * 4);
- return `@"%@",\n#if TARGET_OS_IPHONE\n${iosValue}\n#else\n${macosValue}\n#endif\n${''.indent((indent - 1) * 4)}`;
- }
- return '@"{1, 1}"';
- }
- case 'anchor':
- return `@"{'top','bottom'}"`;
- case 'mode':
- return `@"{'horizontal','vertical'}"`;
- default:
- throw new Error(`unknown array type for ${property.name}`);
- }
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-};
-
-global.mbglTestValue = function (property, layerType) {
- let propertyName = originalPropertyName(property);
- switch (property.type) {
- case 'boolean':
- return property.default ? 'false' : 'true';
- case 'number':
- return '1.0';
- case 'formatted':
- case 'string':
- case 'resolvedImage':
- return `"${_.startCase(propertyName)}"`;
- case 'enum': {
- let type = camelize(originalPropertyName(property));
- if (/-translate-anchor$/.test(originalPropertyName(property))) {
- type = 'TranslateAnchor';
- }
- if (/-(rotation|pitch)-alignment$/.test(originalPropertyName(property))) {
- type = 'Alignment';
- }
- if (/^(text|icon)-anchor$/.test(originalPropertyName(property))) {
- type = 'SymbolAnchor'
- }
- let value = camelize(_.last(_.keys(property.values)));
- if (property['light-property']) {
- return `mbgl::style::Light${type}Type::${value}`;
- }
- return `mbgl::style::${type}Type::${value}`;
- }
- case 'color':
- return '{ 1, 0, 0, 1 }';
- case 'array':
- switch (arrayType(property)) {
- case 'dasharray':
- return '{1, 2}';
- case 'font':
- return `{ "${_.startCase(propertyName)}", "${_.startCase(_.reverse(propertyName.split('')).join(''))}" }`;
- case 'padding':
- return '{ 1, 1, 1, 1 }';
- case 'offset':
- case 'translate':
- return '{ 1, 1 }';
- case 'anchor':
- return '{ mbgl::style::SymbolAnchorType::Top, mbgl::style::SymbolAnchorType::Bottom }';
- case 'mode':
- return '{ mbgl::style::TextWritingModeType::Horizontal, mbgl::style::TextWritingModeType::Vertical }';
- default:
- throw new Error(`unknown array type for ${property.name}`);
- }
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-};
-
-global.mbglExpressionTestValue = function (property, layerType) {
- let propertyName = originalPropertyName(property);
- switch (property.type) {
- case 'enum':
- return `"${_.last(_.keys(property.values))}"`;
- case 'color':
- return 'mbgl::Color(1, 0, 0, 1)';
- case 'array':
- switch (arrayType(property)) {
- case 'anchor':
- return `{"top", "bottom"}`;
- case 'mode':
- return `{"horizontal", "vertical"}`;
- default:
- break;
- }
- default:
- return global.mbglTestValue(property, layerType);
- }
-};
-
-global.testGetterImplementation = function (property, layerType, isFunction) {
- let helperMsg = testHelperMessage(property, layerType, isFunction);
- let value = `[MGLRuntimeStylingHelper ${helperMsg}]`;
- if (property.type === 'enum') {
- if (isFunction) {
- return `XCTAssertEqualObjects(gLayer.${objCName(property)}, ${value});`;
- }
- return `XCTAssert([gLayer.${objCName(property)} isKindOfClass:[MGLConstantStyleValue class]]);
- XCTAssertEqualObjects(gLayer.${objCName(property)}, ${value});`;
- }
- return `XCTAssertEqualObjects(gLayer.${objCName(property)}, ${value});`;
-};
-
-global.testHelperMessage = function (property, layerType, isFunction) {
- let fnSuffix = isFunction ? 'Function' : '';
- switch (property.type) {
- case 'boolean':
- return 'testBool' + fnSuffix;
- case 'number':
- return 'testNumber' + fnSuffix;
- case 'formatted':
- case 'string':
- case 'resolvedImage':
- return 'testString' + fnSuffix;
- case 'enum':
- let objCType = global.objCType(layerType, property.name);
- let objCEnum = `${objCType}${camelize(Object.keys(property.values)[Object.keys(property.values).length-1])}`;
- return `testEnum${fnSuffix}:${objCEnum} type:@encode(${objCType})`;
- case 'color':
- return 'testColor' + fnSuffix;
- case 'array':
- switch (arrayType(property)) {
- case 'dasharray':
- return 'testDashArray' + fnSuffix;
- case 'font':
- return 'testFont' + fnSuffix;
- case 'padding':
- return 'testPadding' + fnSuffix;
- case 'offset':
- case 'translate':
- return 'testOffset' + fnSuffix;
- default:
- throw new Error(`unknown array type for ${property.name}`);
- }
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-};
-
-global.propertyDoc = function (propertyName, property, layerType, kind) {
- // Match references to other property names & values.
- // Requires the format 'When `foo` is set to `bar`,'.
- let doc = property.doc.replace(/`([^`]+?)` is set to `([^`]+?)`(?: or `([^`]+?)`)?/g, function (m, peerPropertyName, propertyValue, secondPropertyValue, offset, str) {
- let otherProperty = camelizeWithLeadingLowercase(peerPropertyName);
- let otherValue = objCType(layerType, peerPropertyName) + camelize(propertyValue);
- if (property.type == 'array' && kind == 'light') {
- otherValue = propertyValue;
- }
- const firstPropertyValue = '`' + `${otherProperty}` + '` is set to `' + `${otherValue}` + '`';
- if (secondPropertyValue) {
- return firstPropertyValue + ' or `' +
- objCType(layerType, peerPropertyName) + camelize(secondPropertyValue) +
- '`';
- } else {
- return firstPropertyValue;
- }
- });
- // Match references to our own property values.
- // Requires the format 'is equivalent to `bar`'.
- doc = doc.replace(/is equivalent to `(.+?)`/g, function(m, propertyValue, offset, str) {
- propertyValue = objCType(layerType, propertyName) + camelize(propertyValue);
- return 'is equivalent to `' + propertyValue + '`';
- });
- // Format everything else: our property name & its possible values.
- // Requires symbols to be surrounded by backticks.
- doc = doc.replace(/`(.+?)`/g, function (m, symbol, offset, str) {
- if (kind === 'enum') {
- let layoutProperties = spec[`layout_${layerType}`] || [];
- let paintProperties = spec[`paint_${layerType}`] || [];
- if (symbol in layoutProperties || symbol in paintProperties) {
- return '`MGL' + camelize(layerType) + 'StyleLayer.' + camelizeWithLeadingLowercase(symbol) + '`';
- }
- }
- if ('values' in property && Object.keys(property.values).indexOf(symbol) !== -1) {
- let objCType = global.objCType(layerType, property.name);
- return '`' + `${objCType}${camelize(symbol)}` + '`';
- }
- if (str.substr(offset - 4, 3) !== 'CSS') {
- symbol = camelizeWithLeadingLowercase(symbol);
- }
- return '`' + symbol + '`';
- });
- // Format references to units.
- if ('units' in property) {
- if (!property.units.match(/s$/)) {
- property.units += 's';
- }
- doc += `\n\nThis property is measured in ${property.units}.`;
- }
- doc = doc.replace(/(p)ixel/gi, '$1oint').replace(/(\d)px\b/g, '$1pt');
- if (kind !== 'enum') {
- if ('default' in property) {
- doc += `\n\nThe default value of this property is ${propertyDefault(property, layerType)}.`;
- if (!property.required && kind != 'light') {
- doc += ' Set this property to `nil` to reset it to the default value.';
- }
- }
- if ('requires' in property) {
- doc += '\n\n' + propertyReqs(property, spec[`${kind}_${layerType}`], layerType);
- }
- if ('original' in property) {
- let anchor;
- switch (kind) {
- case 'layout':
- anchor = `layout-${layerType}-${property.original}`;
- break;
- case 'paint':
- anchor = `paint-${property.original}`;
- break;
- }
- doc += `\n\nThis attribute corresponds to the <a href="https://www.mapbox.com/mapbox-gl-style-spec/#${anchor}"><code>${property.original}</code></a> layout property in the Mapbox Style Specification.`;
- }
- doc += '\n\nYou can set this property to an expression containing any of the following:\n\n';
- doc += `* Constant ${describeType(property)} values`;
- if ('minimum' in property) {
- if ('maximum' in property) {
- doc += ` between ${formatNumber(property.minimum)} and ${formatNumber(property.maximum)} inclusive`;
- } else {
- doc += ` no less than ${formatNumber(property.minimum)}`;
- }
- } else if ('maximum' in property) {
- doc += ` no greater than ${formatNumber(property.maximum)}`;
- }
- doc += '\n';
- if (property.type === 'enum') {
- doc += '* Any of the following constant string values:\n';
- doc += Object.keys(property.values).map(value => ' * `' + value + '`: ' + property.values[value].doc).join('\n') + '\n';
- } else if (property.type === 'array' && property.value === 'enum') {
- doc += '* Constant array, in which each element is any of the following constant string values:\n';
- doc += Object.keys(property.values).map(value => ' * `' + value + '`: ' + property.values[value].doc).join('\n') + '\n';
- }
- if (property.type === 'formatted') {
- doc += '* Formatted expressions.\n';
- }
- doc += '* Predefined functions, including mathematical and string operators\n' +
- '* Conditional expressions\n' +
- '* Variable assignments and references to assigned variables\n';
- const inputVariable = property.expression && property['property-type'] === 'color-ramp' ?
- '$' + camelizeWithLeadingLowercase(property.expression.parameters[0]) : '$zoomLevel';
- if (isDataDriven(property)) {
- doc += `* Interpolation and step functions applied to the \`${inputVariable}\` variable and/or feature attributes\n`;
- } else if (property.expression && property.expression.interpolated) {
- doc += `* Interpolation and step functions applied to the \`${inputVariable}\` variable\n\n` +
- 'This property does not support applying interpolation or step functions to feature attributes.';
- } else {
- doc += `* Step functions applied to the \`${inputVariable}\` variable\n\n` +
- `This property does not support applying interpolation functions to the \`${inputVariable}\` variable or applying interpolation or step functions to feature attributes.`;
- }
- }
- return doc;
-};
-
-global.propertyExample = function (property) {
- return property.examples;
-};
-
-global.isDataDriven = function (property) {
- return property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven';
-};
-
-global.propertyReqs = function (property, propertiesByName, type) {
- return 'This property is only applied to the style if ' + property.requires.map(function (req) {
- if (typeof req === 'string') {
- return '`' + camelizeWithLeadingLowercase(req) + '` is non-`nil`';
- } else if ('!' in req) {
- return '`' + camelizeWithLeadingLowercase(req['!']) + '` is set to `nil`';
- } else {
- let name = Object.keys(req)[0];
- if (name === 'source')
- return 'the data source requirements are met';
- return '`' + camelizeWithLeadingLowercase(name) + '` is set to an expression that evaluates to ' + describeValue(req[name], propertiesByName[name], type);
- }
- }).join(', and ') + '. Otherwise, it is ignored.';
-};
-
-global.parseColor = function (str) {
- let color = colorParser.parseCSSColor(str);
- return {
- r: color[0] / 255,
- g: color[1] / 255,
- b: color[2] / 255,
- a: color[3],
- };
-};
-
-global.describeType = function (property) {
- switch (property.type) {
- case 'boolean':
- return 'Boolean';
- case 'number':
- return 'numeric';
- case 'formatted':
- case 'string':
- case 'resolvedImage':
- return 'string';
- case 'enum':
- return '`MGL' + camelize(property.name) + '`';
- case 'color':
- return '`UIColor`';
- case 'array':
- switch (arrayType(property)) {
- case 'padding':
- return '`UIEdgeInsets`';
- case 'offset':
- case 'translate':
- return '`CGVector`';
- case 'position':
- return '`MGLSphericalPosition`';
- case 'anchor':
- return '`MGLTextAnchor` array';
- case 'mode':
- return '`MGLTextWritingMode` array';
- default:
- return 'array';
- }
- break;
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-}
-
-global.describeValue = function (value, property, layerType) {
- if (Array.isArray(value) && property.type !== 'array' && property.type !== 'enum') {
- switch (value[0]) {
- case 'interpolate': {
- let curveType = value[1][0];
- let minimum = describeValue(value[3 + value.length % 2], property, layerType);
- let maximum = describeValue(_.last(value), property, layerType);
- return `${curveType.match(/^[aeiou]/i) ? 'an' : 'a'} ${curveType} interpolation expression ranging from ${minimum} to ${maximum}`;
- }
- default:
- throw new Error(`No description available for ${value[0]} expression in ${property.name} of ${layerType}.`);
- }
- }
-
- switch (property.type) {
- case 'boolean':
- return value ? '`YES`' : '`NO`';
- case 'number':
- return 'the float ' + '`' + formatNumber(value) + '`';
- case 'formatted':
- case 'string':
- case 'resolvedImage':
- if (value === '') {
- return 'the empty string';
- }
- return 'the string `' + value + '`';
- case 'enum':
- let displayValue;
- if (Array.isArray(value)) {
- let separator = (value.length === 2) ? ' ' : ', ';
- displayValue = value.map((possibleValue, i) => {
- let conjunction = '';
- if (value.length === 2 && i === 0) conjunction = 'either ';
- if (i === value.length - 1) conjunction = 'or ';
- let objCType = global.objCType(layerType, property.name);
- return `${conjunction}\`${objCType}${camelize(possibleValue)}\``;
- }).join(separator);
- } else {
- displayValue = `\`${value}\``;
- }
- return displayValue;
- case 'color':
- let color = parseColor(value);
- if (!color) {
- throw new Error(`unrecognized color format in default value of ${property.name}`);
- }
- if (color.r === 0 && color.g === 0 && color.b === 0 && color.a === 0) {
- return '`UIColor.clearColor`';
- }
- if (color.r === 0 && color.g === 0 && color.b === 0 && color.a === 1) {
- return '`UIColor.blackColor`';
- }
- if (color.r === 1 && color.g === 1 && color.b === 1 && color.a === 1) {
- return '`UIColor.whiteColor`';
- }
- return 'a `UIColor`' + ` object whose RGB value is ${formatNumber(color.r)}, ${formatNumber(color.g)}, ${formatNumber(color.b)} and whose alpha value is ${formatNumber(color.a)}`;
- case 'array':
- let units = property.units || '';
- if (units) {
- units = ` ${units}`.replace(/pixel/, 'point');
- }
- switch (arrayType(property)) {
- case 'padding':
- if (value[0] === 0 && value[1] === 0 && value[2] === 0 && value[3] === 0) {
- return 'an `NSValue` object containing `UIEdgeInsetsZero`';
- }
- return 'an `NSValue` object containing a `UIEdgeInsets` struct set to' + ` ${formatNumber(value[0])}${units} on the top, ${formatNumber(value[3])}${units} on the left, ${formatNumber(value[2])}${units} on the bottom, and ${formatNumber(value[1])}${units} on the right`;
- case 'offset':
- case 'translate':
- return 'an `NSValue` object containing a `CGVector` struct set to' + ` ${formatNumber(value[0])}${units} rightward and ${formatNumber(value[1])}${units} downward`;
- case 'position':
- return 'an `MGLSphericalPosition` struct set to' + ` ${formatNumber(value[0])} radial, ${formatNumber(value[1])} azimuthal and ${formatNumber(value[2])} polar`;
- default:
- return 'the array `' + value.join('`, `') + '`';
- }
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-};
-
-global.formatNumber = function (num) {
- return num.toLocaleString().replace('-', '\u2212');
-}
-
-global.propertyDefault = function (property, layerType) {
- if (property.name === 'heatmap-color') {
- return 'an expression that evaluates to a rainbow color scale from blue to red';
- } else {
- return 'an expression that evaluates to ' + describeValue(property.default, property, layerType);
- }
-};
-
-global.originalPropertyName = function (property) {
- return property.original || property.name;
-};
-
-global.enumName = function (property) {
- return property.enumName || property.name;
-};
-
-global.propertyType = function (property) {
- switch (property.type) {
- case 'boolean':
- return 'NSNumber *';
- case 'number':
- return 'NSNumber *';
- case 'formatted':
- case 'string':
- case 'resolvedImage':
- return 'NSString *';
- case 'enum':
- return 'NSValue *';
- case 'color':
- return 'MGLColor *';
- case 'array':
- switch (arrayType(property)) {
- case 'dasharray':
- return 'NSArray<NSNumber *> *';
- case 'font':
- return 'NSArray<NSString *> *';
- case 'padding':
- case 'position':
- case 'offset':
- case 'translate':
- return 'NSValue *';
- case 'anchor':
- case 'mode':
- return 'NSArray<NSValue *> *';
- default:
- throw new Error(`unknown array type for ${property.name}`);
- }
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-};
-
-global.isInterpolatable = function (property) {
- const type = property.type === 'array' ? property.value : property.type;
- return type !== 'boolean' &&
- type !== 'enum' &&
- type !== 'string' &&
- type !== 'resolvedImage' &&
- type !== 'formatted';
-};
-
-global.valueTransformerArguments = function (property) {
- let objCType = propertyType(property);
- switch (property.type) {
- case 'boolean':
- return ['bool', objCType];
- case 'number':
- return ['float', objCType];
- case 'formatted':
- return ['mbgl::style::expression::Formatted', objCType];
- case 'resolvedImage':
- return ['mbgl::style::expression::Image', objCType];
- case 'string':
- return ['std::string', objCType];
- case 'enum':
- return [mbglType(property), 'NSValue *', mbglType(property), `MGL${camelize(property.name)}`];
- case 'color':
- return ['mbgl::Color', objCType];
- case 'array':
- switch (arrayType(property)) {
- case 'dasharray':
- return ['std::vector<float>', objCType, 'float'];
- case 'font':
- return ['std::vector<std::string>', objCType, 'std::string'];
- case 'padding':
- return ['std::array<float, 4>', objCType];
- case 'position':
- return ['mbgl::style::Position', objCType];
- case 'offset':
- case 'translate':
- return ['std::array<float, 2>', objCType];
- case 'anchor':
- return ['std::vector<mbgl::style::SymbolAnchorType>', objCType, 'mbgl::style::SymbolAnchorType', 'MGLTextAnchor'];
- case 'mode':
- return ['std::vector<mbgl::style::TextWritingModeType>', objCType, 'mbgl::style::TextWritingModeType', 'MGLTextWritingMode'];
- default:
- throw new Error(`unknown array type for ${property.name}`);
- }
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-};
-
-global.mbglType = function(property) {
- switch (property.type) {
- case 'boolean':
- return 'bool';
- case 'number':
- return 'float';
- case 'formatted':
- return 'mbgl::style::expression::Formatted';
- case 'resolvedImage':
- return 'mbgl::style::expression::Image';
- case 'string':
- return 'std::string';
- case 'enum': {
- let type = camelize(originalPropertyName(property));
- if (property['light-property']) {
- return `mbgl::style::Light${type}Type`;
- }
- if (/-translate-anchor$/.test(originalPropertyName(property))) {
- type = 'TranslateAnchor';
- }
- if (/-(rotation|pitch)-alignment$/.test(originalPropertyName(property))) {
- type = 'Alignment';
- }
- if (/^(text|icon)-anchor$/.test(originalPropertyName(property))) {
- type = 'SymbolAnchor'
- }
- return `mbgl::style::${type}Type`;
- }
- case 'color':
- return 'mbgl::Color';
- case 'array':
- switch (arrayType(property)) {
- case 'dasharray':
- return 'std::vector<float>';
- case 'font':
- return 'std::vector<std::string>';
- case 'padding':
- return 'std::array<float, 4>';
- case 'offset':
- case 'translate':
- return 'std::array<float, 2>';
- case 'position':
- return 'mbgl::style::Position';
- case 'anchor':
- return 'std::vector<mbgl::style::SymbolAnchorType>';
- case 'mode':
- return 'std::vector<mbgl::style::TextWritingModeType>';
- default:
- throw new Error(`unknown array type for ${property.name}`);
- }
- default:
- throw new Error(`unknown type for ${property.name}`);
- }
-};
-
-global.initLayer = function (layerType) {
- if (layerType == "background") {
- return `_layer = new mbgl::style::${camelize(layerType)}Layer(identifier.UTF8String);`
- } else {
- return `_layer = new mbgl::style::${camelize(layerType)}Layer(identifier.UTF8String, source.identifier.UTF8String);`
- }
-};
-
-global.setSourceLayer = function() {
- return `_layer->setSourceLayer(sourceLayer.UTF8String);`
-};
-
-const lightProperties = Object.keys(spec['light']).reduce((memo, name) => {
- var property = spec['light'][name];
- property.name = name;
- property['light-property'] = true;
- memo.push(property);
- return memo;
-}, []);
-
-const lightDoc = spec['light-cocoa-doc'];
-const lightType = 'light';
-
-const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h.ejs', 'utf8'), { strict: true });
-const layerPrivateH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer_Private.h.ejs', 'utf8'), { strict: true });
-const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true});
-const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.mm.ejs', 'utf8'), { strict: true});
-const forStyleAuthorsMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true });
-const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Migrating to Expressions.md.ejs', 'utf8'), { strict: true });
-const templatesMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Tile URL Templates.md.ejs', 'utf8'), { strict: true });
-
-const lightH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLLight.h.ejs', 'utf8'), {strict: true});
-const lightM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLLight.mm.ejs', 'utf8'), {strict: true});
-const testLight = ejs.compile(fs.readFileSync('platform/darwin/test/MGLLightTest.mm.ejs', 'utf8'), { strict: true});
-writeIfModified(`platform/darwin/src/MGLLight.h`, duplicatePlatformDecls(lightH({ properties: lightProperties, doc: lightDoc, type: lightType })));
-writeIfModified(`platform/darwin/src/MGLLight.mm`, lightM({ properties: lightProperties, doc: lightDoc, type: lightType }));
-writeIfModified(`platform/darwin/test/MGLLightTest.mm`, testLight({ properties: lightProperties, doc: lightDoc, type: lightType }));
-
-
-const layers = _(spec.layer.type.values).map((value, layerType) => {
- const layoutProperties = Object.keys(spec[`layout_${layerType}`]).reduce((memo, name) => {
- if (name !== 'visibility') {
- spec[`layout_${layerType}`][name].name = name;
- memo.push(spec[`layout_${layerType}`][name]);
- }
- return memo;
- }, []);
-
- const paintProperties = Object.keys(spec[`paint_${layerType}`]).reduce((memo, name) => {
- spec[`paint_${layerType}`][name].name = name;
- memo.push(spec[`paint_${layerType}`][name]);
- return memo;
- }, []);
-
- return {
- doc: spec.layer.type.values[layerType].doc,
- examples: spec.layer.type.values[layerType].examples,
- type: layerType,
- layoutProperties: _.sortBy(layoutProperties, ['name']),
- paintProperties: _.sortBy(paintProperties, ['name']),
- };
-}).sortBy(['type']).value();
-
-function duplicatePlatformDecls(src) {
- // Look for a documentation comment that contains “MGLColor” or “UIColor”
- // and the subsequent function, method, or property declaration. Try not to
- // match greedily.
- return src.replace(/(\/\*\*(?:\*[^\/]|[^*])*?\b(?:MGL|NS|UI)Color\b[\s\S]*?\*\/)(\s*.+?;)/g,
- (match, comment, decl) => {
- let macosComment = comment.replace(/\b(?:MGL|UI)Color\b/g, 'NSColor')
- // Use the correct indefinite article.
- .replace(/\ba(\s+`?NSColor)\b/gi, 'an$1');
- let iosDecl = decl.replace(/\bMGLColor\b/g, 'UIColor');
- let macosDecl = decl.replace(/\b(?:MGL|UI)Color\b/g, 'NSColor');
- return `\
-#if TARGET_OS_IPHONE
-${comment}${iosDecl}
-#else
-${macosComment}${macosDecl}
-#endif`;
- })
- // Do the same for CGVector-typed properties.
- .replace(/(\/\*\*(?:\*[^\/]|[^*])*?\b(?:CGVector|UIEdgeInsets(?:Zero)?)\b[\s\S]*?\*\/)(\s*.+?;)/g,
- (match, comment, decl) => {
- let macosComment = comment.replace(/\bdownward\b/g, 'upward')
- .replace(/\bUI(EdgeInsets(?:Zero)?)\b/g, 'NS$1');
- return `\
-#if TARGET_OS_IPHONE
-${comment}${decl}
-#else
-${macosComment}${decl}
-#endif`;
- });
-}
-
-var renamedPropertiesByLayerType = {};
-
-for (var layer of layers) {
- layer.properties = _.concat(layer.layoutProperties, layer.paintProperties);
- let enumProperties = _.filter(layer.properties, prop => definesEnum(prop, layer.properties));
- if (enumProperties.length) {
- layer.enumProperties = enumProperties;
- }
-
- let renamedProperties = {};
- _.assign(renamedProperties, _.filter(layer.properties, prop => 'original' in prop || 'getter' in prop));
- if (!_.isEmpty(renamedProperties)) {
- renamedPropertiesByLayerType[layer.type] = renamedProperties;
- }
-
- writeIfModified(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.h`, duplicatePlatformDecls(layerH(layer)));
- writeIfModified(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}_Private.h`, duplicatePlatformDecls(layerPrivateH(layer)));
- writeIfModified(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.mm`, layerM(layer));
- writeIfModified(`platform/darwin/test/${prefix}${camelize(layer.type)}${suffix}Tests.mm`, testLayers(layer));
-}
-
-// Extract examples for guides from unit tests.
-let examplesSrc = fs.readFileSync('platform/darwin/test/MGLDocumentationGuideTests.swift', 'utf8');
-const exampleRegex = /func test([\w$]+)\s*\(\)\s*\{[^]*?\n([ \t]+)\/\/#-example-code\n([^]+?)\n\2\/\/#-end-example-code\n/gm;
-
-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;
-}
-
-global.guideExample = function (guide, exampleId, os) {
- // Get the contents of the test method whose name matches the symbol path.
- let testMethodName = `${guide}$${exampleId}`;
- let example = examples[testMethodName];
- if (!example) {
- console.error(`MGLDocumentationExampleTests.test${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\b\n?/gm,
- function (m, indentation, ifOs, ifCase, elseCase) {
- return (os === ifOs ? ifCase : elseCase).replace(new RegExp('^ ', 'gm'), '');
- }).replace(/\n$/, '');
-
- return '```swift\n' + example + '\n```';
-};
-
-writeIfModified(`platform/ios/docs/guides/For Style Authors.md`, forStyleAuthorsMD({
- os: 'iOS',
- renamedProperties: renamedPropertiesByLayerType,
- layers: layers,
-}));
-writeIfModified(`platform/macos/docs/guides/For Style Authors.md`, forStyleAuthorsMD({
- os: 'macOS',
- renamedProperties: renamedPropertiesByLayerType,
- layers: layers,
-}));
-writeIfModified(`platform/ios/docs/guides/Migrating to Expressions.md`, ddsGuideMD({
- os: 'iOS',
-}));
-writeIfModified(`platform/macos/docs/guides/Migrating to Expressions.md`, ddsGuideMD({
- os: 'macOS',
-}));
-writeIfModified(`platform/ios/docs/guides/Tile URL Templates.md`, templatesMD({
- os: 'iOS',
-}));
-writeIfModified(`platform/macos/docs/guides/Tile URL Templates.md`, templatesMD({
- os: 'macOS',
-}));
diff --git a/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json b/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
deleted file mode 100644
index c781879bc5..0000000000
--- a/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "layout_symbol": {
- "icon-allow-overlap": "icon-allows-overlap",
- "icon-image": "icon-image-name",
- "icon-ignore-placement": "icon-ignores-placement",
- "icon-keep-upright": "keeps-icon-upright",
- "icon-optional": "is-icon-optional",
- "icon-rotate": "icon-rotation",
- "icon-size": "icon-scale",
- "symbol-avoid-edges": "symbol-avoids-edges",
- "text-allow-overlap": "text-allows-overlap",
- "text-field": "text",
- "text-font": "text-font-names",
- "text-ignore-placement": "text-ignores-placement",
- "text-justify": "text-justification",
- "text-keep-upright": "keeps-text-upright",
- "text-max-angle": "maximum-text-angle",
- "text-max-width": "maximum-text-width",
- "text-optional": "is-text-optional",
- "text-rotate": "text-rotation",
- "text-size": "text-font-size",
- "text-writing-mode": {"name": "text-writing-modes", "enumName": "text-writing-mode"}
- },
- "paint_circle": {
- "circle-pitch-scale": "circle-scale-alignment",
- "circle-translate": "circle-translation",
- "circle-translate-anchor": "circle-translation-anchor"
- },
- "paint_fill": {
- "fill-antialias": "is-fill-antialiased",
- "fill-translate": "fill-translation",
- "fill-translate-anchor": "fill-translation-anchor"
- },
- "paint_fill-extrusion": {
- "fill-extrusion-translate": "fill-extrusion-translation",
- "fill-extrusion-translate-anchor": "fill-extrusion-translation-anchor",
- "fill-extrusion-vertical-gradient": "fill-extrusion-has-vertical-gradient"
- },
- "paint_raster": {
- "raster-brightness-min": "minimum-raster-brightness",
- "raster-brightness-max": "maximum-raster-brightness",
- "raster-hue-rotate": "raster-hue-rotation",
- "raster-resampling": "raster-resampling-mode"
- },
- "paint_line": {
- "line-dasharray": "line-dash-pattern",
- "line-translate": "line-translation",
- "line-translate-anchor": "line-translation-anchor"
- },
- "paint_symbol": {
- "icon-translate": "icon-translation",
- "icon-translate-anchor": "icon-translation-anchor",
- "text-translate": "text-translation",
- "text-translate-anchor": "text-translation-anchor"
- }
-} \ No newline at end of file
diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json
deleted file mode 100644
index 0ba2b77dc5..0000000000
--- a/platform/darwin/scripts/style-spec-overrides-v8.json
+++ /dev/null
@@ -1,148 +0,0 @@
-{
- "light-cocoa-doc": "An `MGLLight` object represents the light source for extruded geometries in `MGLStyle`.\n\n### Example\n```swift\n```\n\n#### Related examples\nSee the <a href=\"https://docs.mapbox.com/ios/maps/examples/light-example/\">Adjust light of 3D buildings</a> to learn how to create and modify the light source for 3D geometries.",
- "light": {
- "position": {
- "doc": "Position of the `MGLLight` source relative to lit (extruded) geometries, in a `MGLSphericalPosition` struct [radial coordinate, azimuthal angle, polar angle] where radial indicates the distance from the center of the base of an object to its light, azimuthal indicates the position of the light relative to 0° (0° when `MGLLight.anchor` is set to `MGLLightAnchorViewport` corresponds to the top of the viewport, or 0° when `MGLLight.anchor` is set to `MGLLightAnchorMap` corresponds to due north, and degrees proceed clockwise), and polar indicates the height of the light (from 0°, directly above, to 180°, directly below).",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/light-example/\">Adjust light of 3D buildings</a> example to learn how to create and modify the position of value of an `MGLLight` object for 3D geometries."
- }
- },
- "layer": {
- "type": {
- "values": {
- "fill": {
- "doc": "An `MGLFillStyleLayer` is a style layer that renders one or more filled (and optionally stroked) polygons on the map.\n\nUse a fill style layer to configure the visual appearance of polygon or multipolygon features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/select-layer/\">Select a feature within a layer</a> example to learn how to use a `TERNARY` expression to modify the `fillOpacity` of an `MGLFillStyleLayer` object. See the <a href=\"https://docs.mapbox.com/ios/maps/examples/fill-pattern/\">Add a pattern to a polygon</a> example to learn how to use an image to add pattern to the features styled by a `MGLFillStyleLayer`."
- },
- "fill-extrusion": {
- "doc": "An `MGLFillExtrusionStyleLayer` is a style layer that renders one or more 3D extruded polygons on the map.\n\nUse a fill-extrusion style layer to configure the visual appearance of polygon or multipolygon features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/extrusions/\">Display 3D buildings</a> example to learn how to add and style 3D layers on a map."
- },
- "line": {
- "doc": "An `MGLLineStyleLayer` is a style layer that renders one or more stroked polylines on the map.\n\nUse a line style layer to configure the visual appearance of polyline or multipolyline features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or `MGLMultiPolylineFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/shape-collection/\">Add multiple shapes from a single shape source</a> example to learn how to add a line to your map using this style layer. See the <a href=\"https://docs.mapbox.com/ios/maps/examples/runtime-add-line/\">Add a line style layer from GeoJSON</a> example to learn how to add and style line data to an `MGLMapView` object at runtime."
- },
- "symbol": {
- "doc": "An `MGLSymbolStyleLayer` is a style layer that renders icon and text labels at points or along lines on the map.\n\nUse a symbol style layer to configure the visual appearance of feature labels. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLShape` or `MGLFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/runtime-multiple-annotations/\">Dynamically style interactive points</a> and <a href=\"https://docs.mapbox.com/ios/maps/examples/clustering-with-images/\">Use images to cluster point data</a> examples learn how to style data on your map using this layer."
- },
- "circle": {
- "doc": "An `MGLCircleStyleLayer` is a style layer that renders one or more filled circles on the map.\n\nUse a circle style layer to configure the visual appearance of point or point collection features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.\n\nA circle style layer renders circles whose radii are measured in screen units. To display circles on the map whose radii correspond to real-world distances, use many-sided regular polygons and configure their appearance using an `MGLFillStyleLayer` object.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/dds-circle-layer/\">Data-driven circles</a>, <a href=\"https://docs.mapbox.com/ios/maps/examples/shape-collection/\">Add multiple shapes from a single shape source</a>, and <a href=\"https://docs.mapbox.com/ios/maps/examples/clustering/\">Cluster point data</a> examples to learn how to add circles to your map using this style layer."
- },
- "heatmap": {
- "doc": "An `MGLHeatmapStyleLayer` is a style layer that renders a <a href=\"https://en.wikipedia.org/wiki/Heat_map\">heatmap</a>.\n\nA heatmap visualizes the spatial distribution of a large, dense set of point data, using color to avoid cluttering the map with individual points at low zoom levels. The points are weighted by an attribute you specify. Use a heatmap style layer in conjunction with point or point collection features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.\n\nConsider accompanying a heatmap style layer with an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer` at high zoom levels. If you are unsure whether the point data in an `MGLShapeSource` is dense enough to warrant a heatmap, you can alternatively cluster the source using the `MGLShapeSourceOptionClustered` option and render the data using an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer`.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/heatmap-example/\">Create a heatmap layer</a> example to learn how to add this style layer to your map."
- },
- "raster": {
- "doc": "An `MGLRasterStyleLayer` is a style layer that renders georeferenced raster imagery on the map, especially raster tiles.\n\nUse a raster style layer to configure the color parameters of raster tiles loaded by an `MGLRasterTileSource` object or raster images loaded by an `MGLImageSource` object. For example, you could use a raster style layer to render <a href=\"https://www.mapbox.com/satellite/\">Mapbox Satellite</a> imagery, a <a href=\"https://docs.mapbox.com/help/glossary/tileset/#raster-tilesets\">raster tile set</a> uploaded to Mapbox Studio, or a raster map authored in <a href=\"https://tilemill-project.github.io/tilemill/\">TileMill</a>, the classic Mapbox Editor, or Mapbox Studio Classic.\n\nRaster images may also be used as icons or patterns in a style layer. To register an image for use as an icon or pattern, use the `-[MGLStyle setImage:forName:]` method. To configure a point annotation’s image, use the `MGLAnnotationImage` class.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/image-source/\">Add an image</a> and <a href=\"https://docs.mapbox.com/ios/maps/examples/source-custom-raster/\">Add raster imagery</a> examples to learn how to add imagery with this style layer."
- },
- "hillshade": {
- "doc": "An `MGLHillshadeStyleLayer` is a style layer that renders raster <a href=\"https://en.wikipedia.org/wiki/Digital_elevation_model\">digital elevation model</a> (DEM) tiles on the map.\n\nUse a hillshade style layer to configure the color parameters of raster tiles loaded by an `MGLRasterDEMSource` object. For example, you could use a hillshade style layer to render <a href=\"https://docs.mapbox.com/help/troubleshooting/access-elevation-data/#mapbox-terrain-rgb\">Mapbox Terrain-RGB</a> data.\n\nTo display posterized hillshading based on vector shapes, as with the <a href=\"https://www.mapbox.com/vector-tiles/mapbox-terrain/\">Mapbox Terrain</a> source, use an `MGLVectorTileSource` object in conjunction with several `MGLFillStyleLayer` objects."
- },
- "background": {
- "doc": "An `MGLBackgroundStyleLayer` is a style layer that covers the entire map. Use a background style layer to configure a color or pattern to show below all other map content. If the style’s other layers use the Mapbox Streets source, the background style layer is responsible for drawing land, whereas the oceans and other bodies of water are drawn by `MGLFillStyleLayer` objects.\n\nA background style layer is typically the bottommost layer in a style, because it covers the entire map and can occlude any layers below it. You can therefore access it by getting the last item in the `MGLStyle.layers` array.\n\nIf the background style layer is transparent or omitted from the style, any portion of the map view that does not show another style layer is transparent."
- }
- }
- }
- },
- "layout_symbol": {
- "symbol-z-order": {
- "values": {
- "viewport-y": {
- "doc": "Specify this z order if symbols’ appearance relies on lower features overlapping higher features. For example, symbols with a pin-like appearance would require this z order."
- },
- "source": {
- "doc": "Specify this z order if the order in which features appear in the source is significant."
- }
- }
- },
- "icon-text-fit-padding": {
- "doc": "Size of the additional area added to dimensions determined by `icon-text-fit`."
- },
- "icon-offset": {
- "doc": "Offset distance of icon from its anchor."
- },
- "icon-image": {
- "doc": "Name of a style image to use for drawing an image background.\n\nUse the `+[MGLStyle setImage:forName:]` method to associate an image with a name that you can set this property to.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/clustering-with-images/\">Use images to cluster point data</a> example to learn how to dynamically set your icons with an expression."
- },
- "text-field": {
- "doc": "Value to use for a text label.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions.",
- "examples": "See the <a href=\"https://docs.mapbox.com/ios/maps/examples/clustering/\">Cluster point data</a> and <a href=\"https://docs.mapbox.com/ios/maps/examples/clustering-with-images/\">Use images to cluster point data</a> to learn how to use an expression to set this attribute to the number of markers within a cluster."
- },
- "text-font": {
- "doc": "An array of font face names used to display the text.\n\nEach font name must be included in the `{fontstack}` portion of the JSON stylesheet’s <a href=\"https://www.mapbox.com/mapbox-gl-style-spec/#glyphs\"><code>glyphs</code></a> property. You can register a custom font when designing the style in Mapbox Studio. Fonts installed on the system are not used.\n\nThe first font named in the array is applied to the text. For each character in the text, if the first font lacks a glyph for the character, the next font is applied as a fallback, and so on."
- },
- "text-offset": {
- "doc": "Offset distance of text from its anchor."
- },
- "text-transform": {
- "doc": "Specifies how to capitalize text."
- }
- },
- "paint_background": {
- "background-pattern": {
- "doc": "Name of image in style images to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512)."
- }
- },
- "paint_fill": {
- "fill-pattern": {
- "doc": "Name of image in style images to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512)."
- }
- },
- "paint_fill-extrusion": {
- "fill-extrusion-pattern": {
- "doc": "Name of image in style images to use for drawing image fill-extrusions. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512)."
- },
- "fill-extrusion-translate": {
- "doc": "The geometry's offset."
- },
- "fill-extrusion-color": {
- "doc": "The base color of this layer. The extrusion's surfaces will be shaded differently based on this color in combination with the `light` settings. If this color is specified with an alpha component, the alpha component will be ignored; use `fill-extrusion-opacity` to set layer opacityco."
- }
- },
- "paint_heatmap": {
- "heatmap-color": {
- "doc": "The color of each screen point based on its density value in a heatmap. This property is normally set to an interpolation or step expression with the `$heatmapDensity` value as its input."
- }
- },
- "paint_line": {
- "line-gradient": {
- "doc": "The color gradient with which the line will be drawn. This property only has an effect on lines defined by an `MGLShapeSource` whose `MGLShapeSourceOptionLineDistanceMetrics` option is set to `YES`."
- },
- "line-pattern": {
- "doc": "Name of image in style images to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512)."
- },
- "line-translate": {
- "doc": "The geometry's offset."
- }
- },
- "paint_circle": {
- "circle-translate": {
- "doc": "The geometry's offset."
- }
- },
- "paint_fill": {
- "fill-translate": {
- "doc": "The geometry's offset."
- },
- "fill-color": {
- "doc": "The color of the filled part of this layer."
- }
- },
- "paint_symbol": {
- "icon-color": {
- "doc": "The tint color to apply to the icon. The `icon-image-name` property must be set to a template image."
- },
- "icon-halo-color": {
- "doc": "The color of the icon’s halo. The `icon-image-name` property must be set to a template image."
- },
- "icon-translate": {
- "doc": "Distance that the icon's anchor is moved from its original placement."
- },
- "text-translate": {
- "doc": "Distance that the text's anchor is moved from its original placement."
- }
- }
-}
diff --git a/platform/darwin/scripts/update-examples.js b/platform/darwin/scripts/update-examples.js
deleted file mode 100755
index 885b26248c..0000000000
--- a/platform/darwin/scripts/update-examples.js
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/env node
-'use strict';
-
-const fs = require('fs');
-const execFileSync = require('child_process').execFileSync;
-const _ = require('lodash');
-
-require('../../../scripts/style-code');
-
-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, { maxBuffer: Infinity }).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.test${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\b\n?/gm,
- function (m, indentation, ifOs, ifCase, elseCase) {
- return (os === ifOs ? ifCase : elseCase).replace(new RegExp('^ ', 'gm'), '');
- }).replace(/\n$/, '');
-
- // 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.
- writeIfModified(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');