Feat: Ensure markdown formatting (#34547)
<!-- Please follow this checklist and put an x in each of the boxes, like this: [x]. It will ensure that our team takes your pull request seriously. --> - [x] I have read [freeCodeCamp's contribution guidelines](https://github.com/freeCodeCamp/freeCodeCamp/blob/master/CONTRIBUTING.md). - [x] My pull request has a descriptive title (not a vague title like `Update index.md`) - [x] My pull request targets the `master` branch of freeCodeCamp. Closes #34535
This commit is contained in:
committed by
mrugesh mohapatra
parent
6685494344
commit
2d3c2efa2a
@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
title: Context API
|
title: Context API
|
||||||
|
localeTitle: Context API
|
||||||
---
|
---
|
||||||
|
|
||||||
# Context API
|
# Context API
|
||||||
|
|
||||||
Новый Context API был реализован в версии React 16.3.
|
Новый Context API был реализован в версии React 16.3.
|
||||||
|
|
||||||
Он существовал и раньше, однако находился в бета-версии, и, таким образом, не имел возможности предоставить инструменты для работы с его помощью.
|
Он существовал и раньше, однако находился в бета-версии, и, таким образом, не имел возможности предоставить инструменты для работы с его помощью.
|
||||||
|
|
||||||
@ -94,7 +95,7 @@ export default () => (
|
|||||||
```javascript
|
```javascript
|
||||||
<p> It’s 17:00 ! </p>
|
<p> It’s 17:00 ! </p>
|
||||||
```
|
```
|
||||||
### Динамическое изменение контекста
|
### Динамическое изменение контекста
|
||||||
|
|
||||||
Чтобы изменить значение параметра время (time), которое мы передаем компоненту ShowTime, нам нужно предоставить нашему контексту функцию, которая может использоваться потребителем для обновления значения.
|
Чтобы изменить значение параметра время (time), которое мы передаем компоненту ShowTime, нам нужно предоставить нашему контексту функцию, которая может использоваться потребителем для обновления значения.
|
||||||
|
|
||||||
|
29
package-lock.json
generated
29
package-lock.json
generated
@ -1984,6 +1984,12 @@
|
|||||||
"restore-cursor": "^2.0.0"
|
"restore-cursor": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cli-spinners": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"cli-width": {
|
"cli-width": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
|
||||||
@ -6766,6 +6772,15 @@
|
|||||||
"lodash._reinterpolate": "~3.0.0"
|
"lodash._reinterpolate": "~3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"log-symbols": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"loose-envify": {
|
"loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
@ -7649,6 +7664,20 @@
|
|||||||
"wordwrap": "~1.0.0"
|
"wordwrap": "~1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ora": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-LBS97LFe2RV6GJmXBi6OKcETKyklHNMV0xw7BtsVn2MlsgsydyZetSCbCANr+PFLmDyv4KV88nn0eCKza665Mg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.3.1",
|
||||||
|
"cli-cursor": "^2.1.0",
|
||||||
|
"cli-spinners": "^1.1.0",
|
||||||
|
"log-symbols": "^2.2.0",
|
||||||
|
"strip-ansi": "^4.0.0",
|
||||||
|
"wcwidth": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"os-homedir": {
|
"os-homedir": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"test:lint": "echo 'Warning: TODO - Define Linting tests.'",
|
"test:lint": "echo 'Warning: TODO - Define Linting tests.'",
|
||||||
"test:client": "cd ./client && npm test && cd ../",
|
"test:client": "cd ./client && npm test && cd ../",
|
||||||
"test:curriculum": "cd ./curriculum && npm test && cd ../",
|
"test:curriculum": "cd ./curriculum && npm test && cd ../",
|
||||||
"test:guide-directories": "node ./tools/scripts/ci/ensure-guide-page-naming.js",
|
"test:challenge-formatting": "node ./tools/scripts/ci/ensure-challenge-formatting.js",
|
||||||
|
"test:guide-formatting": "node ./tools/scripts/ci/ensure-guide-formatting.js",
|
||||||
"test:server": "cd ./api-server && npm test && cd ../",
|
"test:server": "cd ./api-server && npm test && cd ../",
|
||||||
"test:tools": "jest ./tools"
|
"test:tools": "jest ./tools"
|
||||||
},
|
},
|
||||||
@ -33,6 +34,7 @@
|
|||||||
"lerna": "^3.4.0",
|
"lerna": "^3.4.0",
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
|
"ora": "^3.0.0",
|
||||||
"readdirp-walk": "^1.6.0",
|
"readdirp-walk": "^1.6.0",
|
||||||
"shortid": "^2.2.14",
|
"shortid": "^2.2.14",
|
||||||
"slugg": "^1.2.1",
|
"slugg": "^1.2.1",
|
||||||
|
77
tools/scripts/ci/ensure-challenge-formatting.js
Normal file
77
tools/scripts/ci/ensure-challenge-formatting.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
const readdirp = require('readdirp-walk');
|
||||||
|
const { has, isEmpty, isNumber } = require('lodash');
|
||||||
|
const ora = require('ora');
|
||||||
|
|
||||||
|
const { parseMarkdown } = require('../../challenge-md-parser');
|
||||||
|
const { challengeRoot, checkFrontmatter } = require('./md-testing-utils');
|
||||||
|
|
||||||
|
const scrimbaUrlRE = /^https:\/\/scrimba\.com\//;
|
||||||
|
const requiredProps = ['title', 'id', 'challengeType'];
|
||||||
|
|
||||||
|
const spinner = ora('Checking challenge markdown formatting').start();
|
||||||
|
|
||||||
|
readdirp({ root: challengeRoot, directoryFilter: '!_meta' })
|
||||||
|
.on('data', file =>
|
||||||
|
Promise.all([
|
||||||
|
isChallengeParseable(file),
|
||||||
|
checkFrontmatter(file, {
|
||||||
|
validator: challengeFrontmatterValidator(file)
|
||||||
|
})
|
||||||
|
]).catch(err => {
|
||||||
|
console.info(`
|
||||||
|
the following error occured when testing
|
||||||
|
|
||||||
|
${file.fullPath}
|
||||||
|
|
||||||
|
`);
|
||||||
|
console.error(err);
|
||||||
|
// eslint-disable-next-line no-process-exit
|
||||||
|
process.exit(1);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.on('end', () => spinner.stop());
|
||||||
|
|
||||||
|
const challengeFrontmatterValidator = file => frontmatter => {
|
||||||
|
const { fullPath } = file;
|
||||||
|
|
||||||
|
const hasRequiredProperties = requiredProps
|
||||||
|
.map(
|
||||||
|
prop =>
|
||||||
|
has(frontmatter, prop) &&
|
||||||
|
(!isEmpty(frontmatter[prop]) || isNumber(frontmatter[prop]))
|
||||||
|
)
|
||||||
|
.every(bool => bool);
|
||||||
|
|
||||||
|
if (!hasRequiredProperties) {
|
||||||
|
console.log(`${fullPath} is missing required frontmatter
|
||||||
|
|
||||||
|
${JSON.stringify(frontmatter, null, 2)}
|
||||||
|
|
||||||
|
Required properties are: ${JSON.stringify(requiredProps, null, 2)}
|
||||||
|
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
const { videoUrl } = frontmatter;
|
||||||
|
|
||||||
|
let validVideoUrl = false;
|
||||||
|
if (isEmpty(videoUrl)) {
|
||||||
|
validVideoUrl = true;
|
||||||
|
} else {
|
||||||
|
validVideoUrl = scrimbaUrlRE.test(videoUrl);
|
||||||
|
|
||||||
|
if (!validVideoUrl) {
|
||||||
|
console.log(`
|
||||||
|
${fullPath} contains an invalid videoUrl
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasRequiredProperties && validVideoUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isChallengeParseable(file) {
|
||||||
|
const { stat, fullPath } = file;
|
||||||
|
if (!stat.isFile() || (/_meta/).test(fullPath)) {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
return parseMarkdown(fullPath);
|
||||||
|
}
|
34
tools/scripts/ci/ensure-guide-formatting.js
Normal file
34
tools/scripts/ci/ensure-guide-formatting.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
const readdirp = require('readdirp-walk');
|
||||||
|
const { has } = require('lodash');
|
||||||
|
const ora = require('ora');
|
||||||
|
|
||||||
|
const {
|
||||||
|
guideRoot,
|
||||||
|
checkGuideFile,
|
||||||
|
checkFrontmatter,
|
||||||
|
extractLangFromFileName
|
||||||
|
} = require('./md-testing-utils');
|
||||||
|
|
||||||
|
const spinner = ora('Checking guide markdown formatting').start();
|
||||||
|
|
||||||
|
const guideFrontmatterValidator = file => frontmatter => {
|
||||||
|
const hasLocale =
|
||||||
|
extractLangFromFileName(file) === 'english'
|
||||||
|
? true
|
||||||
|
: has(frontmatter, 'localeTitle');
|
||||||
|
const hasTitle = has(frontmatter, 'title');
|
||||||
|
return hasLocale && hasTitle;
|
||||||
|
};
|
||||||
|
|
||||||
|
readdirp({ root: guideRoot })
|
||||||
|
.on('data', file =>
|
||||||
|
Promise.all([
|
||||||
|
checkGuideFile(file),
|
||||||
|
checkFrontmatter(file, { validator: guideFrontmatterValidator(file) })
|
||||||
|
]).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
// eslint-disable-next-line no-process-exit
|
||||||
|
process.exit(1);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.on('end', () => spinner.stop());
|
@ -1,10 +1,13 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const readdirp = require('readdirp-walk');
|
|
||||||
const matter = require('gray-matter');
|
const matter = require('gray-matter');
|
||||||
const _ = require('lodash');
|
|
||||||
|
const pass = true;
|
||||||
|
|
||||||
const guideRoot = path.resolve(__dirname, '../../../guide');
|
const guideRoot = path.resolve(__dirname, '../../../guide');
|
||||||
|
const challengeRoot = path.resolve(__dirname, '../../../curriculum/challenges');
|
||||||
|
exports.guideRoot = guideRoot;
|
||||||
|
exports.challengeRoot = challengeRoot;
|
||||||
|
|
||||||
const allowedLangDirNames = [
|
const allowedLangDirNames = [
|
||||||
'arabic',
|
'arabic',
|
||||||
@ -15,7 +18,7 @@ const allowedLangDirNames = [
|
|||||||
'spanish'
|
'spanish'
|
||||||
];
|
];
|
||||||
|
|
||||||
function checkFile(file) {
|
exports.checkGuideFile = function checkGuideFile(file) {
|
||||||
const { stat, depth, name, fullPath } = file;
|
const { stat, depth, name, fullPath } = file;
|
||||||
if (depth === 1) {
|
if (depth === 1) {
|
||||||
if (stat.isFile()) {
|
if (stat.isFile()) {
|
||||||
@ -26,43 +29,10 @@ function checkFile(file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stat.isDirectory()) {
|
if (stat.isDirectory()) {
|
||||||
return checkDirName(name, fullPath).catch(err => {
|
return checkDirName(name, fullPath);
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return checkFileName(name, fullPath)
|
return checkGuideFileName(name, fullPath);
|
||||||
.then(() => checkFrontmatter(fullPath))
|
};
|
||||||
.catch(err => {
|
|
||||||
console.log(`
|
|
||||||
|
|
||||||
The below occured in:
|
|
||||||
|
|
||||||
${fullPath}
|
|
||||||
|
|
||||||
`);
|
|
||||||
console.error(err);
|
|
||||||
// eslint-disable-next-line no-process-exit
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
readdirp({ root: guideRoot })
|
|
||||||
.on('data', file =>
|
|
||||||
checkFile(file).catch(err => {
|
|
||||||
console.error(err);
|
|
||||||
// eslint-disable-next-line no-process-exit
|
|
||||||
process.exit(1);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.on('end', () => {
|
|
||||||
console.log(`
|
|
||||||
|
|
||||||
guide directory naming checks complete
|
|
||||||
|
|
||||||
`);
|
|
||||||
// eslint-disable-next-line no-process-exit
|
|
||||||
process.exit(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
function checkDirName(dirName, fullPath) {
|
function checkDirName(dirName, fullPath) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -86,11 +56,11 @@ Upper case characters found in ${dirName}, all folder names must be lower case
|
|||||||
`)
|
`)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return resolve();
|
return resolve(pass);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkFileName(fileName, fullPath) {
|
function checkGuideFileName(fileName, fullPath) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (fileName !== 'index.md') {
|
if (fileName !== 'index.md') {
|
||||||
return reject(
|
return reject(
|
||||||
@ -103,11 +73,21 @@ function checkFileName(fileName, fullPath) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return resolve();
|
return resolve(pass);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkFrontmatter(fullPath) {
|
exports.checkFrontmatter = function checkFrontmatter(
|
||||||
|
{ fullPath, stat },
|
||||||
|
options = {
|
||||||
|
validator() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if (!stat.isFile()) {
|
||||||
|
return Promise.resolve(pass);
|
||||||
|
}
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
fs.readFile(fullPath, 'utf8', (err, content) => {
|
fs.readFile(fullPath, 'utf8', (err, content) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -115,25 +95,15 @@ function checkFrontmatter(fullPath) {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const { data: frontmatter } = matter(content);
|
const { data: frontmatter } = matter(content);
|
||||||
if (!frontmatter || _.isEmpty(frontmatter) || !frontmatter.title) {
|
const { validator } = options;
|
||||||
|
if (!validator(frontmatter)) {
|
||||||
return reject(
|
return reject(
|
||||||
new Error(`
|
new Error(
|
||||||
The article at: ${fullPath} is missing frontmatter.
|
`The article at: ${fullPath} failed frontmatter validation.`
|
||||||
|
)
|
||||||
Example:
|
|
||||||
|
|
||||||
---
|
|
||||||
title: The Article Title
|
|
||||||
localeTitle: The Translated Title # Only required for translations
|
|
||||||
---
|
|
||||||
|
|
||||||
< The Article Body >
|
|
||||||
|
|
||||||
`)
|
|
||||||
);
|
);
|
||||||
// process.exit(1);
|
|
||||||
}
|
}
|
||||||
return resolve();
|
return resolve(pass);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`
|
console.log(`
|
||||||
|
|
||||||
@ -146,4 +116,10 @@ function checkFrontmatter(fullPath) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function extractLangFromFileName({ path: relativePath }) {
|
||||||
|
return relativePath.split(path.sep)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.extractLangFromFileName = extractLangFromFileName;
|
49
tools/scripts/tests-pass.js
Normal file
49
tools/scripts/tests-pass.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
console.log(`
|
||||||
|
,@@@@@@@@@@,,@@@@@@@% .#&@@@&&.,@@@@@@@@@@, .#&@@@&&. %@@@@@@%* ,@@@% .#&@@@&&. *&@@@@&( ,@@@@@@@% %@@@@@, ,@@,
|
||||||
|
,@@, ,@@, ,@@/ ./. ,@@, ,@@/ ./. %@% ,&@# .&@&@@( .@@/ ./. #@&. .,/ ,@@, %@% *&@&. ,@@,
|
||||||
|
,@@, ,@@&%%%%. .&@@/, ,@@, .&@@/, %@% ,&@# %@& /@@, .&@@/, (@@&%(*. ,@@&%%%%. %@% &@# ,@@,
|
||||||
|
,@@, ,@@/,,,, ./#&@@@( ,@@, ./#&@@@( %@@@@@@%* /@@, #@&. ./#&@@@( *(%&@@&. ,@@/,,,, %@% &@# .&&.
|
||||||
|
,@@, ,@@, ./, .&@# ,@@, ./, .&@# %@% ,@@@@@@@@@% ./. .&@# /*. /@@. ,@@, %@% *&@&. ,,
|
||||||
|
,@@, ,@@@@@@@% .#&@@@@&/ ,@@, .#&@@@@&/ %@% .&@# ,@@/.#&@@@@&/ /%&@@@@. ,@@@@@@@% %@@@@@. ,@@,
|
||||||
|
,*************,,*/(((((//,,*(#%%%%%%%%%%%%%%%#(*,,,****************************************************,*/(((((((((/((((////****/((##%%%%%%
|
||||||
|
,*************,,//((((((//,,*(%%%%%%%%%%%%%%%%%##/*****************************************************,,*/(///(//////****//((##%%%%%%%%%%%
|
||||||
|
,************,,*/(((((((//***/#%%%%%%%%%%%%%%%%%%%#(/***************************************************,*//////////*//((#%%%%%%%%%%%%%%%%%
|
||||||
|
,***********,,*////////////***/##%%%%%%%%%%%%%%%%%%%##(*,***********************************************,,*////////(###%%%%%%%%%%%%%%%%%%%%
|
||||||
|
,**********,,,*/*******//////**/(#%%%%%%%%%%%%%%%%%%%%%#(/**********************************************,,,***/(##%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
,*********,,,,*************///***/(#%%%%%%%%%%%%%%%%%%%%%%#(/***********************************,****,****/((#%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
|
||||||
|
,*********,,,***************//****/(##%%%%%%%%%%%%%%%%%%%%%%##//**************//////////////////////((#####%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(
|
||||||
|
,********,,,,***********************/(#%%%%%%%%%%%%%%%%%%%%%%%##################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##(/
|
||||||
|
,*******,..,***********************,,*/##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###((//
|
||||||
|
,*******,.,,***********************,,,,*(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##(//**//
|
||||||
|
,******,.,,,************************,,,,*/(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(//*******
|
||||||
|
,*****,,,,,********,***,,,,,,,,,,,,*,,,,,,*/(######%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##(/**********
|
||||||
|
,*****,..,*******,,,,,,,,,,,,,,,,,,,,,,*,,,,*///((#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%###(/************
|
||||||
|
,*****,,,*******,,,,,*,,,,,,,,,,,,,,,,,****,,,*/(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#######(//**************
|
||||||
|
,****,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,**,,,/(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#((//******************
|
||||||
|
,***,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,,,,,,,*(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(/*******************
|
||||||
|
,**,,.,,,,,,,,,,,,,,,,,,,,,,,,,,.......,,,,,,/#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#####%%%%%%%%%%%%%%%%#(/******************
|
||||||
|
,**,..,,,,,,,,,,,,,,,,,,,,,,,,,......,,,*,,,*(#%%%%%%%%##(((/(##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##(((/*/((#%%%%%%%%%%%%%%#(/*****************
|
||||||
|
,*,..,,,,,,,,,,,,,,,,,,,,,,,,,,,.....,,**,,*/#%%%%%%%##((((*,**/#%%%%%%%%%%%%%%%%%%%%%%%%%%%%##((##/,,,*(#%%%%%%%%%%%%%%#(*****************
|
||||||
|
.*,.,,,**,,,,,,,,,,,,,,,,,,,,,,,,,,*****,,,/(%%%%%%%%#(//(#/,..*/#%%%%%%%%%%%%%%%%%%%%%%%%%%%#(//(#/,..,/(#%%%%%%%%%%%%%%#/*****///////////
|
||||||
|
.,..,,,,,,,,,,,,,,,,,,,,,,,,,,*,,*******,,,(#%%%%%%%%#(*,,,....,/#%%%%%%%%%%%%%%%%%%%%%%%%%%%#(*,,,....,/(#%%%%%%%%%%%%%%#(*,**////////////
|
||||||
|
.,..,,,,,,,,,...........,,,,,,*,********,,*(#%%%%%%%%%#(/*,,...,/#%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(/*,,..,*/##%%%%%%%%%%%%%%%#(***////////////
|
||||||
|
...,,,,,,,................,,*,**********,,/#%%%%%%%%%%%%#((////((#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##((///(#%%%%%%%%%%%%%%%%%%(/**////////////
|
||||||
|
..,,,,,,.................,,,**********,,*(#%%%%%%%%%%%%%%%%%%#%%%%%%%%#((///((#%%%%%%%%%%%%%%%%%%%%%#%%%%%%%%%%%%%%%%%%%%%#/**////////////
|
||||||
|
.,,,,,,,,.................,,***********,,/(####%%%%%%%%%%%%%%%%%%%%%%%%#(/*,,,*(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(/*////////////
|
||||||
|
.,***,,,,,,..............,,,**********,..,***//((##%%%%%%%%%%%%%%%%%%%%%%%##((##%%%%%%%%%%%%%%%%%%%%%%%%%##(((((((((###%%%%%#/**///////////
|
||||||
|
.*****,,,,,,,,,,,,,,,,,,,*************,..,*******/(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##///*//////((#%%%%%#(**///////////
|
||||||
|
.****************/******/***////*****,.,*///////**/#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(////////////(#%%%%%#/**//////////
|
||||||
|
.***********************/////*******,..,*//////////(#%%%%%%%%%%%%%%%%%%%%##########%%%%%%%%%%%%%%%%%%%%#(///////////*/(#%%%%%#(***/////////
|
||||||
|
.************************///********,..,*//////////#%%%%%%%%%%%%%%%%%%#(//*****///(((##%%%%%%%%%%%%%%%%#(///////////**/##%%%%##/***////////
|
||||||
|
.***********************************,.,,***///////(#%%%%%%%%%%%%%%%%#(/*,,,*//((((////(#%%%%%%%%%%%%%%%#((////////////(#%%%%%%#(*********//
|
||||||
|
,***********,,,*,,*,,**************,,,*//******//(#%%%%%%%%%%%%%%%%%#(*,,*/(((#####(((((#%%%%%%%%%%%%%%%##///////////(#%%%%%%%%#(***///////
|
||||||
|
,*************,,**,,,************,,,,,/(##((((####%%%%%%%%%%%%%%%%%%%(/**/(((#((((#((//(#%%%%%%%%%%%%%%%%%#(((((((((##%%%%%%%%%%#/**///////
|
||||||
|
,******************************,,,,,,,*(#%#%%%%%%%%%%%%%%%%%%%%%%%%%%#(**/((#(#(((#((//(#%%%%%%%%%%%%%%%%%%%%%%%#%#%%%%%%%%%%%%%#(**///////
|
||||||
|
,*************,**************,****,,,,,/(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(/*/((((#((((///(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%(/*///////
|
||||||
|
,*************************************,*/#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##(////////////(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#/**/////*
|
||||||
|
,******////****///////////////////////***/#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%####(((((((###%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(********
|
||||||
|
.,*,****///////////////////////////////***/#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#(/*******
|
||||||
|
.,,,,*****//////////////////////////*******(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%##(*******
|
||||||
|
.,,,,,,***********/////////////////********/(#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%(*******
|
||||||
|
`);
|
Reference in New Issue
Block a user