Travis build: 407
This commit is contained in:
@ -2,164 +2,150 @@ const fs = require('fs-extra'),
|
||||
path = require('path'),
|
||||
{ red } = require('kleur'),
|
||||
crypto = require('crypto'),
|
||||
frontmatter = require('front-matter');
|
||||
const sass = require('node-sass');
|
||||
const caniuseDb = require('caniuse-db/data.json');
|
||||
const config = require('../../config');
|
||||
frontmatter = require('front-matter')
|
||||
const sass = require('node-sass')
|
||||
const caniuseDb = require('caniuse-db/data.json')
|
||||
const config = require('../../config')
|
||||
|
||||
// Reade all files in a directory
|
||||
const getFilesInDir = (directoryPath, withPath, exclude = null) => {
|
||||
try {
|
||||
let directoryFilenames = fs.readdirSync(directoryPath);
|
||||
let directoryFilenames = fs.readdirSync(directoryPath)
|
||||
directoryFilenames.sort((a, b) => {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
if (a < b) return -1;
|
||||
if (a > b) return 1;
|
||||
return 0;
|
||||
});
|
||||
a = a.toLowerCase()
|
||||
b = b.toLowerCase()
|
||||
if (a < b) return -1
|
||||
if (a > b) return 1
|
||||
return 0
|
||||
})
|
||||
|
||||
if (withPath) {
|
||||
// a hacky way to do conditional array.map
|
||||
return directoryFilenames.reduce((fileNames, fileName) => {
|
||||
if (
|
||||
exclude == null ||
|
||||
!exclude.some(toExclude => fileName === toExclude)
|
||||
)
|
||||
fileNames.push(`${directoryPath}/${fileName}`);
|
||||
return fileNames;
|
||||
}, []);
|
||||
if (exclude == null || !exclude.some(toExclude => fileName === toExclude))
|
||||
fileNames.push(`${directoryPath}/${fileName}`)
|
||||
return fileNames
|
||||
}, [])
|
||||
}
|
||||
return directoryFilenames.filter(v => v !== 'README.md');
|
||||
return directoryFilenames.filter(v => v !== 'README.md')
|
||||
} catch (err) {
|
||||
console.log(`${red('ERROR!')} During snippet loading: ${err}`);
|
||||
process.exit(1);
|
||||
console.log(`${red('ERROR!')} During snippet loading: ${err}`)
|
||||
process.exit(1)
|
||||
}
|
||||
};
|
||||
}
|
||||
// Creates a hash for a value using the SHA-256 algorithm.
|
||||
const hashData = val =>
|
||||
crypto
|
||||
.createHash('sha256')
|
||||
.update(val)
|
||||
.digest('hex');
|
||||
.digest('hex')
|
||||
// Gets the code blocks for a snippet file.
|
||||
const getCodeBlocks = str => {
|
||||
const regex = /```[.\S\s]*?```/g;
|
||||
let results = [];
|
||||
let m = null;
|
||||
const regex = /```[.\S\s]*?```/g
|
||||
let results = []
|
||||
let m = null
|
||||
while ((m = regex.exec(str)) !== null) {
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1
|
||||
|
||||
m.forEach((match, groupIndex) => {
|
||||
results.push(match);
|
||||
});
|
||||
results.push(match)
|
||||
})
|
||||
}
|
||||
const replacer = new RegExp(
|
||||
`\`\`\`${config.language}([\\s\\S]*?)\`\`\``,
|
||||
'g',
|
||||
);
|
||||
const secondReplacer = new RegExp(
|
||||
`\`\`\`${config.secondLanguage}([\\s\\S]*?)\`\`\``,
|
||||
'g',
|
||||
);
|
||||
const optionalReplacer = new RegExp(
|
||||
`\`\`\`${config.optionalLanguage}([\\s\\S]*?)\`\`\``,
|
||||
'g',
|
||||
);
|
||||
const replacer = new RegExp(`\`\`\`${config.language}([\\s\\S]*?)\`\`\``, 'g')
|
||||
const secondReplacer = new RegExp(`\`\`\`${config.secondLanguage}([\\s\\S]*?)\`\`\``, 'g')
|
||||
const optionalReplacer = new RegExp(`\`\`\`${config.optionalLanguage}([\\s\\S]*?)\`\`\``, 'g')
|
||||
results = results.map(v =>
|
||||
v
|
||||
.replace(replacer, '$1')
|
||||
.replace(secondReplacer, '$1')
|
||||
.replace(optionalReplacer, '$1')
|
||||
.trim()
|
||||
);
|
||||
)
|
||||
if (results.length > 2)
|
||||
return {
|
||||
html: results[0],
|
||||
css: results[1],
|
||||
js: results[2],
|
||||
};
|
||||
js: results[2]
|
||||
}
|
||||
return {
|
||||
html: results[0],
|
||||
css: results[1],
|
||||
js: '',
|
||||
};
|
||||
};
|
||||
js: ''
|
||||
}
|
||||
}
|
||||
// Gets the textual content for a snippet file.
|
||||
const getTextualContent = str => {
|
||||
const regex = /([\s\S]*?)```/g;
|
||||
const results = [];
|
||||
let m = null;
|
||||
const regex = /([\s\S]*?)```/g
|
||||
const results = []
|
||||
let m = null
|
||||
while ((m = regex.exec(str)) !== null) {
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1
|
||||
|
||||
m.forEach((match, groupIndex) => {
|
||||
results.push(match);
|
||||
});
|
||||
results.push(match)
|
||||
})
|
||||
}
|
||||
return results[1].replace(/\r\n/g, '\n');
|
||||
};
|
||||
return results[1].replace(/\r\n/g, '\n')
|
||||
}
|
||||
|
||||
// Gets the explanation for a snippet file.
|
||||
const getExplanation = str => {
|
||||
const regex = /####\s*Explanation([\s\S]*)####/g;
|
||||
const results = [];
|
||||
let m = null;
|
||||
const regex = /####\s*Explanation([\s\S]*)####/g
|
||||
const results = []
|
||||
let m = null
|
||||
while ((m = regex.exec(str)) !== null) {
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1
|
||||
|
||||
m.forEach((match, groupIndex) => {
|
||||
results.push(match);
|
||||
});
|
||||
results.push(match)
|
||||
})
|
||||
}
|
||||
// console.log(results);
|
||||
return results[1].replace(/\r\n/g, '\n');
|
||||
};
|
||||
return results[1].replace(/\r\n/g, '\n')
|
||||
}
|
||||
|
||||
// Gets the browser support for a snippet file.
|
||||
const getBrowserSupport = str => {
|
||||
const regex = /####\s*Browser [s|S]upport([\s\S]*)/g;
|
||||
const results = [];
|
||||
let m = null;
|
||||
const regex = /####\s*Browser [s|S]upport([\s\S]*)/g
|
||||
const results = []
|
||||
let m = null
|
||||
while ((m = regex.exec(str)) !== null) {
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1;
|
||||
if (m.index === regex.lastIndex) regex.lastIndex += 1
|
||||
|
||||
m.forEach((match, groupIndex) => {
|
||||
results.push(match);
|
||||
});
|
||||
results.push(match)
|
||||
})
|
||||
}
|
||||
let browserSupportText = results[1].replace(/\r\n/g, '\n');
|
||||
const supportPercentage = (browserSupportText.match(/https?:\/\/caniuse\.com\/#feat=.*/g) || []).map(
|
||||
feat => {
|
||||
const featData = caniuseDb.data[feat.match(/#feat=(.*)/)[1]];
|
||||
// caniuse doesn't count "untracked" users, which makes the overall share appear much lower
|
||||
// than it probably is. Most of these untracked browsers probably support these features.
|
||||
// Currently it's around 5.3% untracked, so we'll use 4% as probably supporting the feature.
|
||||
// Also the npm package appears to be show higher usage % than the main website, this shows
|
||||
// about 0.2% lower than the main website when selecting "tracked users" (as of Feb 2019).
|
||||
const UNTRACKED_PERCENT = 4;
|
||||
const usage = featData
|
||||
? Number(featData.usage_perc_y + featData.usage_perc_a) + UNTRACKED_PERCENT
|
||||
: 100;
|
||||
return Math.min(100, usage);
|
||||
}
|
||||
)
|
||||
let browserSupportText = results[1].replace(/\r\n/g, '\n')
|
||||
const supportPercentage = (
|
||||
browserSupportText.match(/https?:\/\/caniuse\.com\/#feat=.*/g) || []
|
||||
).map(feat => {
|
||||
const featData = caniuseDb.data[feat.match(/#feat=(.*)/)[1]]
|
||||
// caniuse doesn't count "untracked" users, which makes the overall share appear much lower
|
||||
// than it probably is. Most of these untracked browsers probably support these features.
|
||||
// Currently it's around 5.3% untracked, so we'll use 4% as probably supporting the feature.
|
||||
// Also the npm package appears to be show higher usage % than the main website, this shows
|
||||
// about 0.2% lower than the main website when selecting "tracked users" (as of Feb 2019).
|
||||
const UNTRACKED_PERCENT = 4
|
||||
const usage = featData
|
||||
? Number(featData.usage_perc_y + featData.usage_perc_a) + UNTRACKED_PERCENT
|
||||
: 100
|
||||
return Math.min(100, usage)
|
||||
})
|
||||
return {
|
||||
text: browserSupportText,
|
||||
supportPercentage: Math.min(...supportPercentage,100)
|
||||
supportPercentage: Math.min(...supportPercentage, 100)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Synchronously read all snippets and sort them as necessary (case-insensitive)
|
||||
const readSnippets = snippetsPath => {
|
||||
const snippetFilenames = getFilesInDir(snippetsPath, false);
|
||||
const snippetFilenames = getFilesInDir(snippetsPath, false)
|
||||
|
||||
let snippets = {};
|
||||
let snippets = {}
|
||||
try {
|
||||
for (let snippet of snippetFilenames) {
|
||||
let data = frontmatter(
|
||||
fs.readFileSync(path.join(snippetsPath, snippet), 'utf8'),
|
||||
);
|
||||
let data = frontmatter(fs.readFileSync(path.join(snippetsPath, snippet), 'utf8'))
|
||||
snippets[snippet] = {
|
||||
id: snippet.slice(0, -3),
|
||||
title: data.attributes.title,
|
||||
@ -170,22 +156,24 @@ const readSnippets = snippetsPath => {
|
||||
explanation: getExplanation(data.body),
|
||||
browserSupport: getBrowserSupport(data.body),
|
||||
codeBlocks: getCodeBlocks(data.body),
|
||||
tags: data.attributes.tags.split(',').map(t => t.trim()),
|
||||
tags: data.attributes.tags.split(',').map(t => t.trim())
|
||||
},
|
||||
meta: {
|
||||
hash: hashData(data.body),
|
||||
},
|
||||
};
|
||||
snippets[snippet].attributes.codeBlocks.scopedCss = sass.renderSync({
|
||||
data: `[data-scope="${snippets[snippet].id}"] { ${snippets[snippet].attributes.codeBlocks.css} }`
|
||||
}).css.toString();
|
||||
hash: hashData(data.body)
|
||||
}
|
||||
}
|
||||
snippets[snippet].attributes.codeBlocks.scopedCss = sass
|
||||
.renderSync({
|
||||
data: `[data-scope="${snippets[snippet].id}"] { ${snippets[snippet].attributes.codeBlocks.css} }`
|
||||
})
|
||||
.css.toString()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(`${red('ERROR!')} During snippet loading: ${err}`);
|
||||
process.exit(1);
|
||||
console.log(`${red('ERROR!')} During snippet loading: ${err}`)
|
||||
process.exit(1)
|
||||
}
|
||||
return snippets;
|
||||
};
|
||||
return snippets
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getFilesInDir,
|
||||
@ -194,5 +182,5 @@ module.exports = {
|
||||
getTextualContent,
|
||||
getExplanation,
|
||||
getBrowserSupport,
|
||||
readSnippets,
|
||||
};
|
||||
readSnippets
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user