30
.eslintrc.js
Normal file
30
.eslintrc.js
Normal file
@@ -0,0 +1,30 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true
|
||||
},
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
|
||||
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
|
||||
'plugin:vue/recommended',
|
||||
// 'plugin:prettier/recommended'
|
||||
],
|
||||
// required to lint *.vue files
|
||||
plugins: [
|
||||
'vue'
|
||||
],
|
||||
// add your custom rules here
|
||||
rules: {
|
||||
'semi': ['error', 'never'],
|
||||
'no-console': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'quotes': ['error', 'single', { 'avoidEscape': true }],
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'vue/require-default-prop': 'off',
|
||||
}
|
||||
}
|
||||
3
.vscode/webgems.code-snippets
vendored
3
.vscode/webgems.code-snippets
vendored
@@ -21,7 +21,8 @@
|
||||
"{",
|
||||
" \"title\": \"${1:title}\",",
|
||||
" \"desc\": \"${2:desc}\",",
|
||||
" \"url\": \"${3:url}\"",
|
||||
" \"url\": \"${3:url}\",",
|
||||
" \"tags\": [\"${4:tag}\"]",
|
||||
"},"
|
||||
],
|
||||
"description": "Add a webgem"
|
||||
|
||||
@@ -5,4 +5,5 @@ These are lovely people who have helped this project:
|
||||
* twitter: @lostdesign
|
||||
- [Kevin](https://github.com/S3B4S) :dog:
|
||||
- [jacobparis](https://github.com/jacobparis) : Team Devcord
|
||||
* twitter: @jacobmparis
|
||||
* twitter: @jacobmparis
|
||||
- [JonasPardon](https://github.com/JonasPardon)
|
||||
|
||||
16
README.md
16
README.md
@@ -39,27 +39,29 @@ For any other editor, please use the following schema:
|
||||
```js
|
||||
[
|
||||
{
|
||||
"title": "Category",
|
||||
"slug": "/category",
|
||||
"title": String, // Start with uppercase
|
||||
"slug": String, // All lowercase, eg: "/category"
|
||||
"resources": [
|
||||
{
|
||||
"title": "Awesome resource",
|
||||
"desc": "This awesome resource will make your life much easier.", // 1 - 2 sentences long.
|
||||
"url": "https://url.com"
|
||||
"title": String,
|
||||
"desc": String, // 1 - 2 sentences long
|
||||
"url": String, // See below for notes about correct format of URLs
|
||||
"tags": [String] // Please try to add at least 3 tags
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
If you just want to add a resource to an already existing category, extend the `resources` array with your resources. Please include all the keys enlisted (`title`, `desc`, `url`).
|
||||
In our [resources](resources/) we have an `<category>.json` file for each category, you can add your suggested resource by adding it to the `resources` array in the JSON file using the schema as described above. Please include all the keys enlisted (`title`, `desc`, `url`, `tags`).
|
||||
|
||||
For URLs, please consider the following:
|
||||
- Do not link to language specific pages (e.g. don't link to `<url>.org/en-US/docs`, instead, link to `<url>/docs` if possible).
|
||||
- Do not use `'&'` as it will break the URL referencing.
|
||||
- We won't allow referral links.
|
||||
|
||||
To add a completely new resource, include a new object at the root of the array, the pages are dynamically rendered so you don't have to worry about anything else. Again, include all the enlisted keys, reference to the schema above.
|
||||
To add a completely new resource, add a `<category>.json` file to [resources](resources/). Make sure it follows the sceme as described above.
|
||||
Add it to [resources.index.js](resources/index.js) list of imports and export it aswell, that way Nuxt can take care of rendering the page.
|
||||
|
||||
## Built With
|
||||
|
||||
|
||||
@@ -10,7 +10,11 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['resource', 'isActive', 'createCopyUrl'],
|
||||
props: {
|
||||
resource: Object,
|
||||
isActive: Boolean,
|
||||
createCopyUrl: Function,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -31,6 +35,12 @@ export default {
|
||||
|
||||
&--reference {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&--target {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&--links {
|
||||
@@ -72,20 +82,20 @@ export default {
|
||||
}
|
||||
&--reference {
|
||||
&::before {
|
||||
position:absolute;
|
||||
align-self: flex-start;
|
||||
padding-right: 0.2rem;
|
||||
height: .9rem;
|
||||
width: .9rem;
|
||||
margin-left: -1.15rem;
|
||||
margin-top: -.1rem;
|
||||
content: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzA4ZTVmZiI+PHBhdGggZD0iTSA0IDIgQyAzLjkwNSAyIDMuODE1NjA5NCAyLjAxNDM0MzggMy43MjQ2MDk0IDIuMDI3MzQzOCBDIDMuNDM0NjA5NCAyLjE0MzM0MzggMy4xMzk3MDMxIDIuMjU3MDkzOCAyLjg0NTcwMzEgMi4zNzEwOTM4IEMgMi4zMzQ3MDMxIDIuNzMzMDkzOCAyIDMuMzI2IDIgNCBMIDIgMTggTCA0IDE4IEwgNCA0IEwgMTggNCBMIDE4IDIgTCA0IDIgeiBNIDggNiBDIDYuODk1IDYgNiA2Ljg5NSA2IDggTCA2IDIwIEMgNiAyMS4xMDUgNi44OTUgMjIgOCAyMiBMIDIwIDIyIEMgMjEuMTA1IDIyIDIyIDIxLjEwNSAyMiAyMCBMIDIyIDggQyAyMiA2Ljg5NSAyMS4xMDUgNiAyMCA2IEwgOCA2IHogTSAxNyA4LjAwMTk1MzEgQyAxNy43NjggOC4wMDE5NTMxIDE4LjUzNjA5NCA4LjI5MzkwNjIgMTkuMTIxMDk0IDguODc4OTA2MiBDIDE5LjY4ODA5NCA5LjQ0NDkwNjMgMjAgMTAuMTk5IDIwIDExIEMgMjAgMTEuODAxIDE5LjY4ODA5NCAxMi41NTQwOTQgMTkuMTIxMDk0IDEzLjEyMTA5NCBMIDE3LjIyNDYwOSAxNS4wMTc1NzggTCAxNS44MTA1NDcgMTMuNjAzNTE2IEwgMTcuNzA3MDMxIDExLjcwNzAzMSBDIDE3Ljg5NjAzMSAxMS41MTgwMzEgMTggMTEuMjY3IDE4IDExIEMgMTggMTAuNzMzIDE3Ljg5NjAzMSAxMC40ODE5NjkgMTcuNzA3MDMxIDEwLjI5Mjk2OSBDIDE3LjMxNjAzMSA5LjkwMTk2ODcgMTYuNjgzOTY5IDkuOTAyOTY4OCAxNi4yOTI5NjkgMTAuMjkyOTY5IEwgMTQuMzkwNjI1IDEyLjE5NTMxMiBMIDE1LjgwNDY4OCAxMy42MDkzNzUgTCAxMy44MDA3ODEgMTUuNjEzMjgxIEwgMTUuMjE0ODQ0IDE3LjAyNzM0NCBMIDEzLjExOTE0MSAxOS4xMjEwOTQgQyAxMi41NTQxNDEgMTkuNjg3MDk0IDExLjgwMSAyMCAxMSAyMCBDIDEwLjE5OSAyMCA5LjQ0NDkwNjMgMTkuNjg4MDk0IDguODc4OTA2MiAxOS4xMjEwOTQgQyA4LjMxMjkwNjMgMTguNTU1MDk0IDggMTcuODAxIDggMTcgQyA4IDE2LjE5OSA4LjMxMjkwNjIgMTUuNDQ1OTA2IDguODc4OTA2MiAxNC44Nzg5MDYgTCAxMC45NzI2NTYgMTIuNzg1MTU2IEwgMTIuMzg2NzE5IDE0LjE5OTIxOSBMIDE0LjM2OTE0MSAxMi4yMTY3OTcgTCAxMi45NTUwNzggMTAuODAyNzM0IEwgMTQuODc4OTA2IDguODc4OTA2MiBDIDE1LjQ2MzkwNiA4LjI5MzkwNjIgMTYuMjMyIDguMDAxOTUzMSAxNyA4LjAwMTk1MzEgeiBNIDEyLjM3MzA0NyAxNC4yMTI4OTEgTCAxMC4yOTI5NjkgMTYuMjkyOTY5IEMgMTAuMTAzOTY5IDE2LjQ4MTk2OSAxMCAxNi43MzMgMTAgMTcgQyAxMCAxNy4yNjcgMTAuMTAzOTY5IDE3LjUxODAzMSAxMC4yOTI5NjkgMTcuNzA3MDMxIEMgMTAuNjcxOTY5IDE4LjA4NjAzMSAxMS4zMjgwMzEgMTguMDg1MDMxIDExLjcwNzAzMSAxNy43MDcwMzEgTCAxMy43ODcxMDkgMTUuNjI2OTUzIEwgMTIuMzczMDQ3IDE0LjIxMjg5MSB6IiBmaWxsPSIjMDhlNWZmIi8+PC9zdmc+Cg==');
|
||||
}
|
||||
}
|
||||
&--target {
|
||||
&::before {
|
||||
position:absolute;
|
||||
align-self: flex-start;
|
||||
padding-right: 0.2rem;
|
||||
height: .9rem;
|
||||
width: .9rem;
|
||||
margin-left: -1.15rem;
|
||||
margin-top: -.1rem;
|
||||
content: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzA4ZTVmZiI+PHBhdGggc3R5bGU9ImxpbmUtaGVpZ2h0Om5vcm1hbDt0ZXh0LWluZGVudDowO3RleHQtYWxpZ246c3RhcnQ7dGV4dC1kZWNvcmF0aW9uLWxpbmU6bm9uZTt0ZXh0LWRlY29yYXRpb24tc3R5bGU6c29saWQ7dGV4dC1kZWNvcmF0aW9uLWNvbG9yOiMwMDA7dGV4dC10cmFuc2Zvcm06bm9uZTtibG9jay1wcm9ncmVzc2lvbjp0Yjtpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0gNSAzIEMgMy45MDY5MzcyIDMgMyAzLjkwNjkzNzIgMyA1IEwgMyAxOSBDIDMgMjAuMDkzMDYzIDMuOTA2OTM3MiAyMSA1IDIxIEwgMTkgMjEgQyAyMC4wOTMwNjMgMjEgMjEgMjAuMDkzMDYzIDIxIDE5IEwgMjEgMTIgTCAxOSAxMiBMIDE5IDE5IEwgNSAxOSBMIDUgNSBMIDEyIDUgTCAxMiAzIEwgNSAzIHogTSAxNCAzIEwgMTQgNSBMIDE3LjU4NTkzOCA1IEwgOC4yOTI5Njg4IDE0LjI5Mjk2OSBMIDkuNzA3MDMxMiAxNS43MDcwMzEgTCAxOSA2LjQxNDA2MjUgTCAxOSAxMCBMIDIxIDEwIEwgMjEgMyBMIDE0IDMgeiIgZm9udC13ZWlnaHQ9IjQwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIHdoaXRlLXNwYWNlPSJub3JtYWwiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMDhlNWZmIi8+PC9zdmc+Cg==');
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
goToHome(){
|
||||
this.$router.push("/")
|
||||
}
|
||||
}
|
||||
goToHome() {
|
||||
this.$router.push('/')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -26,16 +26,14 @@ export default {
|
||||
cursor: pointer;
|
||||
}
|
||||
.gem {
|
||||
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgNDggNDgiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIGZpbGw9IiMwRDQ3QTEiIHBvaW50cz0iMzMsMTcgNDMsMTcgMjQsNDIgIi8+PHBvbHlnb24gZmlsbD0iIzg0RkZGRiIgcG9pbnRzPSI1LDE3IDE1LDUgMTUsMTcgIi8+PHBvbHlnb24gZmlsbD0iIzE5NzZEMiIgcG9pbnRzPSIzMyw1IDMzLDE3IDQzLDE3ICIvPjxnPjxwb2x5Z29uIGZpbGw9IiMwMDkxRUEiIHBvaW50cz0iMTUsMTcgMjMuOTk2LDQyLjE0OSAzMywxNyAiLz48cG9seWdvbiBmaWxsPSIjMDA5MUVBIiBwb2ludHM9IjE1LDUgMjQsNSAxNSwxNyAiLz48cG9seWdvbiBmaWxsPSIjMDA5MUVBIiBwb2ludHM9IjI0LDUgMzMsMTcgMzMsNSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzAwQjBGRiIgcG9pbnRzPSIzMywxNyAxNSwxNyAyNCw1ICIvPjxwb2x5Z29uIGZpbGw9IiMwMEIwRkYiIHBvaW50cz0iMzMsMTcgMzgsMTUgNDMsMTcgMzgsMTkgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMwMEU1RkYiIHBvaW50cz0iMTUsMTcgNSwxNyAyMy45OTYsNDIuMTQ5ICIvPjxwb2x5Z29uIGZpbGw9IiMwMEU1RkYiIHBvaW50cz0iMTUsMTcgMjQsMTUgMzMsMTcgMjQsMTkgIi8+PC9nPjxwb2x5Z29uIGZpbGw9IiNFMEY3RkEiIHBvaW50cz0iNSwxNyAxMCwxNSAxNSwxNyAxMCwxOSAiLz48L3N2Zz4=);
|
||||
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgNDggNDgiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIGZpbGw9IiMwRDQ3QTEiIHBvaW50cz0iMzMsMTcgNDMsMTcgMjQsNDIgIi8+PHBvbHlnb24gZmlsbD0iIzg0RkZGRiIgcG9pbnRzPSI1LDE3IDE1LDUgMTUsMTcgIi8+PHBvbHlnb24gZmlsbD0iIzE5NzZEMiIgcG9pbnRzPSIzMyw1IDMzLDE3IDQzLDE3ICIvPjxnPjxwb2x5Z29uIGZpbGw9IiMwMDkxRUEiIHBvaW50cz0iMTUsMTcgMjMuOTk2LDQyLjE0OSAzMywxNyAiLz48cG9seWdvbiBmaWxsPSIjMDA5MUVBIiBwb2ludHM9IjE1LDUgMjQsNSAxNSwxNyAiLz48cG9seWdvbiBmaWxsPSIjMDA5MUVBIiBwb2ludHM9IjI0LDUgMzMsMTcgMzMsNSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzAwQjBGRiIgcG9pbnRzPSIzMywxNyAxNSwxNyAyNCw1ICIvPjxwb2x5Z29uIGZpbGw9IiMwMEIwRkYiIHBvaW50cz0iMzMsMTcgMzgsMTUgNDMsMTcgMzgsMTkgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMwMEU1RkYiIHBvaW50cz0iMTUsMTcgNSwxNyAyMy45OTYsNDIuMTQ5ICIvPjxwb2x5Z29uIGZpbGw9IiMwMEU1RkYiIHBvaW50cz0iMTUsMTcgMjQsMTUgMzMsMTcgMjQsMTkgIi8+PC9nPjxwb2x5Z29uIGZpbGw9IiNFMEY3RkEiIHBvaW50cz0iNSwxNyAxMCwxNSAxNSwxNyAxMCwxOSAiLz48L3N2Zz4=);
|
||||
background-size: cover;
|
||||
width:35px;
|
||||
height:35px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 0 .3rem;
|
||||
margin: 0 0 0 0.3rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -10,32 +10,34 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from "vuex";
|
||||
import { mapMutations } from 'vuex'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
categories: [{ slug: "", title: "" }]
|
||||
};
|
||||
categories: [{ slug: '', title: '' }],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
areCardsVisible() {
|
||||
return this.$store.getters['Sidebar/areCardsVisible']
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.categories = this.$store.getters['data/resources'].map(({ title, slug }) => ({ title, slug }))
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
toggleCardsVisible: "Sidebar/toggleCardsVisible"
|
||||
})
|
||||
}
|
||||
};
|
||||
toggleCardsVisible: 'Sidebar/toggleCardsVisible',
|
||||
}),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sidebar {
|
||||
position: sticky;
|
||||
top: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
font-size: 14px;
|
||||
|
||||
@@ -5,15 +5,19 @@
|
||||
td.tableRow--links
|
||||
tr
|
||||
td
|
||||
a.tableRow--reference(@click='createCopyUrl(resource)') Copy
|
||||
a.tableRow--reference(@click="createCopyUrl(resource)") Copy
|
||||
td
|
||||
a.tableRow--target(:href="resource.url" :target='resource.title' rel='noreferrer') Open
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['resource', 'isActive', 'createCopyUrl'],
|
||||
};
|
||||
props: {
|
||||
resource: Object,
|
||||
isActive: Boolean,
|
||||
createCopyUrl: Function,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ export default {
|
||||
Github,
|
||||
Logo,
|
||||
Search,
|
||||
Sidebar
|
||||
}
|
||||
Sidebar,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -99,6 +99,35 @@ h1 {
|
||||
grid-gap: 1rem;
|
||||
}
|
||||
|
||||
// Fade in title and cards and rows
|
||||
.fade-title {
|
||||
&-enter {
|
||||
opacity: 0;
|
||||
|
||||
&-to {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-active {
|
||||
transition: opacity .1s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fade-card {
|
||||
&-enter {
|
||||
opacity: 0;
|
||||
|
||||
&-to {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-active {
|
||||
transition: opacity .1s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.layout {
|
||||
|
||||
@@ -18,18 +18,34 @@ export default {
|
||||
{ rel:'manifest', href:'/site.webmanifest' },
|
||||
{ rel:'icon', type:'image/png', sizes:'16x16', href:'/favicon-16x16.png' },
|
||||
{ rel:'icon', type:'image/png', sizes:'32x32', href:'/favicon-32x32.png' },
|
||||
{ rel:'apple-touch-icon', sizes:'76x76', href:'/apple-touch-icon.png' }
|
||||
{ rel:'apple-touch-icon', sizes:'76x76', href:'/apple-touch-icon.png' },
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
|
||||
]
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
||||
],
|
||||
},
|
||||
|
||||
/*
|
||||
** Generate dynamic routes
|
||||
*/
|
||||
generate: {
|
||||
routes: resources.map(category => category.slug)
|
||||
routes: resources.map(category => category.slug),
|
||||
},
|
||||
|
||||
/**
|
||||
* Configure ESLint to run on save with hot reloading
|
||||
*/
|
||||
build: {
|
||||
extend(config, ctx) {
|
||||
if (ctx.isDev && ctx.isClient) {
|
||||
config.module.rules.push({
|
||||
enforce: 'pre',
|
||||
test: /\.(js|vue)$/,
|
||||
loader: 'eslint-loader',
|
||||
exclude: /(node_modules)/,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -38,12 +54,12 @@ export default {
|
||||
loading: { color: '#fff' },
|
||||
|
||||
plugins: [
|
||||
'~/plugins/i18n.js'
|
||||
'~/plugins/i18n.js',
|
||||
],
|
||||
/*
|
||||
** Nuxt.js modules
|
||||
*/
|
||||
modules: [
|
||||
'nuxt-clipboard2',
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
781
package-lock.json
generated
781
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -8,7 +8,9 @@
|
||||
"dev": "nuxt",
|
||||
"build": "nuxt build",
|
||||
"start": "nuxt start",
|
||||
"generate": "nuxt generate"
|
||||
"generate": "nuxt generate",
|
||||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
|
||||
"lintfix": "eslint --fix --ext .js,.vue --ignore-path .gitignore ."
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-env": "^5.2.0",
|
||||
@@ -18,8 +20,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^8.6.4",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-config-prettier": "^6.3.0",
|
||||
"eslint-loader": "^3.0.2",
|
||||
"eslint-plugin-prettier": "^3.1.1",
|
||||
"eslint-plugin-vue": "^5.2.3",
|
||||
"node-sass": "^4.12.0",
|
||||
"nodemon": "^1.18.9",
|
||||
"prettier": "^1.18.2",
|
||||
"pug": "^2.0.3",
|
||||
"pug-plain-loader": "^1.0.0",
|
||||
"sass-loader": "^7.1.0",
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
h1 {{ category.title }}
|
||||
.cards(v-if="areCardsVisible")
|
||||
template(v-for='resource in category.resources' )
|
||||
Card(:resource='resource' :key='resource.title' :createCopyUrl="createCopyUrl" :isActive='activeCard === resource.cleanTitle')
|
||||
table(v-if="!areCardsVisible")
|
||||
template(v-for='resource in category.resources' )
|
||||
TableRow(:resource='resource' :key='resource.title' :createCopyUrl="createCopyUrl" :isActive='activeCard === resource.cleanTitle')
|
||||
transition(name="fade-title" @after-enter="afterEnter")
|
||||
h1(v-if="showTitle") {{ category.title }}
|
||||
transition(name="fade-card")
|
||||
.cards(v-if="areCardsVisible && showCards")
|
||||
template(v-for='resource in category.resources' )
|
||||
Card(:resource='resource' :key='resource.title' :createCopyUrl="createCopyUrl" :isActive='activeCard === resource.cleanTitle')
|
||||
transition(name="fade-card")
|
||||
table(v-if="!areCardsVisible && showCards")
|
||||
template(v-for='resource in category.resources' )
|
||||
TableRow(:resource='resource' :key='resource.title' :createCopyUrl="createCopyUrl" :isActive='activeCard === resource.cleanTitle')
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Card from "../components/Card";
|
||||
import TableRow from "../components/TableRow";
|
||||
import Card from '../components/Card'
|
||||
import TableRow from '../components/TableRow'
|
||||
|
||||
export default {
|
||||
components: { Card, TableRow },
|
||||
data() {
|
||||
return {
|
||||
categoryRouteTitle: this.$route.params.category,
|
||||
index: '',
|
||||
activeCard: '',
|
||||
};
|
||||
showTitle: false,
|
||||
showCards: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
areCardsVisible() {
|
||||
@@ -29,6 +35,12 @@ export default {
|
||||
return this.$store.getters['data/sortByTitle'](this.categoryRouteTitle)
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.activeCard = this.$route.query.card || ''
|
||||
},
|
||||
mounted() {
|
||||
this.showTitle = true
|
||||
},
|
||||
methods: {
|
||||
setActiveCard(index) {
|
||||
this.activeCard = index
|
||||
@@ -40,15 +52,14 @@ export default {
|
||||
this.setActiveCard(cleanTitle)
|
||||
this.$router.push(path)
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
afterEnter() {
|
||||
this.showCards = true
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.activeCard = this.$route.query.card || ''
|
||||
},
|
||||
components: { Card, TableRow }
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -11,8 +11,8 @@ export default ({ app, store }) => {
|
||||
fallbackLocale: 'en',
|
||||
messages: {
|
||||
'en': require('~/locales/en.json'),
|
||||
'fr': require('~/locales/fr.json')
|
||||
}
|
||||
'fr': require('~/locales/fr.json'),
|
||||
},
|
||||
})
|
||||
|
||||
app.i18n.path = (link) => {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
const join = require('path').join
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
]
|
||||
require('autoprefixer'),
|
||||
],
|
||||
}
|
||||
|
||||
@@ -6,133 +6,133 @@
|
||||
"title": "CSS Grid Generator",
|
||||
"desc": "Visually create your css grid and export the code.",
|
||||
"url": "https://cssgrid-generator.netlify.com/",
|
||||
"tags": []
|
||||
"tags": ["generator", "grid", "layout", "visual tool"]
|
||||
},
|
||||
{
|
||||
"title": "Keyframes Editor",
|
||||
"desc": "An insanely simple way to create CSS animations",
|
||||
"url": "https://keyframes.app/editor/",
|
||||
"tags": []
|
||||
"tags": ["generator", "animation", "visual tool"]
|
||||
},
|
||||
{
|
||||
"title": "Flexbox Froggy",
|
||||
"desc": "A game to learn Flexbox",
|
||||
"url": "https://flexboxfroggy.com",
|
||||
"tags": []
|
||||
"tags": ["educational", "beginner"]
|
||||
},
|
||||
{
|
||||
"title": "Flexbox Zombies",
|
||||
"desc": "A course to learn Flexbox",
|
||||
"url": "https://mastery.games/p/flexbox-zombies",
|
||||
"tags": []
|
||||
"tags": ["educational", "beginner"]
|
||||
},
|
||||
{
|
||||
"title": "CSS Gridgarden",
|
||||
"desc": "A game to learn Grid",
|
||||
"url": "https://cssgridgarden.com",
|
||||
"tags": []
|
||||
"tags": ["educational", "beginner"]
|
||||
},
|
||||
{
|
||||
"title": "30 Seconds of Code",
|
||||
"desc": "A curated collection of useful CSS snippets you can understand in 30 seconds or less.",
|
||||
"url": "https://30-seconds.github.io/30-seconds-of-css/",
|
||||
"tags": []
|
||||
"tags": ["tips", "tricks", "collection"]
|
||||
},
|
||||
{
|
||||
"title": "Grid by example",
|
||||
"desc": "Everything you need to learn CSS Grid Layout",
|
||||
"url": "https://gridbyexample.com/learn/",
|
||||
"tags": []
|
||||
"tags": ["example", "showcase", "educational"]
|
||||
},
|
||||
{
|
||||
"title": "BEM naming convention",
|
||||
"desc": "Block Element Modifier is a methodology that helps you to create reusable components and code sharing in front-end development",
|
||||
"url": "https://getbem.com/",
|
||||
"tags": []
|
||||
"tags": ["convention", "naming", "structure"]
|
||||
},
|
||||
{
|
||||
"title": "CSS Triggers",
|
||||
"desc": "Overview of css attributes which trigger either layout, paint or composite. Good to know if you want to learn more about css performance.",
|
||||
"url": "https://csstriggers.com/",
|
||||
"tags": []
|
||||
"tags": ["performance", "rendering"]
|
||||
},
|
||||
{
|
||||
"title": "A complete guide to flexbox",
|
||||
"desc": "A comprehensive guide to flexbox, focusing on all the different possible properties for the parent element (the flex container).",
|
||||
"url": "https://css-tricks.com/snippets/css/a-guide-to-flexbox/",
|
||||
"tags": []
|
||||
"tags": ["guide", "educational"]
|
||||
},
|
||||
{
|
||||
"title": "Learn CSS layout",
|
||||
"desc": "This site teaches the CSS fundamentals that are used in any website's layout (Unfortunately nothing abour display:grid yet).",
|
||||
"desc": "This site teaches the CSS fundamentals that are used in any website's layout.",
|
||||
"url": "http://learnlayout.com",
|
||||
"tags": []
|
||||
"tags": ["layout", "educational", "beginner"]
|
||||
},
|
||||
{
|
||||
"title": "CSSmatic - box shadow generator",
|
||||
"desc": "The ultimate box shadow generator",
|
||||
"url": "https://www.cssmatic.com/box-shadow",
|
||||
"tags": []
|
||||
"tags": ["generator", "visual tool"]
|
||||
},
|
||||
{
|
||||
"title": "AirBnB CSS / Sass Styleguide",
|
||||
"desc": "A mostly reasonable approach to css and sass.",
|
||||
"url": "https://github.com/airbnb/css",
|
||||
"tags": []
|
||||
"tags": ["structure", "styleguide", "convention"]
|
||||
},
|
||||
{
|
||||
"title": "Animista",
|
||||
"desc": "CSS animations on demand.",
|
||||
"url": "http://animista.net/",
|
||||
"tags": []
|
||||
"tags": ["animation", "collection", "generator", "visual tool"]
|
||||
},
|
||||
{
|
||||
"title": "Use CSS Grids the right way",
|
||||
"desc": "CSS Grid is robust, flexible, and a refreshing paradigm shift from other CSS layout systems. While these are selling points for Grid, they also make it hard to learn.",
|
||||
"url": "https://vgpena.github.io/using-css-grid-the-right-way/",
|
||||
"tags": []
|
||||
"tags": ["guide", "educational"]
|
||||
},
|
||||
{
|
||||
"title": "CSS Protips",
|
||||
"desc": "A collection of tips to help take your CSS skills pro.",
|
||||
"url": "https://github.com/AllThingsSmitty/css-protips#readme",
|
||||
"tags": []
|
||||
"tags": ["collection", "tips", "tricks"]
|
||||
},
|
||||
{
|
||||
"title": "Flexbox Defense",
|
||||
"desc": "Your job is to stop the incoming enemies from getting past your defenses. Unlike other tower defense games, you must position your towers using CSS!",
|
||||
"url": "http://www.flexboxdefense.com/",
|
||||
"tags": []
|
||||
"tags": ["educational", "beginner"]
|
||||
},
|
||||
{
|
||||
"title": "CSS Diner",
|
||||
"desc": "Learn CSS selectors while playing a game.",
|
||||
"url": "https://flukeout.github.io/",
|
||||
"tags": []
|
||||
"tags": ["educational", "beginner"]
|
||||
},
|
||||
{
|
||||
"title": "CSS Animation",
|
||||
"desc": "CSS animation articles, tips and tutorials. Level Up Your CSS Animation Skills.",
|
||||
"url": "https://cssanimation.rocks/",
|
||||
"tags": []
|
||||
"tags": ["collection", "guide", "educational"]
|
||||
},
|
||||
{
|
||||
"title": "JustREM",
|
||||
"desc": "Easily and quickly convert pixel values into rem values.",
|
||||
"url": "https://justrem.xyz/",
|
||||
"tags": []
|
||||
"tags": ["units"]
|
||||
},
|
||||
{
|
||||
"title": "(Re)learn css layout",
|
||||
"desc": "If you find yourself wrestling with CSS layout, it’s likely you’re making decisions for browsers they should be making themselves. Through a series of simple, composable layouts, Every Layout will teach you how to better harness the built-in algorithms that power browsers and CSS.",
|
||||
"url": "https://every-layout.dev/",
|
||||
"tags": []
|
||||
"tags": ["educational", "guide"]
|
||||
},
|
||||
{
|
||||
"title": "Interactive CSS box-model view",
|
||||
"desc": "Learn CSS box-model by interractively changing the values.",
|
||||
"url": "https://codepen.io/carolineartz/full/ogVXZj",
|
||||
"tags": []
|
||||
"tags": ["visual tool", "educational", "beginner"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -6,43 +6,43 @@
|
||||
"title": "dev.to",
|
||||
"desc": "Where programmers share ideas and help each other grow. It is an online community for sharing and discovering great ideas, having debates, and making friends.",
|
||||
"url": "https://www.dev.to",
|
||||
"tags": []
|
||||
"tags": ["community", "reading"]
|
||||
},
|
||||
{
|
||||
"title": "CSS Tricks",
|
||||
"desc": "Daily webdev related articles, snippets and guides since 2007",
|
||||
"url": "https://css-tricks.com/",
|
||||
"tags": []
|
||||
"tags": ["reading", "educational", "design"]
|
||||
},
|
||||
{
|
||||
"title": "Smashing magazine",
|
||||
"desc": "Founded in September 2006 in Germany, Smashing Magazine delivers reliable, useful, but most importantly practical articles to web designers and developers. ",
|
||||
"url": "https://www.smashingmagazine.com/",
|
||||
"tags": []
|
||||
"tags": ["reading", "educational", "design", "development"]
|
||||
},
|
||||
{
|
||||
"title": "Hackernews",
|
||||
"desc": "Hacker News is a social news website focusing on computer science and entrepreneurship.",
|
||||
"url": "https://news.ycombinator.com/",
|
||||
"tags": []
|
||||
"tags": ["forum", "development", "reading"]
|
||||
},
|
||||
{
|
||||
"title": "Producthunt",
|
||||
"desc": "Check popular new products out and get inspired, maybe even post yours?",
|
||||
"url": "https://www.producthunt.com/",
|
||||
"tags": []
|
||||
"tags": ["discover", "explore"]
|
||||
},
|
||||
{
|
||||
"title": "dailydevlinks",
|
||||
"desc": "Fresh, daily links so you can keep up-to-date with everything developer ",
|
||||
"url": "https://dailydevlinks.com/",
|
||||
"tags": []
|
||||
"tags": ["development", "reading"]
|
||||
},
|
||||
{
|
||||
"title": "Sidebar.io",
|
||||
"desc": "The five best design links, every day.",
|
||||
"url": "https://sidebar.io/",
|
||||
"tags": []
|
||||
"tags": ["design", "reading"]
|
||||
}
|
||||
]
|
||||
}
|
||||
30
resources/icons.json
Normal file
30
resources/icons.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"title": "Icons",
|
||||
"slug": "/icons",
|
||||
"resources": [
|
||||
{
|
||||
"title": "Font awesome",
|
||||
"desc": "CSS and LESS based font and icon toolkit.",
|
||||
"url": "https://fontawesome.com/",
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"title": "Icomoon",
|
||||
"desc": "IcoMoon provides a package of vector icons, along with a free HTML5 app for making custom icon fonts or SVG sprites.",
|
||||
"url": "https://icomoon.io/",
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"title": "Icons8",
|
||||
"desc": "Get free icons designed to combine perfectly and fit into the style of your design.",
|
||||
"url": "https://icons8.com/",
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"title": "Material Icons",
|
||||
"desc": "Material icons are delightful, beautifully crafted symbols for common actions and items. Download on desktop to use them in your digital products for Android, iOS, and web.",
|
||||
"url": "https://material.io/resources/icons",
|
||||
"tags": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import python from './python'
|
||||
import ruby from './ruby'
|
||||
import server from './server'
|
||||
import utility from './utility'
|
||||
import icons from './icons'
|
||||
|
||||
export default [
|
||||
css,
|
||||
@@ -28,4 +29,5 @@ export default [
|
||||
ruby,
|
||||
server,
|
||||
utility,
|
||||
]
|
||||
icons,
|
||||
]
|
||||
|
||||
@@ -163,6 +163,12 @@
|
||||
"desc": "Let's Encrypt is a free, automated, and open certificate authority brought to you by the non-profit Internet Security Research Group (ISRG).",
|
||||
"url": "https://letsencrypt.org/",
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"title": "Mailhog",
|
||||
"desc": "Web and API based SMTP testing.",
|
||||
"url": "https://github.com/mailhog/MailHog",
|
||||
"tags": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
export const state = () => ({
|
||||
areCardsVisible: true
|
||||
areCardsVisible: true,
|
||||
})
|
||||
|
||||
export const getters = {
|
||||
areCardsVisible: state => state.areCardsVisible
|
||||
areCardsVisible: state => state.areCardsVisible,
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
toggleCardsVisible(state) {
|
||||
if (process.browser) localStorage.setItem('areCardsVisible', !state.areCardsVisible)
|
||||
state.areCardsVisible = !state.areCardsVisible
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -5,20 +5,20 @@ if (!Array.prototype.flat) {
|
||||
Object.defineProperty(Array.prototype, 'flat', {
|
||||
configurable: true,
|
||||
value: function flat () {
|
||||
var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]);
|
||||
var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0])
|
||||
|
||||
return depth ? Array.prototype.reduce.call(this, function (acc, cur) {
|
||||
if (Array.isArray(cur)) {
|
||||
acc.push.apply(acc, flat.call(cur, depth - 1));
|
||||
acc.push.apply(acc, flat.call(cur, depth - 1))
|
||||
} else {
|
||||
acc.push(cur);
|
||||
acc.push(cur)
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []) : Array.prototype.slice.call(this);
|
||||
return acc
|
||||
}, []) : Array.prototype.slice.call(this)
|
||||
},
|
||||
writable: true
|
||||
});
|
||||
writable: true,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,14 +39,14 @@ export const state = () => ({
|
||||
cleanTitle,
|
||||
path: `${category.slug}?card=${cleanTitle}`,
|
||||
}
|
||||
})
|
||||
}),
|
||||
})),
|
||||
// List of all tags, duplicates removed
|
||||
tags: [...new Set(
|
||||
resources
|
||||
.map(resource => resource.resources).flat()
|
||||
.map(resource => resource.tags).flat()
|
||||
)]
|
||||
)],
|
||||
})
|
||||
|
||||
export const getters = {
|
||||
@@ -64,9 +64,9 @@ export const getters = {
|
||||
const clone = [...category.resources]
|
||||
return {
|
||||
...category,
|
||||
resources: clone.sort(compareTitles)
|
||||
resources: clone.sort(compareTitles),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const compareTitles = (x, y) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const state = () => ({
|
||||
locales: ['en', 'fr', 'de'],
|
||||
locale: 'en'
|
||||
locale: 'en',
|
||||
})
|
||||
|
||||
export const mutations = {
|
||||
@@ -8,5 +8,5 @@ export const mutations = {
|
||||
if (state.locales.indexOf(locale) !== -1) {
|
||||
state.locale = locale
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user