Skip to content

Instantly share code, notes, and snippets.

@niksurff
Last active February 12, 2017 14:17
Show Gist options
  • Save niksurff/e3abd7dfc8bbe9d9c073 to your computer and use it in GitHub Desktop.
Save niksurff/e3abd7dfc8bbe9d9c073 to your computer and use it in GitHub Desktop.
A hacked together http://www.getmdl.io/components/index.html scraper for automating creation of components for nikvm/material-design-react
var scrapeMDLComponents = require('./scrape-mdl-components');
var parseScrapeData = require('./parse-scrape-data');
var fs = require('fs');
scrapeMDLComponents()
.then(function(data) {
var parsed = parseScrapeData(data);
fs.writeFileSync('./parsed.json', JSON.stringify(parsed, null, 2))
return Promise.resolve(parsed);
})
// .then(function(components) {
// _.forEach(components, function(co) {
// // saveComponent(co);
// });
// })
.catch(function(err) {
throw new Error(err);
});
var _ = require('lodash');
var PREFIX = 'mdl-'
var JS_PREFIX = 'js-'
var KEBAB_STRING = '[a-z]+(?:-[a-z]+)*'
var BEM_BLOCK = PREFIX + '(?!' + JS_PREFIX + ')' + '(' + KEBAB_STRING + ')'; // $1 = block
var BEM_ELEMENT = BEM_BLOCK + '__(' + KEBAB_STRING + ')'; // $1 = block, $2 = element
var BEM_BLOCK_MODIFIER = BEM_BLOCK + '--(' + KEBAB_STRING + ')'; // $1 = block, $2 = modifier
var BEM_ELEMENT_MODIFIER = BEM_ELEMENT + '--(' + KEBAB_STRING + ')'; // $1 = block, $2 = element, $3 = modifier
var JS_BLOCK = PREFIX + JS_PREFIX + '(' + KEBAB_STRING + ')'; // $1 = js-block
var GLOBAL_MODIFIER = '((?!' + PREFIX + ')[a-z-]+)'; // $1 = modifier
function pascalCase(str) {
return _.capitalize(_.camelCase(str));
}
function parseScrapeData(data) {
return _(data)
.map(parseConfig)
.flatten()
.value();
}
function parseConfig(config) {
var components = parseBlocks(config);
var elements = parseElements(config);
var blockModifiers = parseBlockModifiers(config);
var elementModifiers = parseElementModifiers(config);
var jsBlocks = parseJsBlocks(config);
var globalModifiers = parseGlobalModifiers(config);
var elementsWithModifiers = _(elements)
.map(function(el) {
return _.merge(el, {
modifiers: _.where(
elementModifiers,
{componentName: el.componentName}
)
});
})
.map(function(el) {
var parentModifiers = _.where(
blockModifiers,
{componentName: el.parentComponentName}
);
return _.merge(el, {
maybeModifiers: _.merge(parentModifiers, globalModifiers)
});
})
.value();
return _(components)
.map(function addJSClassName(co) {
var jsBlock = _.findWhere(
jsBlocks,
{componentName: co.componentName}
);
if (jsBlock) {
co.className = co.className + ' ' + jsBlock.className;
}
return co;
})
.map(function addChildren(co) {
return _.merge(co, {
children: _.where(
elementsWithModifiers,
{parentComponentName: co.componentName}
)
});
})
.map(function addComponentModifiers(co) {
return _.merge(co, {
modifiers: _.where(
blockModifiers,
{componentName: co.componentName}
)
});
})
.map(function addGlobalModifiers(co) {
co.modifiers = _.merge(co.modifiers, globalModifiers);
return co;
})
.value()
}
function parseBlocks(config) {
return _(config)
.map(function(str) {
var match = str.match('^' + BEM_BLOCK + '$')
return match
})
.compact()
.map(function(arr) {
return {
className: arr[0],
componentName: pascalCase(arr[1])
}
})
.value();
}
function parseElements(config) {
return _(config)
.map(function(str) {
return str.match('^' + BEM_ELEMENT + '$')
})
.compact()
.map(function(arr) {
return {
className: arr[0],
parentComponentName: pascalCase(arr[1]),
componentName: pascalCase(arr[1]) + pascalCase(arr[2])
}
})
.value();
}
function parseBlockModifiers(config) {
return _(config)
.map(function(str) {
return str.match('^' + BEM_BLOCK_MODIFIER + '$')
})
.compact()
.map(function(arr) {
return {
className: arr[0],
componentName: pascalCase(arr[1]),
modifierName: _.camelCase(arr[2])
}
})
.value();
}
function parseElementModifiers(config) {
return _(config)
.map(function(str) {
return str.match('^' + BEM_ELEMENT_MODIFIER + '$')
})
.compact()
.map(function(arr) {
return {
className: arr[0],
parentComponentName: pascalCase(arr[1]),
componentName: pascalCase(arr[1]) + pascalCase(arr[2]),
modifierName: _.camelCase(arr[3])
}
})
.value();
}
function parseJsBlocks(config) {
return _(config)
.map(function(str) {
return str.match('^' + JS_BLOCK + '$')
})
.compact()
.map(function(arr) {
// console.log(arr);
return {
className: arr[0],
componentName: pascalCase(arr[1])
}
})
.value();
}
function parseGlobalModifiers(config) {
return _(config)
.map(function(str) {
return str.match('^' + GLOBAL_MODIFIER + '$')
})
.compact()
.map(function(arr) {
return {
className: arr[0],
modifierName: _.camelCase(arr[1])
}
})
.value();
}
module.exports = parseScrapeData;
var Xray = require('x-ray');
var x = Xray();
/**
* Returns array of config classNames/ props
* @return {Promise} configs
*/
function scrapeMDLComponents() {
return new Promise(function(resolve, reject) {
x(
'http://www.getmdl.io/components/index.html',
x(
'.mdl-components__link@href',
x(
'#configuration-options + p + table tbody',
[['tr td:first-of-type code']]
)
)
)(function(err, data) {
if (err) return reject(err);
// console.log(data);
resolve(data);
});
});
}
module.exports = scrapeMDLComponents;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment