Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
4c3dccfc0b | |||
1075e3a005 | |||
dad8fff12d | |||
a6a175ede1 | |||
a01607fd97 | |||
345084a764 | |||
27582319fa | |||
44bb99259c | |||
9b0e83d971 | |||
db882ebb6f | |||
c501bf4e16 | |||
c0eb873feb |
41
appveyor.yml
Normal file
41
appveyor.yml
Normal file
@ -0,0 +1,41 @@
|
||||
# appveyor file
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: 10.1.0
|
||||
|
||||
cache:
|
||||
- node_modules
|
||||
|
||||
build: off
|
||||
|
||||
install:
|
||||
# Update Node.js
|
||||
# 標準で入っている Node.js を更新します (2014/11/13 時点では、v0.10.32 が標準)
|
||||
- ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)
|
||||
- node --version
|
||||
|
||||
# Update NPM
|
||||
- npm install -g npm
|
||||
- npm --version
|
||||
|
||||
# Update node-gyp
|
||||
# 必須! node-gyp のバージョンを上げないと、ネイティブモジュールのコンパイルに失敗します
|
||||
- npm install -g node-gyp
|
||||
|
||||
- npm install
|
||||
|
||||
init:
|
||||
# git clone の際の改行を変換しないようにします
|
||||
- git config --global core.autocrlf false
|
||||
|
||||
before_test:
|
||||
# 設定ファイルを配置
|
||||
- cp ./.travis/default.yml ./.config
|
||||
- cp ./.travis/test.yml ./.config
|
||||
|
||||
- npm run build
|
||||
|
||||
test_script:
|
||||
- npm test
|
@ -1,4 +1,7 @@
|
||||
---
|
||||
meta:
|
||||
lang: "English"
|
||||
divider: " "
|
||||
common:
|
||||
misskey: "Share everything with others using Misskey."
|
||||
time:
|
||||
|
@ -1,3 +1,7 @@
|
||||
meta:
|
||||
lang: "日本語"
|
||||
divider: ""
|
||||
|
||||
common:
|
||||
misskey: "Misskeyで皆と共有しよう。"
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "2.9.0",
|
||||
"clientVersion": "1.0.5394",
|
||||
"version": "2.10.0",
|
||||
"clientVersion": "1.0.5406",
|
||||
"codename": "nighthike",
|
||||
"main": "./built/index.js",
|
||||
"private": true,
|
||||
|
19
src/client/app/common/views/components/acct.vue
Normal file
19
src/client/app/common/views/components/acct.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<span class="mk-acct">
|
||||
<span class="name">@{{ user.username }}</span>
|
||||
<span class="host" v-if="user.host">@{{ user.host }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
export default Vue.extend({
|
||||
props: ['user']
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.mk-acct
|
||||
> .host
|
||||
opacity 0.5
|
||||
</style>
|
@ -23,7 +23,7 @@ export default Vue.extend({
|
||||
computed: {
|
||||
style(): any {
|
||||
return {
|
||||
backgroundColor: this.user.avatarColor ? `rgb(${ this.user.avatarColor.join(',') })` : null,
|
||||
backgroundColor: this.user.avatarColor && this.user.avatarColor.length == 3 ? `rgb(${ this.user.avatarColor.join(',') })` : null,
|
||||
backgroundImage: `url(${ this.user.avatarUrl }?thumbnail)`,
|
||||
borderRadius: (this as any).clientSettings.circleIcons ? '100%' : null
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ import Vue from 'vue';
|
||||
import signin from './signin.vue';
|
||||
import signup from './signup.vue';
|
||||
import forkit from './forkit.vue';
|
||||
import acct from './acct.vue';
|
||||
import avatar from './avatar.vue';
|
||||
import nav from './nav.vue';
|
||||
import noteHtml from './note-html';
|
||||
@ -29,6 +30,7 @@ import welcomeTimeline from './welcome-timeline.vue';
|
||||
Vue.component('mk-signin', signin);
|
||||
Vue.component('mk-signup', signup);
|
||||
Vue.component('mk-forkit', forkit);
|
||||
Vue.component('mk-acct', acct);
|
||||
Vue.component('mk-avatar', avatar);
|
||||
Vue.component('mk-nav', nav);
|
||||
Vue.component('mk-note-html', noteHtml);
|
||||
|
@ -50,7 +50,7 @@ export default Vue.extend({
|
||||
return `${this.file.name}\n${this.file.type} ${Vue.filter('bytes')(this.file.datasize)}`;
|
||||
},
|
||||
background(): string {
|
||||
return this.file.properties.avgColor
|
||||
return this.file.properties.avgColor && this.file.properties.avgColor.length == 3
|
||||
? `rgb(${this.file.properties.avgColor.join(',')})`
|
||||
: 'transparent';
|
||||
}
|
||||
@ -129,7 +129,7 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
onThumbnailLoaded() {
|
||||
if (this.file.properties.avgColor) {
|
||||
if (this.file.properties.avgColor && this.file.properties.avgColor.length == 3) {
|
||||
anime({
|
||||
targets: this.$refs.thumbnail,
|
||||
backgroundColor: `rgba(${this.file.properties.avgColor.join(',')}, 0)`,
|
||||
|
@ -26,7 +26,7 @@ export default Vue.extend({
|
||||
computed: {
|
||||
style(): any {
|
||||
return {
|
||||
'background-color': this.image.properties.avgColor ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url}?thumbnail&size=512)`
|
||||
};
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
|
||||
<span class="username">@{{ note.user | acct }}</span>
|
||||
<span class="username"><mk-acct :user="note.user"/></span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<router-link class="time" :to="note | notePage">
|
||||
|
@ -28,7 +28,7 @@
|
||||
<mk-avatar class="avatar" :user="p.user"/>
|
||||
<header>
|
||||
<router-link class="name" :to="p.user | userPage" v-user-preview="p.user.id">{{ p.user | userName }}</router-link>
|
||||
<span class="username">@{{ p.user | acct }}</span>
|
||||
<span class="username"><mk-acct :user="p.user"/></span>
|
||||
<router-link class="time" :to="p | notePage">
|
||||
<mk-time :time="p.createdAt"/>
|
||||
</router-link>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<div class="main">
|
||||
<header>
|
||||
<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
|
||||
<span class="username">@{{ note.user | acct }}</span>
|
||||
<span class="username"><mk-acct :user="note.user"/></span>
|
||||
<router-link class="time" :to="note | notePage">
|
||||
<mk-time :time="note.createdAt"/>
|
||||
</router-link>
|
||||
@ -59,17 +59,20 @@ root(isDark)
|
||||
> .name
|
||||
margin 0 .5em 0 0
|
||||
padding 0
|
||||
overflow hidden
|
||||
color isDark ? #fff : #607073
|
||||
font-size 1em
|
||||
font-weight bold
|
||||
text-decoration none
|
||||
white-space normal
|
||||
text-overflow ellipsis
|
||||
|
||||
&:hover
|
||||
text-decoration underline
|
||||
|
||||
> .username
|
||||
margin 0 .5em 0 0
|
||||
overflow hidden
|
||||
text-overflow ellipsis
|
||||
color isDark ? #606984 : #d1d8da
|
||||
|
||||
> .time
|
||||
|
@ -4,7 +4,7 @@
|
||||
<div class="main">
|
||||
<header>
|
||||
<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
|
||||
<span class="username">@{{ note.user | acct }}</span>
|
||||
<span class="username"><mk-acct :user="note.user"/></span>
|
||||
<div class="info">
|
||||
<span class="mobile" v-if="note.viaMobile">%fa:mobile-alt%</span>
|
||||
<router-link class="created-at" :to="note | notePage">
|
||||
|
@ -17,7 +17,7 @@
|
||||
<header>
|
||||
<router-link class="name" :to="p.user | userPage" v-user-preview="p.user.id">{{ p.user | userName }}</router-link>
|
||||
<span class="is-bot" v-if="p.user.host === null && p.user.isBot">bot</span>
|
||||
<span class="username">@{{ p.user | acct }}</span>
|
||||
<span class="username"><mk-acct :user="p.user"/></span>
|
||||
<div class="info">
|
||||
<span class="app" v-if="p.app">via <b>{{ p.app.name }}</b></span>
|
||||
<span class="mobile" v-if="p.viaMobile">%fa:mobile-alt%</span>
|
||||
@ -350,6 +350,7 @@ root(isDark)
|
||||
align-items center
|
||||
padding 16px 32px
|
||||
line-height 28px
|
||||
white-space pre
|
||||
color #9dbb00
|
||||
background isDark ? linear-gradient(to bottom, #314027 0%, #282c37 100%) : linear-gradient(to bottom, #edfde2 0%, #fff 100%)
|
||||
|
||||
|
@ -29,7 +29,7 @@ export default Vue.extend({
|
||||
style(): any {
|
||||
if (this.user.bannerUrl == null) return {};
|
||||
return {
|
||||
backgroundColor: this.user.bannerColor ? `rgb(${ this.user.bannerColor.join(',') })` : null,
|
||||
backgroundColor: this.user.bannerColor && this.user.bannerColor.length == 3 ? `rgb(${ this.user.bannerColor.join(',') })` : null,
|
||||
backgroundImage: `url(${ this.user.bannerUrl })`
|
||||
};
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ export default Vue.extend({
|
||||
return this.file.type.split('/')[0];
|
||||
},
|
||||
style(): any {
|
||||
return this.file.properties.avgColor ? {
|
||||
return this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? {
|
||||
'background-color': `rgb(${ this.file.properties.avgColor.join(',') })`
|
||||
} : {};
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ export default Vue.extend({
|
||||
},
|
||||
thumbnail(): any {
|
||||
return {
|
||||
'background-color': this.file.properties.avgColor ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-color': this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-image': `url(${this.file.url}?thumbnail&size=128)`
|
||||
};
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ export default Vue.extend({
|
||||
computed: {
|
||||
style(): any {
|
||||
return {
|
||||
'background-color': this.image.properties.avgColor ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url}?thumbnail&size=512)`
|
||||
};
|
||||
}
|
||||
|
@ -69,8 +69,9 @@ root(isDark)
|
||||
text-decoration underline
|
||||
|
||||
> .username
|
||||
text-align left
|
||||
margin 0 .5em 0 0
|
||||
overflow hidden
|
||||
text-overflow ellipsis
|
||||
color isDark ? #606984 : #d1d8da
|
||||
|
||||
> .time
|
||||
|
@ -268,6 +268,7 @@ root(isDark)
|
||||
align-items center
|
||||
padding 8px 16px
|
||||
line-height 28px
|
||||
white-space pre
|
||||
color #9dbb00
|
||||
background isDark ? linear-gradient(to bottom, #314027 0%, #282c37 100%) : linear-gradient(to bottom, #edfde2 0%, #fff 100%)
|
||||
|
||||
|
@ -84,7 +84,7 @@ export default Vue.extend({
|
||||
style(): any {
|
||||
if (this.user.bannerUrl == null) return {};
|
||||
return {
|
||||
backgroundColor: this.user.bannerColor ? `rgb(${ this.user.bannerColor.join(',') })` : null,
|
||||
backgroundColor: this.user.bannerColor && this.user.bannerColor.length == 3 ? `rgb(${ this.user.bannerColor.join(',') })` : null,
|
||||
backgroundImage: `url(${ this.user.bannerUrl })`
|
||||
};
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ gulp.task('doc:api:endpoints', async () => {
|
||||
return;
|
||||
}
|
||||
const i18n = new I18nReplacer(lang);
|
||||
html = html.replace(i18n.pattern, i18n.replacement.bind(null, null));
|
||||
html = html.replace(i18n.pattern, i18n.replacement);
|
||||
html = fa(html);
|
||||
const htmlPath = `./built/client/docs/${lang}/api/endpoints/${ep.endpoint}.html`;
|
||||
mkdirp(path.dirname(htmlPath), (mkdirErr) => {
|
||||
@ -171,7 +171,7 @@ gulp.task('doc:api:entities', async () => {
|
||||
return;
|
||||
}
|
||||
const i18n = new I18nReplacer(lang);
|
||||
html = html.replace(i18n.pattern, i18n.replacement.bind(null, null));
|
||||
html = html.replace(i18n.pattern, i18n.replacement);
|
||||
html = fa(html);
|
||||
const htmlPath = `./built/client/docs/${lang}/api/entities/${kebab(entity.name)}.html`;
|
||||
mkdirp(path.dirname(htmlPath), (mkdirErr) => {
|
||||
|
@ -53,7 +53,7 @@ gulp.task('doc:docs', async () => {
|
||||
return;
|
||||
}
|
||||
const i18n = new I18nReplacer(lang);
|
||||
html = html.replace(i18n.pattern, i18n.replacement.bind(null, null));
|
||||
html = html.replace(i18n.pattern, i18n.replacement);
|
||||
html = fa(html);
|
||||
const htmlPath = `./built/client/docs/${lang}/${name}.html`;
|
||||
mkdirp(path.dirname(htmlPath), (mkdirErr) => {
|
||||
|
@ -2,14 +2,20 @@ import * as Koa from 'koa';
|
||||
import summaly from 'summaly';
|
||||
|
||||
module.exports = async (ctx: Koa.Context) => {
|
||||
const summary = await summaly(ctx.query.url);
|
||||
summary.icon = wrap(summary.icon);
|
||||
summary.thumbnail = wrap(summary.thumbnail);
|
||||
try {
|
||||
const summary = await summaly(ctx.query.url, {
|
||||
followRedirects: false
|
||||
});
|
||||
summary.icon = wrap(summary.icon);
|
||||
summary.thumbnail = wrap(summary.thumbnail);
|
||||
|
||||
// Cache 7days
|
||||
ctx.set('Cache-Control', 'max-age=604800, immutable');
|
||||
// Cache 7days
|
||||
ctx.set('Cache-Control', 'max-age=604800, immutable');
|
||||
|
||||
ctx.body = summary;
|
||||
ctx.body = summary;
|
||||
} catch (e) {
|
||||
ctx.status = 500;
|
||||
}
|
||||
};
|
||||
|
||||
function wrap(url: string): string {
|
||||
|
@ -171,6 +171,9 @@ const addFile = async (
|
||||
|
||||
log('calculate average color...');
|
||||
|
||||
const info = await prominence(gm(fs.createReadStream(path), name)).identify();
|
||||
const isTransparent = info ? info['Channel depth'].Alpha != null : false;
|
||||
|
||||
const buffer = await prominence(gm(fs.createReadStream(path), name)
|
||||
.setFormat('ppm')
|
||||
.resize(1, 1)) // 1pxのサイズに縮小して平均色を取得するというハック
|
||||
@ -182,7 +185,7 @@ const addFile = async (
|
||||
|
||||
log(`average color is calculated: ${r}, ${g}, ${b}`);
|
||||
|
||||
return [r, g, b];
|
||||
return isTransparent ? [r, g, b, 255] : [r, g, b];
|
||||
})(),
|
||||
// folder
|
||||
(async () => {
|
||||
|
Reference in New Issue
Block a user