mirror of
https://github.com/dzeiocom/markblog.git
synced 2025-04-22 02:42:14 +00:00
updated
Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
parent
e5fb01eea8
commit
a0f1799114
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
@ -1,11 +1,13 @@
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { ChevronRight } from 'react-feather'
|
||||
import next from 'next'
|
||||
|
||||
interface Props {
|
||||
title: string
|
||||
date: Date
|
||||
image?: string
|
||||
alt?: string
|
||||
link: string
|
||||
}
|
||||
|
||||
@ -30,31 +32,41 @@ export default class Element extends React.Component<Props, {}> {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
let date = this.props.date
|
||||
if (typeof this.props.date === "string") {
|
||||
date = new Date(this.props.date)
|
||||
}
|
||||
const t = `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}`
|
||||
return (
|
||||
<div>
|
||||
<Link href={this.props.link}>
|
||||
{this.props.image ? (
|
||||
<a><img src={this.props.image}/></a>
|
||||
<a><img src={this.props.image} alt={this.props.alt}/></a>
|
||||
) : (
|
||||
<div></div>
|
||||
)}
|
||||
</Link>
|
||||
|
||||
<i>Le {this.props.date.getDate()} {months[this.props.date.getMonth()]} {this.props.date.getFullYear()}</i>
|
||||
<i>Le {t}</i>
|
||||
<span>
|
||||
<Link href={this.props.link}>
|
||||
<a>{this.props.title}</a>
|
||||
</Link>
|
||||
<Link href={this.props.link}>
|
||||
<Link as={this.props.link} href="/[category]/[slug]">
|
||||
<a><ChevronRight size={48}/></a>
|
||||
</Link>
|
||||
</span>
|
||||
<style jsx>{`
|
||||
div {
|
||||
padding: 5% 5%;
|
||||
min-width: 90%;
|
||||
}
|
||||
@media (min-width: 840px) {
|
||||
div {
|
||||
max-width: 40%;
|
||||
min-width: 400px;
|
||||
}
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
|
@ -1,13 +1,11 @@
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import Category from './interfaces/Category'
|
||||
import '../styl/styl.styl'
|
||||
import { ChevronRight } from 'react-feather'
|
||||
import Router from 'next/router'
|
||||
import { ChevronRight, ChevronDown } from 'react-feather'
|
||||
|
||||
interface Props {
|
||||
categories?: Category[]
|
||||
onQuery?: (query: string) => void
|
||||
categories?: string[]
|
||||
onQuery?: (query: string, sort?: boolean) => void
|
||||
onHeight?: (height: number) => void
|
||||
}
|
||||
|
||||
@ -25,20 +23,10 @@ export default class Filters extends React.Component<Props, States> {
|
||||
super(props)
|
||||
}
|
||||
|
||||
setRef = element => {
|
||||
this.aside = element
|
||||
}
|
||||
|
||||
setInput = element => {
|
||||
this.input = element
|
||||
}
|
||||
|
||||
onScroll = () => {
|
||||
this.setState({
|
||||
follow: window.pageYOffset > 217
|
||||
})
|
||||
}
|
||||
|
||||
onKeyDown = (ev: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
setTimeout(() => {
|
||||
this.submit()
|
||||
@ -53,73 +41,65 @@ export default class Filters extends React.Component<Props, States> {
|
||||
this.input.focus()
|
||||
}
|
||||
|
||||
submit = () => {
|
||||
if (this.props.onQuery) this.props.onQuery(this.input.value)
|
||||
onChange = (ev) => {
|
||||
this.submit(ev.target.value === "true")
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
this.onScroll()
|
||||
this.setState({
|
||||
height: this.aside.clientHeight
|
||||
})
|
||||
if (this.props.onHeight) this.props.onHeight(this.aside.clientHeight)
|
||||
window.addEventListener('scroll', this.onScroll)
|
||||
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('scroll', this.onScroll)
|
||||
submit = (sort?: boolean) => {
|
||||
if (this.props.onQuery) this.props.onQuery(this.input.value, sort)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<aside ref={this.setRef} className={this.state && this.state.follow ? "follow" : ""}>
|
||||
<aside>
|
||||
<div>Trier</div>
|
||||
<div className="input icon-right">
|
||||
<select>
|
||||
<option value="plus récant au moins récent"></option>
|
||||
<select onChangeCapture={this.onChange}>
|
||||
<option value="true">plus récent au moins récent</option>
|
||||
<option value="false">moins récent au plus récent</option>
|
||||
</select>
|
||||
<i>
|
||||
<ChevronDown />
|
||||
</i>
|
||||
</div>
|
||||
<div>Filtrer</div>
|
||||
<div className="input icon-right">
|
||||
<div className="input icon-right inline">
|
||||
<input placeholder="ex: dzeio.com" type="text" ref={this.setInput} onKeyDownCapture={this.onKeyDown} />
|
||||
<i>
|
||||
<ChevronRight onClick={this.onClick} />
|
||||
</i>
|
||||
</div>
|
||||
<p>Languages :</p>
|
||||
<span>
|
||||
{this.props.categories.map(cat => (
|
||||
<Link key={cat.slug} href={cat.slug}>
|
||||
<a>{cat.name}</a>
|
||||
<Link key={cat} href="/tag/[tag]" as={`/tag/${cat.toLowerCase()}`}>
|
||||
<a className="button">{cat}</a>
|
||||
</Link>
|
||||
))}
|
||||
</span>
|
||||
|
||||
|
||||
<style jsx>{`
|
||||
|
||||
aside {
|
||||
padding: 5% 3% 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 445px;
|
||||
}
|
||||
|
||||
@media (min-width: 820px) and (min-height: ${this.state && this.state.height ? this.state.height+100 : 600}px) {
|
||||
aside {
|
||||
position: absolute;
|
||||
min-width: calc(400px - 6%);
|
||||
right: 0;
|
||||
}
|
||||
|
||||
|
||||
aside.follow {
|
||||
position: fixed;
|
||||
top: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.input {
|
||||
/*.input {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 20px 0;
|
||||
}*/
|
||||
|
||||
span {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
a {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
div:not(.input) {
|
||||
@ -134,21 +114,8 @@ export default class Filters extends React.Component<Props, States> {
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
}
|
||||
a {
|
||||
padding: 7px 12px;
|
||||
background: #4285F4;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
border-radius: 10px;
|
||||
font-size: 20px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
|
||||
transition: background 200ms
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: #45CAFC;
|
||||
.input {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
|
72
components/Footer.tsx
Normal file
72
components/Footer.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
import React from 'react'
|
||||
import { PhoneCall, Mail, GitHub, Twitter, Linkedin } from 'react-feather'
|
||||
import Link from 'next/link'
|
||||
|
||||
interface Props {}
|
||||
|
||||
interface States {}
|
||||
|
||||
export default class Footer extends React.Component<Props, States> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<footer>
|
||||
<div className="pre"></div>
|
||||
<div className="footer">
|
||||
<span>
|
||||
<a href="mailto:contact@avior.me" target="_blank">
|
||||
<Mail color="#4285F4" />
|
||||
</a>
|
||||
<a href="tel:+33672292683" target="_blank">
|
||||
<PhoneCall color="#4285F4" />
|
||||
</a>
|
||||
<a href="https://git.delta-wings.net" target="_blank">
|
||||
<GitHub color="#4285F4" />
|
||||
</a>
|
||||
<a href="https://twitter.com/aviortheking" target="_blank">
|
||||
<Twitter color="#4285F4" />
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/in/florian-bouillon/" target="_blank">
|
||||
<Linkedin color="#4285F4" />
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<style jsx>{`
|
||||
footer {
|
||||
padding-top: 50px;
|
||||
}
|
||||
.pre {
|
||||
height: 20px;
|
||||
background: #EEE;
|
||||
}
|
||||
.footer {
|
||||
display: flex;
|
||||
padding: 13px 10%;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.footer span {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
@media (min-width: 850px) {
|
||||
.footer {
|
||||
padding: 20px 0
|
||||
}
|
||||
.footer span {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
@ -10,20 +10,27 @@ export default class Header extends React.Component<Props, {}> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<img src="/clouds.svg" alt=""/>
|
||||
|
||||
|
||||
{/* <p>Bienvenue sur le Portfolio de Florian BOUILLON !</p> */}
|
||||
<style jsx>{`
|
||||
div {
|
||||
position: relative;
|
||||
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||
height: 207px;
|
||||
background: url('/clouds.svg'), linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||
background-repeat: repeat-x;
|
||||
background-position: bottom;
|
||||
min-height: 207px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
color: white;
|
||||
font-size: 35px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
img {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
min-width: 100%;
|
||||
height: 50px
|
||||
height: 50px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
|
55
components/Layout.tsx
Normal file
55
components/Layout.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import React from 'react'
|
||||
import Navbar from './Navbar'
|
||||
import Menu from './Menu'
|
||||
import Header from './Header'
|
||||
import Footer from './Footer'
|
||||
|
||||
interface Props {
|
||||
hasHeader?: boolean
|
||||
headerChild?: JSX.Element
|
||||
}
|
||||
|
||||
export default class Layout extends React.Component<Props, {}> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Navbar>
|
||||
<Menu />
|
||||
</Navbar>
|
||||
{this.props.hasHeader && this.props.headerChild ? (
|
||||
<Header>{this.props.headerChild}</Header>
|
||||
) : (
|
||||
<Header />
|
||||
)}
|
||||
{this.props.children}
|
||||
<Footer />
|
||||
<style jsx>{`
|
||||
div {
|
||||
height: inherit;
|
||||
width: inherit;
|
||||
}
|
||||
`}</style>
|
||||
<style jsx global>{`
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
::selection {
|
||||
background: #4285F4;
|
||||
color: #FFF;
|
||||
}
|
||||
body {
|
||||
height: calc(100% - 80px)
|
||||
}
|
||||
#root, #__next {
|
||||
height: 100%;
|
||||
width : 100%;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import { Menu } from 'react-feather'
|
||||
import { timingSafeEqual } from 'crypto'
|
||||
import Link from 'next/link'
|
||||
|
||||
interface Props {
|
||||
height?: number
|
||||
@ -59,11 +60,19 @@ export default class Navbar extends React.Component<Props, States> {
|
||||
margin-top: ${height}px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.menu * {
|
||||
pointer-events: none;
|
||||
}
|
||||
.menu.shown * {
|
||||
pointer-events: initial;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<hr />
|
||||
<div className="head">
|
||||
<img src="/logo.svg" alt=""/>
|
||||
<Link href="/">
|
||||
<a><img src="/logo.svg" alt=""/></a>
|
||||
</Link>
|
||||
<span onClick={this.onClick} data-menu={this.refs.menu}>
|
||||
<Menu size={30} />
|
||||
</span>
|
||||
@ -84,8 +93,11 @@ export default class Navbar extends React.Component<Props, States> {
|
||||
nav.scrolled {
|
||||
box-shadow: 0 0 10px 5px #00000040
|
||||
}
|
||||
img {
|
||||
height: 80%;
|
||||
a {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
hr {
|
||||
height: 10px;
|
||||
@ -94,10 +106,14 @@ export default class Navbar extends React.Component<Props, States> {
|
||||
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||
}
|
||||
.menu {
|
||||
display: none
|
||||
opacity: 0;
|
||||
pointer-event: none;
|
||||
height: 0;
|
||||
transition: opacity 200ms cubic-bezier(.2,0,.6,1);
|
||||
}
|
||||
.menu.shown {
|
||||
display: block
|
||||
opacity: 1;
|
||||
height: initial;
|
||||
}
|
||||
.head {
|
||||
display: flex;
|
||||
@ -109,10 +125,13 @@ export default class Navbar extends React.Component<Props, States> {
|
||||
}
|
||||
img {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
|
||||
}
|
||||
span {
|
||||
width: ${height-10}px;
|
||||
height: ${height-10}px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
@ -7,8 +7,15 @@ interface PostInterface {
|
||||
content: any
|
||||
}
|
||||
|
||||
interface PostHeader {
|
||||
export interface PostHeader {
|
||||
title: string
|
||||
id: string
|
||||
category: string
|
||||
image?: string
|
||||
imageAlt?: string
|
||||
date: Date
|
||||
url?: string
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
export default class Post implements PostInterface {
|
||||
@ -18,23 +25,27 @@ export default class Post implements PostInterface {
|
||||
public content: string
|
||||
public isStarted = false
|
||||
|
||||
public header: PostHeader
|
||||
|
||||
constructor(slug: string) {
|
||||
this.slug = slug
|
||||
}
|
||||
|
||||
public async fetch() {
|
||||
console.log(this.slug)
|
||||
const content = await import(`../posts/${this.slug}.md`)
|
||||
if (!this.slug.endsWith(".md")) this.slug = "portfolio/" + this.slug + ".md"
|
||||
const content = await import(`../posts/${this.slug}`)
|
||||
const md = matter(content.default)
|
||||
this.title = md.data.title
|
||||
this.header = (md.data as PostHeader)
|
||||
this.content = md.content
|
||||
}
|
||||
|
||||
public fetchSync() {
|
||||
console.log(this.slug)
|
||||
const content = require(`../posts/${this.slug}.md`)
|
||||
if (!this.slug.endsWith(".md")) this.slug = "portfolio/" + this.slug + ".md"
|
||||
const content = require(`../posts/${this.slug}`)
|
||||
const md = matter(content.default)
|
||||
this.title = md.data.title
|
||||
this.header = (md.data as PostHeader)
|
||||
this.content = md.content
|
||||
}
|
||||
|
||||
@ -44,10 +55,7 @@ export default class Post implements PostInterface {
|
||||
for (const file of files) {
|
||||
posts.push(
|
||||
new Post(
|
||||
file.replace(/^.*[\\\/]/, '')
|
||||
.split('.')
|
||||
.slice(0, -1)
|
||||
.join('.')
|
||||
file.replace("./", '')
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import React from 'react'
|
||||
|
||||
interface Props {
|
||||
}
|
||||
interface Props {}
|
||||
|
||||
export default class Name extends React.Component<Props, {}> {
|
||||
interface States {}
|
||||
|
||||
export default class Name extends React.Component<Props, States> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
export default interface Category {
|
||||
name: string
|
||||
slug: string
|
||||
}
|
@ -36,13 +36,15 @@ const options3 = {
|
||||
async function run() {
|
||||
try {
|
||||
const res3 = await replace(options3)
|
||||
console.log(res3)
|
||||
// console.log(res3)
|
||||
const res2 = await replace(options2)
|
||||
console.log(res2)
|
||||
// console.log(res2)
|
||||
const results = await replace(options)
|
||||
console.log(results)
|
||||
// console.log(results)
|
||||
process.exit(0)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
const withCSS = require('@zeit/next-stylus')
|
||||
const glob = require('glob')
|
||||
const withOffline = require('next-offline')
|
||||
const matter = require('gray-matter')
|
||||
const fs = require('fs')
|
||||
// import posts from './posts/pages.json.ts'
|
||||
// const posts = require('./posts/pages.json.ts')
|
||||
// const t = require('./pages/portfolio/')
|
||||
@ -22,17 +24,20 @@ module.exports = withOffline(withCSS({
|
||||
exportPathMap: async function() {
|
||||
const paths = {
|
||||
'/': { page: '/'},
|
||||
'/portfolio': { page: '/portfolio'},
|
||||
}
|
||||
|
||||
const posts = glob.sync('./posts/**/*.md')
|
||||
|
||||
posts.forEach(element => {
|
||||
const datas = matter(fs.readFileSync(element)).data
|
||||
element = element.replace(/^.*[\\\/]/, '')
|
||||
.split('.')
|
||||
.slice(0, -1)
|
||||
.join('.')
|
||||
paths[`/portfolio/${element}`] = { page: '/portfolio/[slug]', query: { slug: element}}
|
||||
paths[`/${datas.category.toLowerCase()}/${datas.id}`] = { page: '/[category]/[slug]', query: {category: datas.category.toLowerCase(), slug: datas.id}}
|
||||
for (const tg of datas.tags) {
|
||||
paths[`/tag/${tg.toLowerCase()}`] = { page: '/tag/[tag]', query: {tag: tg}}
|
||||
}
|
||||
});
|
||||
|
||||
return paths
|
||||
|
@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"@zeit/next-css": "^1.0.1",
|
||||
"@zeit/next-stylus": "^1.0.1",
|
||||
"fs": "^0.0.1-security",
|
||||
"glob": "^7.1.6",
|
||||
"gray-matter": "^4.0.2",
|
||||
"next": "9.1.5",
|
||||
|
128
pages/[category]/[slug].tsx
Normal file
128
pages/[category]/[slug].tsx
Normal file
@ -0,0 +1,128 @@
|
||||
import { NextPageContext } from "next"
|
||||
|
||||
import{ Component } from 'react'
|
||||
import Post from "../../components/Post"
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import Error from "../_error"
|
||||
import Link from "next/link"
|
||||
|
||||
interface Props {
|
||||
post: Post
|
||||
}
|
||||
|
||||
interface States {
|
||||
imgHeight: number
|
||||
}
|
||||
|
||||
export default class PostPage extends Component<Props, States> {
|
||||
public render() {
|
||||
return (
|
||||
<main>
|
||||
{this.props.post === undefined ? (
|
||||
<Error statusCode={404} />
|
||||
) : (
|
||||
<div>
|
||||
<img src={this.props.post.header.image} alt={this.props.post.header.imageAlt} />
|
||||
<ReactMarkdown source={this.props.post.content}/>
|
||||
<h2>Détails</h2>
|
||||
<p>Tags:</p>
|
||||
<ul>
|
||||
{this.props.post.header.tags.map((el) => (
|
||||
<li>
|
||||
<Link href="/tag/[tag]" as={'/tag/'+el.toLowerCase()}>
|
||||
<a className="button">{el}</a>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{this.props.post.header.url ? (
|
||||
<a className="button outline large" href={this.props.post.header.url}>Visiter le site :D</a>
|
||||
) : undefined}
|
||||
</div>
|
||||
)}
|
||||
<style jsx global>{`
|
||||
main h1 {
|
||||
font-size: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
main h2 {
|
||||
font-size: 40px;
|
||||
text-align: center;
|
||||
text-shadow: 4px 4px 0px rgba(66, 133, 244, 0.5);
|
||||
}
|
||||
main h2::selection {
|
||||
text-shadow: 4px 4px 0px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
main p {
|
||||
text-align: justify;
|
||||
}
|
||||
.header {
|
||||
height: 250px;
|
||||
}
|
||||
@media (min-width: 820px) {
|
||||
.header {
|
||||
height: 0
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
<style jsx>{`
|
||||
main div {
|
||||
margin-top: -150px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
padding: 0 10%;
|
||||
}
|
||||
main a.button.outline {
|
||||
align-self: center;
|
||||
}
|
||||
@media (min-width: 820px) {
|
||||
main div {
|
||||
margin-top: 0
|
||||
}
|
||||
main img {
|
||||
max-width: 750px;
|
||||
}
|
||||
}
|
||||
main img {
|
||||
z-index: 999;
|
||||
max-width: 100%;
|
||||
border-radius: 10px;
|
||||
max-height: 300px;
|
||||
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
/*
|
||||
li {
|
||||
border-radius: 10px;
|
||||
background: #4285F4;
|
||||
color: white;
|
||||
margin: 10px;
|
||||
display: inline-block;
|
||||
transition: background 200ms;
|
||||
}
|
||||
li:hover {
|
||||
background: #45CAFC;
|
||||
}
|
||||
li a {
|
||||
padding: 15px 20px;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}*/
|
||||
li {
|
||||
display: inline-block;
|
||||
}
|
||||
`}</style>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
public static async getInitialProps(context: NextPageContext) {
|
||||
const { slug } = context.query
|
||||
if (typeof slug === "object" || slug === "[slug]") return {post: undefined}
|
||||
const post = new Post(slug)
|
||||
await post.fetch()
|
||||
return {post}
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ const PortfolioIndex: NextPage<Props> = (props: Props) => {
|
||||
<ul>
|
||||
{props.files.map(post => (
|
||||
<li key={post.slug}>
|
||||
<Link href="/portfolio/[slug]" as={`/portfolio/${post.slug}`}>
|
||||
<Link href="/[category]/[slug]" as={`/${post.slug}`}>
|
||||
<a>{post.title}</a>
|
||||
</Link>
|
||||
</li>
|
||||
@ -41,7 +41,7 @@ PortfolioIndex.getInitialProps = async (context: NextPageContext) => {
|
||||
for (const post of await Post.fetchAll()) {
|
||||
if (!post.isStarted) await post.fetch()
|
||||
arr.push({
|
||||
slug: post.slug,
|
||||
slug: post.slug.replace(".md", ""),
|
||||
title: post.title
|
||||
})
|
||||
}
|
||||
@ -49,10 +49,3 @@ PortfolioIndex.getInitialProps = async (context: NextPageContext) => {
|
||||
}
|
||||
|
||||
export default PortfolioIndex
|
||||
|
||||
function l(args: any) {
|
||||
console.log(arguments)
|
||||
}
|
||||
|
||||
async function test() {
|
||||
}
|
@ -1,22 +1,16 @@
|
||||
import React from 'react'
|
||||
import App from 'next/app'
|
||||
import '../styl/styl.styl'
|
||||
import Layout from '../components/Layout'
|
||||
|
||||
class MyApp extends App {
|
||||
// Only uncomment this method if you have blocking data requirements for
|
||||
// every single page in your application. This disables the ability to
|
||||
// perform automatic static optimization, causing every page in your app to
|
||||
// be server-side rendered.
|
||||
//
|
||||
// static async getInitialProps(appContext) {
|
||||
// // calls page's `getInitialProps` and fills `appProps.pageProps`
|
||||
// const appProps = await App.getInitialProps(appContext);
|
||||
//
|
||||
// return { ...appProps }
|
||||
// }
|
||||
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return <Component {...pageProps} />
|
||||
return(
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,9 @@ class MyDocument extends Document {
|
||||
render() {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<Head>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
|
58
pages/_error.tsx
Normal file
58
pages/_error.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import React, { Component } from 'react'
|
||||
import { NextPageContext } from 'next'
|
||||
import Head from 'next/head'
|
||||
import Layout from '../components/Layout'
|
||||
|
||||
interface Props {
|
||||
statusCode: number
|
||||
}
|
||||
|
||||
const codesTexts = {
|
||||
404: "Page non trouvé !",
|
||||
500: "Le serveur n'a pas pu répondre a ta demande :O"
|
||||
}
|
||||
|
||||
export default class Error extends Component<Props, {}> {
|
||||
public render = () => {
|
||||
const statusCode = this.props.statusCode
|
||||
return (
|
||||
<main>
|
||||
<Head>
|
||||
<title>Pouet :D</title>
|
||||
</Head>
|
||||
<div className="errorContainer">
|
||||
<h1>{statusCode ? statusCode : "404"}</h1>
|
||||
<h2>{statusCode ? codesTexts[statusCode] : codesTexts[404]}</h2>
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.errorContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 100%
|
||||
}
|
||||
|
||||
.separator {
|
||||
border: 1px solid black
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 250px;
|
||||
margin: 10px;
|
||||
color: transparent;
|
||||
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
getInitialProps = ({ res, err }: NextPageContext) => {
|
||||
const statusCode = res ? res.statusCode : err ? err.statusCode : 404
|
||||
return { statusCode }
|
||||
}
|
||||
}
|
123
pages/index.tsx
123
pages/index.tsx
@ -1,124 +1,119 @@
|
||||
import { NextPage } from 'next'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import '../styl/styl.styl'
|
||||
import Element from '../components/Element'
|
||||
import Navbar from '../components/Navbar'
|
||||
import Header from '../components/Header'
|
||||
import Menu from '../components/Menu'
|
||||
import Filters from '../components/Filters'
|
||||
import Category from '../components/interfaces/Category'
|
||||
import { Component } from 'react'
|
||||
import Post, { PostHeader } from '../components/Post'
|
||||
|
||||
interface Props {
|
||||
userAgent?: string
|
||||
}
|
||||
|
||||
interface el {
|
||||
link: string,
|
||||
title: string,
|
||||
img: string,
|
||||
date: Date
|
||||
}
|
||||
interface el extends PostHeader {}
|
||||
|
||||
interface States {
|
||||
elements: el[]
|
||||
loaded: boolean
|
||||
asideHeight: number
|
||||
categories: string[]
|
||||
}
|
||||
|
||||
// export const config = {amp: 'hybrid'}
|
||||
|
||||
const categories: Category[] = [
|
||||
{
|
||||
name: "test",
|
||||
slug: "pouet"
|
||||
}
|
||||
]
|
||||
|
||||
const elements: el[] = [
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Dzeio.io, Services en ligne pour vous simplifier la vie !", img:"/sea.jpg", date: new Date()},
|
||||
{link:"/studiomoto", title:"Loram ipsum dolor sit amet", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"j'aime les licornes et leurs jolie corne", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Pokémon ! attrapez les tous !", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"abcde", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"def", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"abc", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
|
||||
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()}
|
||||
]
|
||||
let elements: PostHeader[] = []
|
||||
|
||||
export default class Page extends Component<Props, States> {
|
||||
|
||||
onQuery = (query: string) => {
|
||||
console.log(`query: ${query}`)
|
||||
onQuery = async (query: string, recent: boolean = true) => {
|
||||
// console.log(`query: ${query}`)
|
||||
const t= elements.filter(el => {
|
||||
return el.title.toLowerCase().includes(query.toLowerCase())
|
||||
})
|
||||
if (recent) {
|
||||
t.sort((a, b) => {
|
||||
return (a.date < b.date) ? 1 : -1
|
||||
})
|
||||
} else {
|
||||
t.sort((a, b) => {
|
||||
return (a.date > b.date) ? 1 : -1
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
elements: t
|
||||
})
|
||||
}
|
||||
|
||||
onHeight = (height: number) => {
|
||||
onHeight = async (height: number) => {
|
||||
this.setState({
|
||||
asideHeight: height
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
async componentDidMount() {
|
||||
const posts = await Post.fetchAll()
|
||||
const header: Array<PostHeader> = []
|
||||
let cats: Array<string> = []
|
||||
posts.forEach(el => {
|
||||
el.fetchSync()
|
||||
header.push(el.header)
|
||||
cats.push(...el.header.tags)
|
||||
})
|
||||
header.sort((a, b) => {
|
||||
return (a.date < b.date) ? 1 : -1
|
||||
})
|
||||
|
||||
cats.sort((a, b) => (a < b) ? -1 : 1)
|
||||
|
||||
elements = header
|
||||
this.setState({
|
||||
elements
|
||||
elements: header,
|
||||
loaded: true,
|
||||
categories: cats.filter((item, pos) => {return cats.indexOf(item) === pos})
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
</Head>
|
||||
<Navbar>
|
||||
<Menu />
|
||||
</Navbar>
|
||||
<Header />
|
||||
<main>
|
||||
<span>
|
||||
{this.state && this.state.elements.map((el, index) => (
|
||||
<Element key={index} link={el.link} title={el.title} image={el.img} date={el.date} />
|
||||
))}
|
||||
{this.state && this.state.elements && this.state.elements.length !== 0 ? this.state.elements.map((el, index) => (
|
||||
<Element key={index} link={"/"+el.category.toLowerCase() + "/" + el.id} title={el.title} image={el.image} alt={el.imageAlt} date={el.date || new Date} />
|
||||
)) : this.state && this.state.loaded ? (
|
||||
<div>La recherche n'a rien donnée <span className="emoji">😢</span></div>
|
||||
) : (
|
||||
<div>Chargement en cours... <span className="emoji">😃</span></div>
|
||||
)}
|
||||
</span>
|
||||
<Filters categories={categories} onQuery={this.onQuery} onHeight={this.onHeight}/>
|
||||
</main>
|
||||
<Filters categories={this.state && this.state.categories || []} onQuery={this.onQuery} onHeight={this.onHeight}/>
|
||||
<style jsx>{`
|
||||
span {
|
||||
span:not(.emoji) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
main span {
|
||||
flex-grow: 1;
|
||||
div {
|
||||
font-size: 36px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (min-width: 820px) and (min-height: ${this.state && this.state.asideHeight ? this.state.asideHeight+100 : 600}px) {
|
||||
main span {
|
||||
span {
|
||||
max-width: calc(100% - 400px);
|
||||
}
|
||||
main {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { NextPage, NextPageContext } from "next"
|
||||
|
||||
import React from 'react'
|
||||
import Post from "../../components/Post"
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
|
||||
interface Props {
|
||||
post: Post
|
||||
}
|
||||
|
||||
const PostPage: NextPage<Props> = (props: Props) => {
|
||||
// React.
|
||||
return (
|
||||
<main>
|
||||
<ReactMarkdown source={props.post.content}/>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
PostPage.getInitialProps = async (context: NextPageContext) => {
|
||||
const { slug } = context.query
|
||||
if (typeof slug === "object") throw new Error("Slug is not correct")
|
||||
const post = new Post(slug)
|
||||
await post.fetch()
|
||||
return {post}
|
||||
}
|
||||
|
||||
export default PostPage
|
85
pages/tag/[tag].tsx
Normal file
85
pages/tag/[tag].tsx
Normal file
@ -0,0 +1,85 @@
|
||||
import { NextPage, NextPageContext } from "next"
|
||||
import Link from 'next/link'
|
||||
import Post from "../../components/Post"
|
||||
import Element from '../../components/Element'
|
||||
import Error from "../_error"
|
||||
// import posts from '../../posts/pages.json'
|
||||
// import firstline from 'firstline'
|
||||
// import 'fs'
|
||||
|
||||
interface Props {
|
||||
files: Post[],
|
||||
tag: string
|
||||
}
|
||||
|
||||
const PortfolioIndex: NextPage<Props> = (props: Props) => {
|
||||
|
||||
const el: JSX.Element[] = []
|
||||
for (const post of props.files) {
|
||||
el.push(
|
||||
)
|
||||
}
|
||||
|
||||
if (props.files.length === 0) {
|
||||
return (
|
||||
<Error statusCode={404} />
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Tag: {props && props.tag}</h2>
|
||||
<div>
|
||||
{props.files.map((post, index) => (
|
||||
<Element key={index} link={"/"+post.header.category.toLowerCase() + "/" + post.header.id} title={post.header.title} image={post.header.image} date={post.header.date || new Date} />
|
||||
))}
|
||||
</div>
|
||||
<style jsx>{`
|
||||
span:not(.emoji) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
div div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
h2 {
|
||||
display: inline-block;
|
||||
padding: 20px;
|
||||
margin: auto;
|
||||
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
PortfolioIndex.getInitialProps = async (context: NextPageContext) => {
|
||||
const { tag } = context.query
|
||||
if (typeof tag === "object" || tag === "[tag]") return {files: [], tag: ""}
|
||||
const arr: Post[] = []
|
||||
for (const post of await Post.fetchAll()) {
|
||||
if (!post.isStarted) await post.fetch()
|
||||
let tags = []
|
||||
for (const tg of post.header.tags) {
|
||||
tags.push(tg.toLowerCase())
|
||||
}
|
||||
if (!tags.includes(tag)) continue
|
||||
arr.push(post)
|
||||
}
|
||||
return {files: arr, tag: tag} as Props
|
||||
}
|
||||
|
||||
export default PortfolioIndex
|
12
posts/portfolio/dzeio.md
Normal file
12
posts/portfolio/dzeio.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: DZE.IO
|
||||
id: dzeio
|
||||
image: /uploads/dzeio.png
|
||||
imageAlt: Logo & Description de dze.io
|
||||
date: 2020-06-01
|
||||
category: Portfolio
|
||||
url: https://dze.io/
|
||||
tags: ["Golang", "Javascript", "Typescript", "CSS", "Stylus"]
|
||||
---
|
||||
|
||||
# Dze.io, Page en cours 😄
|
28
posts/portfolio/studiomoto.md
Normal file
28
posts/portfolio/studiomoto.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Studiomoto
|
||||
id: studiomoto
|
||||
image: /uploads/stm.png
|
||||
imageAlt: Logo & Description de studiomoto
|
||||
date: 2018-10-10
|
||||
category: Portfolio
|
||||
url: https://www.studiomoto.fr/
|
||||
tags: ["PHP", "Symfony", "Javascript", "Typescript", "CSS", "Stylus"]
|
||||
---
|
||||
|
||||
# Studiomoto, Site de référencement d’événement Moto en France
|
||||
|
||||
## Objectifs premiers
|
||||
|
||||
L’idée était de transformer un encien site sous Wordpress en un site construit de zéro afin de pouvoir en faire un système facilement ajustable, plus customisable et plus rapide.
|
||||
|
||||
Afin d’atteindre ces trois points il a été choisis de partir sur Symfony afin de pouvoir avoir un site fonctionnel rapidement.
|
||||
|
||||
## Développement
|
||||
|
||||
Le site est en constante évolution et la roadmap est la suivant :
|
||||
|
||||
- Visualisation des évènement en front pour le public et un dashboard pour les Administrateurs afin de pouvoir ajouter et modifier le évenements
|
||||
|
||||
- Les utilisateurs et organisations peuvent se connecter au site et peuvent rajouter des évènements
|
||||
|
||||
- Plus d’interaction entre le site et les utilisateurs en ajoutant une fonctionnalité de balade.
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: pouet :D
|
||||
---
|
||||
|
||||
# Pouet :D
|
3
public/fonts/Aileron-Black.ttf
Normal file
3
public/fonts/Aileron-Black.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b4ade4e081b12facd22a9e7ffddb10bdf32d978024ba4cd6a06cae5c971da0ef
|
||||
size 38088
|
3
public/fonts/Aileron-BlackItalic.ttf
Normal file
3
public/fonts/Aileron-BlackItalic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:35ed03e1600c62124e5a967b2445565289dbff87363f091f72061ecbbb4a697f
|
||||
size 39996
|
3
public/fonts/Aileron-Bold.ttf
Normal file
3
public/fonts/Aileron-Bold.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8122bfa8c6570dfefbd6b38d1ae6a24f0c81c75a1a8e57b8e6a2f46c625ef979
|
||||
size 38304
|
3
public/fonts/Aileron-BoldItalic.ttf
Normal file
3
public/fonts/Aileron-BoldItalic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9107717e3528638dd53a4f56aa0bdd5411ef277c071a4f42f8a3f9c86568538a
|
||||
size 40620
|
3
public/fonts/Aileron-Heavy.ttf
Normal file
3
public/fonts/Aileron-Heavy.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:71177b607e4053a8c472a68d94a6efba29919f54838d4724ba86cd362ccc6d51
|
||||
size 38416
|
3
public/fonts/Aileron-HeavyItalic.ttf
Normal file
3
public/fonts/Aileron-HeavyItalic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2f43776004e78088aa1adf1c7935ccf70743f6e9032301f21f334be7a7dd72bf
|
||||
size 40440
|
3
public/fonts/Aileron-Italic.ttf
Normal file
3
public/fonts/Aileron-Italic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d8eb6984408b33575359478bf531e78fd3535b08797784aef54b1847e5511705
|
||||
size 41032
|
3
public/fonts/Aileron-Light.ttf
Normal file
3
public/fonts/Aileron-Light.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:85c9c438bc11f0d54065e60f7c884f420f7487a4e921c04334ac944b1613b405
|
||||
size 38876
|
3
public/fonts/Aileron-LightItalic.ttf
Normal file
3
public/fonts/Aileron-LightItalic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:05377820e3ee66a23bb0d40e0caefba8f1579bfb0dbcd2b0cc4e84d0c7de084a
|
||||
size 41220
|
3
public/fonts/Aileron-Regular.ttf
Normal file
3
public/fonts/Aileron-Regular.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:47d06f5a02e49f34766f0f8e746f3c6ec641b9930278772e84c26e6df25bf14d
|
||||
size 38168
|
3
public/fonts/Aileron-SemiBold.ttf
Normal file
3
public/fonts/Aileron-SemiBold.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cb795f523fcd07ffda06179b4649605d5552916e018dec9dce5e2a59ce64ae28
|
||||
size 38612
|
3
public/fonts/Aileron-SemiBoldItalic.ttf
Normal file
3
public/fonts/Aileron-SemiBoldItalic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b73a0b7dbb381344b1f9b32406be8b4d065073f1fbbc586dcc686c4df292cb28
|
||||
size 41184
|
3
public/fonts/Aileron-Thin.ttf
Normal file
3
public/fonts/Aileron-Thin.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5d04db6398893af7c86bb0aff112589c4ff529b56fac128346ff72819a3132b9
|
||||
size 39056
|
3
public/fonts/Aileron-ThinItalic.ttf
Normal file
3
public/fonts/Aileron-ThinItalic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:80d0f93f3f4f029ee0f45fe0ad68c8caf3fbaa739dc61912013d4bf718e34fc6
|
||||
size 41308
|
3
public/fonts/Aileron-UltraLight.ttf
Normal file
3
public/fonts/Aileron-UltraLight.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b68177274ef371eadec5cff5672c9230e94faea0afb1557af79a5eb95c4f53f7
|
||||
size 39136
|
3
public/fonts/Aileron-UltraLightItalic.ttf
Normal file
3
public/fonts/Aileron-UltraLightItalic.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0ddcffab417bd4cd18f31474363162cf5e0fb8165ede8ca50d9afde666cc1d84
|
||||
size 41472
|
3
public/fonts/Blobmoji.ttf
Normal file
3
public/fonts/Blobmoji.ttf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:702d0521c6f58476abc9f16f09b6a2943850b1b54cf098f573f6ee4a5ff5db6a
|
||||
size 8305868
|
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Allow: /
|
BIN
public/sea.jpg
BIN
public/sea.jpg
Binary file not shown.
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 131 B |
3
public/uploads/dzeio.png
Normal file
3
public/uploads/dzeio.png
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1fdb6128c4505163e416216b96f2139214fa1d589f39e8ad01da842e42e4d319
|
||||
size 1556838
|
Binary file not shown.
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 130 B |
110
styl/include/_aileron.styl
Normal file
110
styl/include/_aileron.styl
Normal file
@ -0,0 +1,110 @@
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Bold'), local('Aileron-Bold'), url('/fonts/Aileron-Bold.ttf') format('truetype')
|
||||
font-weight: bold
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Italic'), local('Aileron-Italic'), url('/fonts/Aileron-Italic.ttf') format('truetype')
|
||||
font-weight: normal
|
||||
font-style: italic
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Black Italic'), local('Aileron-BlackItalic'), url('/fonts/Aileron-BlackItalic.ttf') format('truetype')
|
||||
font-weight: 900
|
||||
font-style: italic
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Bold Italic'), local('Aileron-BoldItalic'), url('/fonts/Aileron-BoldItalic.ttf') format('truetype')
|
||||
font-weight: bold
|
||||
font-style: italic
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Light'), local('Aileron-Light'), url('/fonts/Aileron-Light.ttf') format('truetype')
|
||||
font-weight: 300
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Black'), local('Aileron-Black'), url('/fonts/Aileron-Black.ttf') format('truetype')
|
||||
font-weight: 900
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Heavy Italic'), local('Aileron-HeavyItalic'), url('/fonts/Aileron-HeavyItalic.ttf') format('truetype')
|
||||
font-weight: 900
|
||||
font-style: italic
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron UltraLight Italic'), local('Aileron-UltraLightItalic'), url('/fonts/Aileron-UltraLightItalic.ttf') format('truetype')
|
||||
font-weight: 200
|
||||
font-style: italic
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Heavy'), local('Aileron-Heavy'), url('/fonts/Aileron-Heavy.ttf') format('truetype')
|
||||
font-weight: 900
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Thin'), local('Aileron-Thin'), url('/fonts/Aileron-Thin.ttf') format('truetype')
|
||||
font-weight: 100
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron UltraLight'), local('Aileron-UltraLight'), url('/fonts/Aileron-UltraLight.ttf') format('truetype')
|
||||
font-weight: 200
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron SemiBold'), local('Aileron-SemiBold'), url('/fonts/Aileron-SemiBold.ttf') format('truetype')
|
||||
font-weight: 600
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Regular'), local('Aileron-Regular'), url('/fonts/Aileron-Regular.ttf') format('truetype')
|
||||
font-weight: normal
|
||||
font-style: normal
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Thin Italic'), local('Aileron-ThinItalic'), url('/fonts/Aileron-ThinItalic.ttf') format('truetype')
|
||||
font-weight: 100
|
||||
font-style: italic
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron Light Italic'), local('Aileron-LightItalic'), url('/fonts/Aileron-LightItalic.ttf') format('truetype')
|
||||
font-weight: 300
|
||||
font-style: italic
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Aileron'
|
||||
src: local('Aileron SemiBold Italic'), local('Aileron-SemiBoldItalic'), url('/fonts/Aileron-SemiBoldItalic.ttf') format('truetype')
|
||||
font-weight: 600
|
||||
font-style: italic
|
8
styl/include/_blobmoji.styl
Normal file
8
styl/include/_blobmoji.styl
Normal file
@ -0,0 +1,8 @@
|
||||
@font-face
|
||||
font-family: "Blobmoji"
|
||||
// TODO: find a way to use it internally
|
||||
src: local('Blobmoji')
|
||||
src: url('/fonts/Blobmoji.ttf')
|
||||
|
||||
.emoji
|
||||
font-family: 'Blobmoji'
|
@ -12,7 +12,7 @@ button, a.button
|
||||
cursor: pointer
|
||||
color: #FFF
|
||||
background-color: $color
|
||||
border-radius: 5px
|
||||
border-radius: 10px
|
||||
border: none
|
||||
padding: 7px 14px
|
||||
transition-property: box-shadow, background-color
|
||||
@ -26,6 +26,12 @@ button, a.button
|
||||
line-height: 22px
|
||||
text-decoration: none
|
||||
box-sizing: border-box
|
||||
justify-content center
|
||||
|
||||
&.large
|
||||
padding 20px 25px
|
||||
text-transform uppercase
|
||||
font-size 20px
|
||||
|
||||
&:hover
|
||||
background-color: $hover
|
||||
|
@ -11,8 +11,7 @@ $color = #4285F4
|
||||
|
||||
&:not(:last-of-type)
|
||||
margin-right 10px
|
||||
|
||||
input
|
||||
input, select
|
||||
display block
|
||||
border-radius 10px
|
||||
background-color #EEE
|
||||
@ -45,6 +44,13 @@ $color = #4285F4
|
||||
background-color #FFF
|
||||
box-shadow inset 0 0 0 2px $color, 0 0 0 3px rgba(204,204,204, .75)
|
||||
|
||||
|
||||
select
|
||||
-webkit-appearance none
|
||||
-moz-appearance none
|
||||
appearance none
|
||||
display inline-flex
|
||||
|
||||
label
|
||||
text-transform uppercase
|
||||
margin auto
|
||||
@ -60,13 +66,12 @@ $color = #4285F4
|
||||
font-weight 300
|
||||
font-style italic
|
||||
|
||||
|
||||
// Icons
|
||||
|
||||
i
|
||||
width 25px
|
||||
width 24px
|
||||
height 24px
|
||||
position absolute
|
||||
left 28px
|
||||
left 20px
|
||||
top 18px
|
||||
// pointer-events none
|
||||
color #666
|
||||
@ -74,17 +79,25 @@ $color = #4285F4
|
||||
|
||||
&.icon-right i
|
||||
left initial
|
||||
right 28px
|
||||
right 20px
|
||||
|
||||
&.icon-left input
|
||||
&.icon-left input,
|
||||
&.icon-left select
|
||||
padding-left 50px
|
||||
|
||||
&.icon-right input
|
||||
&.icon-right input,
|
||||
&.icon-right select
|
||||
padding-right 50px
|
||||
|
||||
|
||||
&.icon-right input, &.icon-left input
|
||||
&.icon-right input, &.icon-left input,
|
||||
&.icon-right select, &.icon-left select
|
||||
max-width calc(100% - 76px)
|
||||
|
||||
input:focus:not([readonly]) + i
|
||||
&.icon-right select, &.icon-left select
|
||||
max-width 100%
|
||||
|
||||
|
||||
input:focus:not([readonly]) + i,
|
||||
select:focus:not([readonly]) + i
|
||||
color $color
|
||||
|
@ -1,6 +1,16 @@
|
||||
@import "include/_aileron"
|
||||
@import "include/_blobmoji"
|
||||
@import "include/_button"
|
||||
@import "include/_input"
|
||||
|
||||
html, body {
|
||||
margin 0
|
||||
}
|
||||
|
||||
div, span, a, p, h1, h2, h3, h4, h5, h6, i {
|
||||
font-family Aileron, BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif
|
||||
}
|
||||
|
||||
::selection
|
||||
background #4285F4
|
||||
color white
|
||||
|
@ -2911,6 +2911,11 @@ fs.realpath@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
fs@^0.0.1-security:
|
||||
version "0.0.1-security"
|
||||
resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4"
|
||||
integrity sha1-invTcYa23d84E/I4WLV+yq9eQdQ=
|
||||
|
||||
fsevents@^1.2.7:
|
||||
version "1.2.9"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f"
|
||||
|
Loading…
x
Reference in New Issue
Block a user