summaryrefslogtreecommitdiff
path: root/platform/darwin/scripts/generate-style-code.js
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2017-01-16 11:38:35 -0800
committerMinh Nguyễn <mxn@1ec5.org>2017-01-16 11:38:35 -0800
commit7ef2843e6a62116667be6a2c12de085951fdd5ea (patch)
tree40eca249e044e2706efd1193d617e6eb8e59d708 /platform/darwin/scripts/generate-style-code.js
parent76301b252cbc4bc3ae1fc84322bcbcdbd26cae8a (diff)
parent13b97dd0cebffe36b187bdb74923910def6bd87b (diff)
downloadqtlocation-mapboxgl-7ef2843e6a62116667be6a2c12de085951fdd5ea.tar.gz
Merge branch 'release-ios-v3.4.0' into 1ec5-release-ios-v3.4.0-beta.7
Diffstat (limited to 'platform/darwin/scripts/generate-style-code.js')
-rw-r--r--platform/darwin/scripts/generate-style-code.js327
1 files changed, 248 insertions, 79 deletions
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 6606c956f2..3998246580 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -55,17 +55,38 @@ _.forOwn(cocoaConventions, function (properties, kind) {
})
});
+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();
+ });
+};
+
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;
@@ -74,7 +95,87 @@ global.arrayType = function (property) {
global.testImplementation = function (property, layerType, isFunction) {
let helperMsg = testHelperMessage(property, layerType, isFunction);
return `layer.${objCName(property)} = [MGLRuntimeStylingHelper ${helperMsg}];`;
-}
+};
+
+global.objCTestValue = function (property, layerType, indent) {
+ let propertyName = originalPropertyName(property);
+ switch (property.type) {
+ case 'boolean':
+ return property.default ? '@NO' : '@YES';
+ case 'number':
+ return '@0xff';
+ case 'string':
+ return `@"${_.startCase(propertyName)}"`;
+ case 'enum':
+ let type = objCType(layerType, property.name);
+ let value = `${type}${camelize(_.last(_.keys(property.values)))}`;
+ return `[NSValue valueWith${type}:${value}]`;
+ 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': {
+ 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)}`;
+ }
+ case 'offset':
+ case 'translate':
+ 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)}`;
+ 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 '0xff';
+ case 'string':
+ 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';
+ }
+ let value = camelize(_.last(_.keys(property.values)));
+ 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 }';
+ default:
+ throw new Error(`unknown array type for ${property.name}`);
+ }
+ default:
+ throw new Error(`unknown type for ${property.name}`);
+ }
+};
global.testGetterImplementation = function (property, layerType, isFunction) {
let helperMsg = testHelperMessage(property, layerType, isFunction);
@@ -87,7 +188,7 @@ global.testGetterImplementation = function (property, layerType, isFunction) {
XCTAssertEqualObjects(gLayer.${objCName(property)}, ${value});`;
}
return `XCTAssertEqualObjects(gLayer.${objCName(property)}, ${value});`;
-}
+};
global.testHelperMessage = function (property, layerType, isFunction) {
let fnSuffix = isFunction ? 'Function' : '';
@@ -123,7 +224,7 @@ global.testHelperMessage = function (property, layerType, isFunction) {
}
};
-global.propertyDoc = function (propertyName, property, layerType) {
+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 `([^`]+?)`/g, function (m, peerPropertyName, propertyValue, offset, str) {
@@ -141,7 +242,7 @@ global.propertyDoc = function (propertyName, property, layerType) {
// Requires symbols to be surrounded by backticks.
doc = doc.replace(/`(.+?)`/g, function (m, symbol, offset, str) {
if ('values' in property && Object.keys(property.values).indexOf(symbol) !== -1) {
- let objCType = objCType(layerType, property.name);
+ let objCType = global.objCType(layerType, property.name);
return '`' + `${objCType}${camelize(symbol)}` + '`';
}
if (str.substr(offset - 4, 3) !== 'CSS') {
@@ -154,11 +255,33 @@ global.propertyDoc = function (propertyName, property, layerType) {
if (!property.units.match(/s$/)) {
property.units += 's';
}
- doc += `
-
- This property is measured in ${property.units}.`;
+ 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) {
+ 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.`;
+ }
}
- return doc.replace(/(p)ixel/gi, '$1oint').replace(/(\d)px\b/g, '$1pt');
+ return doc;
};
global.propertyReqs = function (property, propertiesByName, type) {
@@ -217,30 +340,32 @@ global.describeValue = function (value, property, layerType) {
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 '`MGLColor.clearColor`';
+ return '`UIColor.clearColor`';
}
if (color.r === 0 && color.g === 0 && color.b === 0 && color.a === 1) {
- return '`MGLColor.blackColor`';
+ return '`UIColor.blackColor`';
}
if (color.r === 1 && color.g === 1 && color.b === 1 && color.a === 1) {
- return '`MGLColor.whiteColor`';
+ return '`UIColor.whiteColor`';
}
- return 'an `MGLColor`' + ` object whose RGB value is ${color.r}, ${color.g}, ${color.b} and whose alpha value is ${color.a}`;
+ return 'a `UIColor`' + ` object whose RGB value is ${color.r}, ${color.g}, ${color.b} and whose alpha value is ${color.a}`;
case 'array':
let units = property.units || '';
if (units) {
units = ` ${units}`.replace(/pixel/, 'point');
}
- if (property.name.indexOf('padding') !== -1) {
- if (value[0] === 0 && value[1] === 0 && value[2] === 0 && value[3] === 0) {
- return 'an `NSValue` object containing `NSEdgeInsetsZero` or `UIEdgeInsetsZero`';
- }
- return 'an `NSValue` object containing an `NSEdgeInsets` or `UIEdgeInsets` struct set to' + ` ${value[0]}${units} on the top, ${value[3]}${units} on the left, ${value[2]}${units} on the bottom, and ${value[1]}${units} on the right`;
- }
- if (property.name.indexOf('offset') !== -1 || property.name.indexOf('translate') !== -1) {
- return 'an `NSValue` object containing a `CGVector` struct set to' + ` ${value[0]}${units} from the left and ${value[1]}${units} from the top`;
+ 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' + ` ${value[0]}${units} on the top, ${value[3]}${units} on the left, ${value[2]}${units} on the bottom, and ${value[1]}${units} on the right`;
+ case 'offset':
+ case 'translate':
+ return 'an `NSValue` object containing a `CGVector` struct set to' + ` ${value[0]}${units} rightward and ${value[1]}${units} downward`;
+ default:
+ return 'the array `' + value.join('`, `') + '`';
}
- return 'the array `' + value.join('`, `') + '`';
default:
throw new Error(`unknown type for ${property.name}`);
}
@@ -252,7 +377,7 @@ global.propertyDefault = function (property, layerType) {
global.originalPropertyName = function (property) {
return property.original || property.name;
-}
+};
global.propertyType = function (property) {
switch (property.type) {
@@ -317,100 +442,144 @@ global.valueTransformerArguments = function (property) {
}
};
+global.mbglType = function(property) {
+ switch (property.type) {
+ case 'boolean':
+ return 'bool';
+ case 'number':
+ return 'float';
+ case 'string':
+ return 'std::string';
+ case 'enum': {
+ let type = camelize(originalPropertyName(property));
+ if (/-translate-anchor$/.test(originalPropertyName(property))) {
+ type = 'TranslateAnchor';
+ }
+ if (/-(rotation|pitch)-alignment$/.test(originalPropertyName(property))) {
+ type = 'Alignment';
+ }
+ 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>';
+ 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);`
-}
-
-global.mbglType = function(property) {
- let mbglType = camelize(originalPropertyName(property)) + 'Type';
- if (/-translate-anchor$/.test(originalPropertyName(property))) {
- mbglType = 'TranslateAnchorType';
- }
- if (/-(rotation|pitch)-alignment$/.test(originalPropertyName(property))) {
- mbglType = 'AlignmentType';
- }
- return mbglType;
-}
+ return `_layer->setSourceLayer(sourceLayer.UTF8String);`
+};
const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.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.m.ejs', 'utf8'), { strict: true});
-const categoryH = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs', 'utf8'), { strict: true});
-const categoryM = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs', 'utf8'), { strict: true});
+const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.mm.ejs', 'utf8'), { strict: true});
+const guideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true });
-const layers = Object.keys(spec.layer.type.values).map((type) => {
- const layoutProperties = Object.keys(spec[`layout_${type}`]).reduce((memo, name) => {
+const layers = _(spec.layer.type.values).map((value, layerType) => {
+ const layoutProperties = Object.keys(spec[`layout_${layerType}`]).reduce((memo, name) => {
if (name !== 'visibility') {
- spec[`layout_${type}`][name].name = name;
- memo.push(spec[`layout_${type}`][name]);
+ spec[`layout_${layerType}`][name].name = name;
+ memo.push(spec[`layout_${layerType}`][name]);
}
return memo;
}, []);
- const paintProperties = Object.keys(spec[`paint_${type}`]).reduce((memo, name) => {
- spec[`paint_${type}`][name].name = name;
- memo.push(spec[`paint_${type}`][name]);
+ 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 {
- type: type,
+ doc: spec.layer.type.values[layerType].doc,
+ type: layerType,
layoutProperties: _.sortBy(layoutProperties, ['name']),
paintProperties: _.sortBy(paintProperties, ['name']),
- layoutPropertiesByName: spec[`layout_${type}`],
- paintPropertiesByName: spec[`paint_${type}`],
};
-});
+}).sortBy(['type']).value();
function duplicatePlatformDecls(src) {
- // Look for a documentation comment that contains “MGLColor” and the
- // subsequent function, method, or property declaration. Try not to match
- // greedily.
- return src.replace(/(\/\*\*(?:\*[^\/]|[^*])*?\bMGLColor\b[\s\S]*?\*\/)(\s*.+?;)/g,
+ // 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(/(\/\*\*(?:\*[^\/]|[^*])*?\*\/)(\s*[^;]+?\b(?:MGL|NS|UI)(?:Color|EdgeInsets(?:Zero)?)\b[^;]+?;)/g,
(match, comment, decl) => {
- let iosComment = comment.replace(/\bMGLColor\b/g, 'UIColor')
+ let macosComment = comment.replace(/\b(?:MGL|UI)(Color|EdgeInsets(?:Zero)?)\b/g, 'NS$1')
// Use the correct indefinite article.
- .replace(/\b(a)n(\s+`?UIColor)\b/gi, '$1$2');
- let macosComment = comment.replace(/\bMGLColor\b/g, 'NSColor');
+ .replace(/\ba(\s+`?NS(?:Color|EdgeInsets))\b/gi, 'an$1');
+ let iosDecl = decl.replace(/\bMGL(Color|EdgeInsets)\b/g, 'UI$1');
+ let macosDecl = decl.replace(/\b(?:MGL|UI)(Color|EdgeInsets)\b/g, 'NS$1');
return `\
#if TARGET_OS_IPHONE
-${iosComment}${decl}
+${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 allLayoutProperties = [];
-var allPaintProperties = [];
-var allTypes = [];
+var renamedPropertiesByLayerType = {};
for (var layer of layers) {
- allLayoutProperties.push(layer.layoutProperties);
- allPaintProperties.push(layer.paintProperties);
- allTypes.push(layer.type);
- const containsEnumerationProperties = _.filter(layer.layoutProperties, function(property){ return property["type"] === "enum"; }).length || _.filter(layer.paintProperties, function(property){ return property["type"] === "enum"; }).length;
- layer.containsEnumerationProperties = containsEnumerationProperties;
+ layer.properties = _.concat(layer.layoutProperties, layer.paintProperties);
+ let enumProperties = _.filter(layer.properties, prop => prop.type === 'enum');
+ 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}.mm`, layerM(layer));
- writeIfModified(`platform/darwin/test/${prefix}${camelize(layer.type)}${suffix}Tests.m`, testLayers(layer));
+ fs.writeFileSync(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.h`, duplicatePlatformDecls(layerH(layer)));
+ fs.writeFileSync(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.mm`, layerM(layer));
+ fs.writeFileSync(`platform/darwin/test/${prefix}${camelize(layer.type)}${suffix}Tests.mm`, testLayers(layer));
}
-fs.writeFileSync(`platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h`, categoryH({
- layoutProperties: _.flatten(allLayoutProperties),
- paintProperties: _.flatten(allPaintProperties),
- types: allTypes
+fs.writeFileSync(`platform/ios/docs/guides/For Style Authors.md`, guideMD({
+ os: 'iOS',
+ renamedProperties: renamedPropertiesByLayerType,
+ layers: layers,
}));
-fs.writeFileSync(`platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm`, categoryM({
- layoutProperties: _.flatten(allLayoutProperties),
- paintProperties: _.flatten(allPaintProperties)
+fs.writeFileSync(`platform/macos/docs/guides/For Style Authors.md`, guideMD({
+ os: 'macOS',
+ renamedProperties: renamedPropertiesByLayerType,
+ layers: layers,
}));