@mapbox/react-native-mapbox-gl
Version:
A Mapbox GL react native module for creating custom maps
238 lines (190 loc) • 6.88 kB
JavaScript
require('./autogenHelpers/globals');
const fs = require('fs');
const path = require('path');
const styleSpecJSON = require('../style-spec/v8.json');
const ejs = require('ejs');
const DocJSONBuilder = require('./autogenHelpers/DocJSONBuilder');
const MarkdownBuilder = require('./autogenHelpers/MarkdownBuilder');
if (!styleSpecJSON) {
console.log('Could not find style spec, try running "yarn run fetch:style:spec"');
process.exit(1);
}
const layers = [];
const androidVersion = "5.1.3";
const iosVersion = "3.6.1";
const TMPL_PATH = path.join(__dirname, 'templates');
const IOS_OUTPUT_PATH = path.join(__dirname, '..', 'example', 'node_modules', '@mapbox', 'react-native-mapbox-gl', 'ios', 'RCTMGL');
const ANDROID_OUTPUT_PATH = path.join(__dirname, '..', 'example', 'node_modules', '@mapbox', 'react-native-mapbox-gl', 'android', 'rctmgl', 'src', 'main', 'java', 'com', 'mapbox', 'rctmgl', 'components', 'styles');
const JS_OUTPUT_PATH = path.join(__dirname, '..', 'example', 'node_modules', '@mapbox', 'react-native-mapbox-gl', 'javascript', 'utils');
Object.keys(styleSpecJSON.layer.type.values).forEach((layerName) => {
layers.push({
name: layerName,
properties: getPropertiesForLayer(layerName),
});
});
// add light as a layer
layers.push({ name: 'light', properties: getPropertiesForLight() })
function getPropertiesForLight () {
const lightAttributes = styleSpecJSON.light;
const lightProps = getSupportedProperties(lightAttributes).map((attrName) => {
return Object.assign({}, buildProperties(lightAttributes, attrName), {
allowedFunctionTypes: [],
});
});
return lightProps;
}
function getPropertiesForLayer (layerName) {
const paintAttributes = styleSpecJSON[`paint_${layerName}`];
const layoutAttributes = styleSpecJSON[`layout_${layerName}`];
const paintProps = getSupportedProperties(paintAttributes).map((attrName) => {
let prop = buildProperties(paintAttributes, attrName);
// overrides
if (['line-width'].includes(attrName)) {
prop.allowedFunctionTypes = ['camera'];
}
return prop;
});
const layoutProps = getSupportedProperties(layoutAttributes).map((attrName) => {
let prop = buildProperties(layoutAttributes, attrName);
// overrides
if (['line-join', 'text-max-width', 'text-letter-spacing', 'text-anchor', 'text-justify'].includes(attrName)) {
prop.allowedFunctionTypes = ['camera'];
}
return prop;
});
return layoutProps.concat(paintProps);
}
function getSupportedProperties (attributes) {
return Object.keys(attributes).filter((attrName) => isAttrSupported(attributes[attrName]));
}
function buildProperties (attributes, attrName) {
return {
name: camelCase(attrName),
doc: {
description: formatDescription(attributes[attrName].doc),
requires: getRequires(attributes[attrName].requires),
disabledBy: getDisables(attributes[attrName].requires),
values: attributes[attrName].values,
},
type: attributes[attrName].type,
value: attributes[attrName].value,
image: isImage(attrName),
translate: isTranslate(attrName),
transition: attributes[attrName].transition,
support: getAttributeSupport(attributes[attrName]['sdk-support']),
allowedFunctionTypes: getAllowedFunctionTypes(attributes[attrName]),
};
}
function formatDescription (description) {
let words = description.split(' ');
for (let i = 0; i < words.length; i++) {
const word = words[i];
if (word.includes('-')) {
words[i] = camelCase(word);
}
}
let formattedDescription = words.join(' ');
return formattedDescription.replace(/\[x, y\]/g, '`{ x: number, y: number }`');
}
function getRequires (requiredItems) {
let items = [];
if (!requiredItems) {
return items;
}
for (let item of requiredItems) {
if (typeof item === 'string') {
items.push(camelCase(item, '-'));
}
}
return items;
}
function getDisables (disabledItems) {
let items = [];
if (!disabledItems) {
return items;
}
for (let item of disabledItems) {
if (item['!']) {
items.push(camelCase(item['!'], '-'));
}
}
return items;
}
function isImage (attrName) {
return attrName.toLowerCase().indexOf('pattern') !== -1 || attrName.toLowerCase().indexOf('image') !== -1;
}
function isTranslate (attrName) {
return attrName.toLowerCase().indexOf('translate') !== -1;
}
function isAttrSupported (attr) {
const support = getAttributeSupport(attr['sdk-support']);
return support.basic.android && support.basic.ios;
}
function getAttributeSupport (sdkSupport) {
let support = {
basic: { android: false, ios: false },
data: { android: false, ios: false },
};
const basicSupport = sdkSupport['basic functionality'];
if (basicSupport.android) {
support.basic.android = isVersionGTE(androidVersion, basicSupport.android);
}
if (basicSupport.ios) {
support.basic.ios = isVersionGTE(iosVersion, basicSupport.ios);
}
const dataDrivenSupport = sdkSupport['data-driven styling'];
if (dataDrivenSupport && dataDrivenSupport.android) {
support.data.android = isVersionGTE(androidVersion, dataDrivenSupport.android);
}
if (dataDrivenSupport && dataDrivenSupport.ios) {
support.data.ios = isVersionGTE(iosVersion, dataDrivenSupport.ios);
}
if (support.data.ios !== true || support.data.android !== true) {
support.data.ios = false;
support.data.android = false;
}
return support;
}
function isVersionGTE(version, otherVersion) {
const v = +version.split('.').join('');
const ov = +otherVersion.split('.').join('');
return v >= ov;
}
function getAllowedFunctionTypes (paintAttr) {
const allowedFunctionTypes = [];
if (paintAttr['zoom-function']) {
allowedFunctionTypes.push('camera');
}
if (paintAttr['property-function']) {
allowedFunctionTypes.push('source');
allowedFunctionTypes.push('composite');
}
return allowedFunctionTypes;
}
// autogenerate code
[
{
input: path.join(TMPL_PATH, 'RCTMGLStyle.h.ejs'),
output: path.join(IOS_OUTPUT_PATH, 'RCTMGLStyle.h'),
},
{
input: path.join(TMPL_PATH, 'RCTMGLStyle.m.ejs'),
output: path.join(IOS_OUTPUT_PATH, 'RCTMGLStyle.m'),
},
{
input: path.join(TMPL_PATH, 'RCTMGLStyleFactory.java.ejs'),
output: path.join(ANDROID_OUTPUT_PATH, 'RCTMGLStyleFactory.java'),
},
{
input: path.join(TMPL_PATH, 'styleMap.js.ejs'),
output: path.join(JS_OUTPUT_PATH, 'styleMap.js'),
}
].forEach(({ input, output }) => {
console.log(`Generating ${output.split('/').pop()}`);
const tmpl = ejs.compile(fs.readFileSync(input, 'utf8'), { strict: true });
fs.writeFileSync(output, tmpl({ layers: layers }));
})
// autogenerate docs
const docBuilder = new DocJSONBuilder(layers);
const markdownBuilder = new MarkdownBuilder();
docBuilder.generate().then(() => markdownBuilder.generate());