Skip to content

Commit

Permalink
feat: Created
Browse files Browse the repository at this point in the history
  • Loading branch information
mya-ake committed Jan 22, 2019
1 parent 16c08da commit ab49843
Show file tree
Hide file tree
Showing 17 changed files with 10,180 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
> 1%
last 2 versions
not ie <= 8
21 changes: 21 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
root: true,
env: {
node: true,
},
extends: ['plugin:vue/recommended', '@vue/prettier'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'prettier/prettier': [
'error',
{
singleQuote: true,
trailingComma: 'all',
},
],
},
parserOptions: {
parser: 'babel-eslint',
},
};
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.DS_Store
node_modules
/dist

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
3 changes: 3 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ['@vue/app'],
};
18 changes: 18 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest',
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'^~fixtures/(.*)$': '<rootDir>/tests/fixtures/$1',
},
snapshotSerializers: ['jest-serializer-vue'],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
],
testURL: 'http://localhost/',
};
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "vue-slot-checker",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit"
},
"dependencies": {
"vue": "^2.5.21"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.3.0",
"@vue/cli-plugin-eslint": "^3.3.0",
"@vue/cli-plugin-unit-jest": "^3.3.0",
"@vue/cli-service": "^3.3.0",
"@vue/eslint-config-prettier": "^4.0.1",
"@vue/test-utils": "^1.0.0-beta.20",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"vue-template-compiler": "^2.5.21"
}
}
5 changes: 5 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {},
},
};
96 changes: 96 additions & 0 deletions src/debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// referred: https://github.com/vuejs/vue/blob/dev/src/core/util/debug.js

import Vue from 'vue';

const noop = () => {};

export let warn = noop;
export let generateComponentTrace = noop;
export let formatComponentName = noop;

if (process.env.NODE_ENV !== 'production') {
const hasConsole = typeof console !== 'undefined';
const classifyRE = /(?:^|[-_])(\w)/g;
const classify = str =>
str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '');

warn = (msg, vm) => {
if (Vue.config.warnHandler) {
Vue.config.warnHandler.call(null, msg, vm);
} else if (hasConsole && !Vue.config.silent) {
console.error(`[vue-slot-checker warn]: ${msg}`);
}
};

formatComponentName = (vm, includeFile) => {
if (vm.$root === vm) {
return '<Root>';
}
const options =
typeof vm === 'function' && vm.cid != null
? vm.options
: vm._isVue
? vm.$options || vm.constructor.options
: vm;
let name = options.name || options._componentTag;
const file = options.__file;
if (!name && file) {
const match = file.match(/([^/\\]+)\.vue$/);
name = match && match[1];
}

return (
(name ? `<${classify(name)}>` : `<Anonymous>`) +
(file && includeFile !== false ? ` at ${file}` : '')
);
};

const repeat = (str, n) => {
let res = '';
while (n) {
if (n % 2 === 1) res += str;
if (n > 1) str += str;
n >>= 1;
}
return res;
};

generateComponentTrace = vm => {
if (vm._isVue && vm.$parent) {
const tree = [];
let currentRecursiveSequence = 0;
while (vm) {
if (tree.length > 0) {
const last = tree[tree.length - 1];
if (last.constructor === vm.constructor) {
currentRecursiveSequence++;
vm = vm.$parent;
continue;
} else if (currentRecursiveSequence > 0) {
tree[tree.length - 1] = [last, currentRecursiveSequence];
currentRecursiveSequence = 0;
}
}
tree.push(vm);
vm = vm.$parent;
}
return (
'\n\nfound in\n\n' +
tree
.map(
(vm, i) =>
`${i === 0 ? '---> ' : repeat(' ', 5 + i * 2)}${
Array.isArray(vm)
? `${formatComponentName(vm[0])}... (${
vm[1]
} recursive calls)`
: formatComponentName(vm)
}`,
)
.join('\n')
);
} else {
return `\n\n(found in ${formatComponentName(vm)})`;
}
};
}
27 changes: 27 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { mixin } from './mixin';

// mixin
export const vueSlotChecker = mixin;

function install(Vue) {
if (install.installed) return;
install.installed = true;

Vue.mixin({
mixins: [mixin],
});
}

const plugin = { install };

let GlobalVue = null;
if (typeof window !== 'undefined') {
GlobalVue = window.Vue;
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue;
}
if (GlobalVue) {
GlobalVue.use(plugin);
}

export default plugin;
48 changes: 48 additions & 0 deletions src/mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { warn } from './debug';

const warnRequire = slotName => {
warn(`Missing required slot: '${slotName}'`);
};

const warnCustomValidator = slotName => {
warn(`Invalid slot: custom validator check failed for slot '${slotName}'`);
};

export const mixin = {
created() {
if (!this.$options.slots) {
return;
}

if (this.$options.slots === true) {
if ('default' in this.$slots === false) {
warnRequire('default');
}
}

if (Array.isArray(this.$options.slots)) {
this.$options.slots.forEach(slotName => {
if (slotName in this.$slots === false) {
warnRequire(slotName);
}
});
}

if (typeof this.$options.slots === 'object') {
Object.keys(this.$options.slots).forEach(slotName => {
const option = this.$options.slots[slotName];
if (option.required === true) {
if (slotName in this.$slots === false) {
warnRequire(slotName);
}
}
const validator = option.validator;
if (typeof validator === 'function') {
if (validator(this.$slots[slotName]) === false) {
warnCustomValidator(slotName);
}
}
});
}
},
};
12 changes: 12 additions & 0 deletions tests/fixtures/ArraySlots.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<template>
<div>
<header><slot name="header" /></header>
<div><slot /></div>
</div>
</template>

<script>
export default {
slots: ['default', 'header'],
};
</script>
29 changes: 29 additions & 0 deletions tests/fixtures/CustomValidator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>
<div>
<header><slot name="header" /></header>
<div><slot /></div>
</div>
</template>

<script>
export default {
slots: {
default: {
validator(slot) {
if (typeof slot === 'undefined') {
return false;
}
return typeof slot[0].text === 'string';
},
},
header: {
validator(slot) {
if (typeof slot === 'undefined') {
return false;
}
return slot[0].tag === 'nav';
},
},
},
};
</script>
19 changes: 19 additions & 0 deletions tests/fixtures/ObjectSlots.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<div>
<header><slot name="header" /></header>
<div><slot /></div>
</div>
</template>

<script>
export default {
slots: {
default: {
required: true,
},
header: {
required: true,
},
},
};
</script>
9 changes: 9 additions & 0 deletions tests/fixtures/SlotsTrue.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<div><slot /></div>
</template>

<script>
export default {
slots: true,
};
</script>
5 changes: 5 additions & 0 deletions tests/unit/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
env: {
jest: true,
},
};
Loading

0 comments on commit ab49843

Please sign in to comment.