[add] initial commit

This commit is contained in:
2022-09-30 21:05:45 -05:00
commit 366ae365ab
27 changed files with 10348 additions and 0 deletions

11
.eslintrc.js Normal file
View File

@@ -0,0 +1,11 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:vue/recommended'
],
rules: {
'vue/multi-word-component-names': 'off'
}
}
// eslint --ext .js,.vue src

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
*.log
.cache
.DS_Store
src/.temp
node_modules
dist
.env
.env.*

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
<h1 align="center">pdev.dev</h1>
<h4 align="center">
Simple personal page.
</h4>
<p align="center">
<strong>
<a href="https://pdev.dev">pdev.dev</a>
• <a href="#build">Build</a>
</strong>
</p>
## Build
Made with [`Vue.js`](https://vuejs.org), [`Gridsome`](https://gridsome.org) and [`Bulma`](https://bulma.io/).
```bash
# run locally
yarn install
yarn develop
```
```bash
# build
yarn install
yarn build
```

12
gridsome.config.js Normal file
View File

@@ -0,0 +1,12 @@
// This is where project configuration and plugin options are located.
// Learn more: https://gridsome.org/docs/config
// Changes here require a server restart.
// To restart press CTRL + C in terminal and run `gridsome develop`
module.exports = {
siteName: 'pdev',
siteUrl: 'https://pdev.dev',
icon: './static/favicon.png',
plugins: []
}

16
gridsome.server.js Normal file
View File

@@ -0,0 +1,16 @@
// Server API makes it possible to hook into various parts of Gridsome
// on server-side and add custom data to the GraphQL data layer.
// Learn more: https://gridsome.org/docs/server-api/
// Changes here require a server restart.
// To restart press CTRL + C in terminal and run `gridsome develop`
module.exports = function (api) {
api.loadSource(({ addCollection }) => {
// Use the Data Store API here: https://gridsome.org/docs/data-store-api/
})
api.createPages(({ createPage }) => {
// Use the Pages API here: https://gridsome.org/docs/pages-api/
})
}

24
package.json Normal file
View File

@@ -0,0 +1,24 @@
{
"name": "static.pdev.dev",
"private": true,
"scripts": {
"build": "gridsome build",
"develop": "gridsome develop",
"explore": "gridsome explore"
},
"dependencies": {
"bulma": "^0.9.4",
"gridsome": "^0.7.0"
},
"devDependencies": {
"@creativebulma/bulma-tooltip": "^1.2.0",
"@fortawesome/fontawesome-svg-core": "^6.2.0",
"@fortawesome/free-brands-svg-icons": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/vue-fontawesome": "^2.0.8",
"eslint": "^8.24.0",
"eslint-plugin-vue": "^9.5.1",
"sass": "^1.55.0",
"sass-loader": "^10.1.1"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,73 @@
@charset "utf-8";
/* latin-ext */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 300;
font-display: swap;
src: local('Overpass Mono Light'), local('OverpassMono-Light'), url('~@/assets/fonts/OverpassMono-Light_ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 300;
font-display: swap;
src: local('Overpass Mono Light'), local('OverpassMono-Light'), url('~@/assets/fonts/OverpassMono-Light.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Overpass Mono Regular'), local('OverpassMono-Regular'), url('~@/assets/fonts/OverpassMono-Regular_ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Overpass Mono Regular'), local('OverpassMono-Regular'), url('~@/assets/fonts/OverpassMono-Regular.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 600;
font-display: swap;
src: local('Overpass Mono SemiBold'), local('OverpassMono-SemiBold'), url('~@/assets/fonts/OverpassMono-SemiBold_ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 600;
font-display: swap;
src: local('Overpass Mono SemiBold'), local('OverpassMono-SemiBold'), url('~@/assets/fonts/OverpassMono-SemiBold.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 700;
font-display: swap;
src: local('Overpass Mono Bold'), local('OverpassMono-Bold'), url('~@/assets/fonts/OverpassMono-Bold_ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Overpass Mono';
font-style: normal;
font-weight: 700;
font-display: swap;
src: local('Overpass Mono Bold'), local('OverpassMono-Bold'), url('~@/assets/fonts/OverpassMono-Bold.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

View File

@@ -0,0 +1,49 @@
@charset "utf-8";
// theme
$family-monospace: 'Overpass Mono', monospace;
$dark-theme: (
background-color: #2E2E2E,
background: #3d3d3d,
text: #ccc,
text-darker: #bbb,
highlight: #f17603,
highlight-hover: #ffab5c
);
// bulma global variables
$grey-light: map-get($dark-theme, "text");
$grey-dark: map-get($dark-theme, "text");
$grey-darker: map-get($dark-theme, "text-darker");
$warning: map-get($dark-theme, "highlight");
$primary: map-get($dark-theme, "highlight");
$background: map-get($dark-theme, 'background');
$family-primary: $family-monospace;
$link-hover: map-get($dark-theme, "highlight");
$link: map-get($dark-theme, "text");
// bulma component variables
$body-background-color: map-get($dark-theme, 'background-color');
// bulma tooltip extension
$tooltip-background-color: map-get($dark-theme, 'background');
$tooltip-color: map-get($dark-theme, "text");
// general css
.link {
margin-left: 1rem;
}
.hash-list {
margin-top: 1rem;
margin-bottom: 1rem;
div {
margin-left: 2em;
}
}
#app {
.highlight {
color: map-get($dark-theme, "highlight");
}
}

View File

@@ -0,0 +1,23 @@
@charset "utf-8";
// import fonts
@import '~@/assets/sass/fonts.scss';
// import global
@import '~@/assets/sass/global.scss';
// import bulma
@import 'bulma/sass/utilities/_all.sass';
@import 'bulma/sass/base/_all.sass';
@import 'bulma/sass/components/navbar.sass';
@import 'bulma/sass/elements/container.sass';
@import 'bulma/sass/elements/title.sass';
@import 'bulma/sass/elements/icon.sass';
@import 'bulma/sass/elements/content.sass';
@import 'bulma/sass/elements/tag.sass';
@import 'bulma/sass/grid/columns.sass';
@import 'bulma/sass/form/all';
@import 'bulma/sass/form/tools.sass';
@import 'bulma/sass/layout/_all.sass';
@import '@creativebulma/bulma-tooltip/src/sass/index.sass'; //https://github.com/CreativeBulma/bulma-tooltip https://wikiki.github.io/elements/tooltip/

57
src/components/Gelvin.vue Normal file
View File

@@ -0,0 +1,57 @@
<template>
<a
class="link icon-text"
href="#"
@click="toggle_locale()"
>
<span class="icon highlight">
<font-awesome-icon icon="fa-solid fa-temperature-three-quarters" />
</span><span style="font-size: 1em">{{ temperature }}</span>
<slot />
</a>
</template>
<script>
export default {
name: 'Gelvin',
props: {
addr: {
type: String,
required: true
},
id: {
type: Number,
required: true
},
},
data() {
return {
fetcher: null,
value: NaN,
celsius: false
};
},
computed: {
temperature() {
return this.celsius ?
this.value.toFixed(2).toLocaleString() + "°C" :
(this.value * 9/5 + 32).toFixed(2).toLocaleString() + "°F" ;
}
},
mounted() {
this.fetch_temp();
this.fetcher = setInterval(this.fetch_temp, 30000)
},
methods: {
fetch_temp() {
fetch(this.addr + "/gelvin/measurements/" + this.id)
.then(response => response.json())
.then(json => this.value = json.value);
},
toggle_locale() {
this.celsius = ! this.celsius;
}
}
}
</script>

View File

@@ -0,0 +1,25 @@
<template>
<div class="hash-list">
<div
v-for="(item, index) in items"
:key="index"
class="content is-small"
>
<span class="highlight">#</span> {{ item }}
</div>
</div>
</template>
<script>
export default {
name: 'HashList',
props: {
items: {
type: Array,
required: true
}
},
}
</script>

View File

@@ -0,0 +1,49 @@
<template>
<a
class="link icon-text"
href="#"
@click="attachUrl()"
>
<span
v-if="icon"
class="icon highlight"
><font-awesome-icon :icon="icon" /></span>{{ text }}
<slot />
</a>
</template>
<script>
export default {
name: 'XorLink',
props: {
addr: {
type: Array,
required: true
},
otp: {
type: Array,
required: true
},
text: {
type: String,
required: true
},
icon: {
type: String,
required: false,
default: null
}
},
methods: {
xorArray(a, b) {
return a.length < b.length ? null : a.map((c, i) => {
return c ^ b[i];
})
},
attachUrl() {
window.location.href = String.fromCharCode(...this.xorArray(this.addr, this.otp));
}
}
}
</script>

76
src/layouts/Default.vue Normal file
View File

@@ -0,0 +1,76 @@
<template>
<div class="layout">
<header class="header">
<strong>
<g-link
to="/"
style="font-size: 1.5em"
><span style="color: #ccc">{{ $static.metadata.siteName }}</span><span
class="highlight"
>#</span></g-link>
</strong>
<nav class="nav">
<Gelvin
:id="2"
addr="https://api.pdev.dev"
class="has-tooltip-bottom"
data-tooltip="office temperature"
/>
<XorLink
text="git"
icon="fa-solid fa-code-branch"
:addr="[0x03, 0x18, 0x40, 0x56, 0x4a, 0x09, 0x1f, 0x63, 0x2d, 0x03, 0x18, 0x47, 0x17, 0x55, 0x4c, 0x42, 0x03, 0x4f, 0x58, 0x12]"
:otp="[0x6b, 0x6c, 0x34, 0x26, 0x39, 0x33, 0x30, 0x4c, 0x4a, 0x6a, 0x6c, 0x69, 0x67, 0x31, 0x29, 0x34, 0x2d, 0x2b, 0x3d, 0x64]"
/>
<XorLink
text="mail"
icon="fa-solid fa-envelope"
:addr="[0x59, 0x12, 0x02, 0x4a, 0x40, 0x07, 0x76, 0x1b, 0x00, 0x19, 0x45, 0x52, 0x06, 0x0e, 0x1b, 0x03, 0x09, 0x5e, 0x45, 0x08, 0x51, 0x53]"
:otp="[0x34, 0x73, 0x6b, 0x26, 0x34, 0x68, 0x4c, 0x6b, 0x61, 0x6a, 0x26, 0x33, 0x6a, 0x4e, 0x6b, 0x67, 0x6c, 0x28, 0x6b, 0x6c, 0x34, 0x25]"
/>
<XorLink
text="pgp"
icon="fa-solid fa-key"
:addr="[0x45, 0x07, 0x02, 0x32, 0x56, 0x1b, 0x48, 0x1b, 0x3e, 0x5b, 0x59, 0x5c, 0x49, 0x44, 0x43, 0x0b, 0x1b]"
:otp="[0x6a, 0x61, 0x6b, 0x5e, 0x33, 0x68, 0x67, 0x6b, 0x4b, 0x39, 0x35, 0x35, 0x2a, 0x6a, 0x33, 0x6c, 0x6b]"
/>
</nav>
</header>
<slot />
</div>
</template>
<static-query>
query {
metadata {
siteName
}
}
</static-query>
<style>
body {
margin: 0;
padding: 0;
line-height: 1.5;
}
.layout {
max-width: 760px;
margin: 0 auto;
padding-left: 20px;
padding-right: 20px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
height: 80px;
}
.nav {
text-align: right;
}
</style>

36
src/main.js Normal file
View File

@@ -0,0 +1,36 @@
// This is the main.js file. Import global CSS and scripts here.
// The Client API can be used here. Learn more: gridsome.org/docs/client-api
// icons import
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
import {config, library} from '@fortawesome/fontawesome-svg-core';
import {
faGitAlt
} from '@fortawesome/free-brands-svg-icons';
import {
faEnvelope,
faKey,
faCodeBranch,
faTemperatureThreeQuarters
} from '@fortawesome/free-solid-svg-icons';
import DefaultLayout from '~/layouts/Default.vue'
import XorLink from '~/components/XorLink.vue'
import Gelvin from '~/components/Gelvin.vue'
import HashList from '~/components/HashList.vue'
// sass
import '~/assets/sass/includes.scss'
// icons config
config.autoAddCss = true;
library.add(faGitAlt, faEnvelope, faKey, faCodeBranch, faTemperatureThreeQuarters)
export default function (Vue) {
// Set default layout as a global component
Vue.component('FontAwesomeIcon', FontAwesomeIcon);
Vue.component('Layout', DefaultLayout);
Vue.component('XorLink', XorLink);
Vue.component('Gelvin', Gelvin);
Vue.component('HashList', HashList);
}

40
src/pages/Index.vue Normal file
View File

@@ -0,0 +1,40 @@
<template>
<Layout>
<div class="container content">
<div class="field is-grouped is-grouped-multiline">
<div class="control">
<h2><span class="highlight">#</span>EHLO</h2>
</div>
<div class="control">
<div class="tags has-addons">
<span class="tag is-medium is-white">I am </span><span class="tag is-medium is-warning">Pascal</span>
</div>
</div>
</div>
<p>
I'm a Software Engineer. I mostly work on embedded network devices, though I like to dabble in web development and server management. When I'm not coding, I'm soldering things to code on.
<HashList
:items="['Linux, OpenWrt, Yoctu, Arduino, RaspberryPi, Xilinx FPGA',
'C/C++, Java/Scala, Python, Shell, Lua, HTML/CSS/JS, SQL, VHDL',
'Autotools, Bitmake, CMake, Doxygen, Docker, Jenkins, Apache, Nginx']"
/>
</p>
</div>
</Layout>
</template>
<script>
export default {
metaInfo: {
title: '/root'
}
}
</script>
<style>
.home-links a {
margin-right: 1rem;
}
</style>

BIN
static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

51
static/files/public.pgp Normal file
View File

@@ -0,0 +1,51 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGA2CcUBEADmSx5K7OsgaidnFbo+rZv5rNLJMCMRsNqcGmD2lbI7PAPrqvai
hAQSEhL/BGW3OIM6/w0juhMV/9EgRvxvo5wVEJVPCNk6JhYuUY+jysPMb3ciwR5U
1XneSWh+U2QGEGW7p9OqizxnRXMSE2QeXISiWGFBP91zin/b2vs0eBDRUzerPh0I
a7tDWR5IK6FdNAYTEH2rqJOi4Kk/YHDY4znzmWo7tG9FKQlqzDm/pL5f7Hzt1ibc
FuQVdVJ/4usUt2PbT9boXZliIQ4AmzIQBlHXh0Qbg7a+woMLVuLO8nU9q8p7+/pd
jHoFQURL5HWp772qG7gevucyJQjYHh66Zp1+OBdb4hPbVQWvElBFFx8cl6PMC/DI
kxWQfsTrCSwK8VmXFsHtKATeCl8oEKPv5SwwSugjFoBvq2QIn/l6WYOfjZv1X7ob
ZbKXuYn302bJeZQnwn7h29sIziI4Lylcp9HoHkVpgK/4V+sFbqh+Po0Ke1gjzbCx
jm71cR+jS2BgUV5qCEFxQXXfnzuOJPBAUwgtw0jPO6F5BZXdcHaQlqsDXyjJFu+7
76655Cr+Z+r2Xd2zOupdT33xYSYE7er28C87egiJDGpMR1GT2UgmIsJh7e3m9/TG
A7/d8liFivHgXTqajIyjz+zwApPybYW+yg3SnD+GTwo7Ckjtpj+3/dFQlQARAQAB
tBhQYXNjYWwgPHBhc2NhbEBwZGV2LmRldj6JAlQEEwEIAD4WIQRFaiOYU0BqgdsL
4VYEyGTKGhKVxgUCYy4fPQIbAwUJBsYgywULCQgHAgYVCgkICwIEFgIDAQIeAQIX
gAAKCRAEyGTKGhKVxvtED/4viGcBxh0POoClC2mH5lkexbcOM8zwiG3N+L+F3bTn
SOcd2RKdGCk1+bmioYXI/uXi+eC+N9FEVShv0DVMtsNZZbGh+EYf2S05XE/+ZoIX
KzcvzKrF+UmUUSEphR+PiSuWysDkqjlHp8vfNs/v5YEVvYkZc5v+TaklmhBoDa2Q
bM+2plv8yiv5VQoi/GmZQtktDv9Cl3D9VXkXTTVSa57JiKifigZlLjktuo4Fi+wM
jwwhkWrJLtuYmcy9Ije6a+H1ddUhfh9TlkHxq9si7CEoD91JtzTN3vdAAdX/F7Jf
YF5KUQKEZn9yziuJALPoZr+B9TWUcCmMnQzFsrSzbGho9pNnd/N31H5z++VmCfGo
zRXpDzl+LNY4HNpG+07T/mfXhdyUCOEgMTi67waeqjrUUmJbJ6ODg/vqTZ1u3n5f
OQyoXfE/3byH9cAj5oJ2cd9z/scQ9B+9HT+Dl5gfm2f90iV86d2iapfF13ZxHOVU
AqKFdUm3MOVWu3GWw0Faqme4roQqJhlSzpjytf7rBEJT2Zw4qeHewBI957c8JCj9
BA5Fo8YczGW4XbLl6obFUeCoT/sq0Ku1Is9lFcz1gtSDK/hf9aMn1N/FpQaBqWfR
QuhUQn65fD0bfETF6WxHXDtqHG+QqvzcS47trqR6EPy9Y4R4OXvv6Y9ywcxCMWAu
grkCDQRgNgnFARAAvOioJoAVRPO9/PT0eRD37X0bIXrUN0vZgcd6bAv4C/b2VvFa
jb7hMn3RB0BQtOnM7rj+3PRnN3oCfftpHD8Q/hkz2HewNs/WB5w2IfK+fCM54rVO
DNZ+uIAxCvxj4acMTG4TFla7Bvl1a45Aw7PD3KA4UDqnR9w/kai2SGEdroLCJhce
gqsvud6CLqSIWt9iR4dZIYt+ANnWf2/HHyUcIA9aLCieqDxGnxM2T7vqwV7bxbdc
cHkS//EA4qSqkmqntFtXvVM41dcpMqNr1hvcc8SlqnkmkZCL0zGkM77H7LWBf5km
tSlg+3T96tdY9bviSQMZ3i2uGhOvVPz4wGa1pxs31R/EdHGoNtoBe/GQGg4bOi0T
u8YGvHsp4aOJDw0ygbO2gY0Koi0g2v5Z53rUM7+o5qn+Z1wB7+M4Wrlp+/uSVS5U
hkKH2hiW/0ibYRMQ/k+AC/uoNnZVKrtQlCMhPRGgV/2Pg91S+Dd+CaBEsAxWC9YY
Eln0q0GjORP6suD4esshkrk2D82ffE5hX4yMEGuWfLA4O7Zcxm8zZqUDJbtO5bTz
/izGOFmCLKZPGvczFSVFjq0E9GVliDD/FWHzCQeQ0rMdlY0I/dnewj2SaVkwjgq0
pkp9wgQtVfgKLAFSQU6Ya1/sc/NBmogh7QHlIedtyRyyEf/x7EDHLJx/LD0AEQEA
AYkCPAQYAQgAJgIbDBYhBEVqI5hTQGqB2wvhVgTIZMoaEpXGBQJjLhzYBQkGxiDL
AAoJEATIZMoaEpXGdVsP/i9GQbyPgSBMUI2gOu4r4R8LmsbnLMYaTtsN9DSdw2U6
mP6lEsliId0E+5KtY3vF5qCBNTU99yTHGTpT9wGSnLaCh0igJv7pf7jp27HHdsYC
VHkJQDA92aPvw3TiQYCZvn8xLjkVRjPNNT0h5Pksbb41eeMu3sMoHhbirgIKK1y6
IPG3k5lIhb/S3y75q2w+FPwflqyMwFcA33TD/EVonUOpfeBSVb571hQkz76nFag5
J+RunmJXEfkrQo1FjXoFnFpBA5ayU9TmldlZs2thXlJLOSOCCdeEBmQJn7m8cYd4
icOCF8r4Knx1jLAsalD5Obr/Eq6FGuNpjD7ofW51vyXrrnu+r/8hEmlAntSz4DJ6
CrSnvxh1eBVKCJdURWfnnlE+O81ia03N0A7YB9ni/D8TB4yr0+vFma0h+U/OyEw8
xmd1nkhEHi3K3D5Bn3VD/mxr1DmQqjRbl9XzS1x+fTMAsee9GFfwI+E27jvKsPPS
yKRmBq3iV6sGUbEXn54QoD+jepId6Xgfait+54Gs7/oaQcVSFk/HMSiCeBUSRNpb
Li1kLpQlSYQjfXnT/LUSxMlhUFiVHl+ghzFPmJhw1wzBePDdySBG6ZB/rWl1FuOK
6BcCetBt5cGYJIxf3ehFJ+wRJBu6xS04Xibc8N4Tyu2wVpuXtqoKVY2n2bQGQN4P
=OHbs
-----END PGP PUBLIC KEY BLOCK-----

2
static/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow: /

9770
yarn.lock Normal file

File diff suppressed because it is too large Load Diff