Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
f1047f1ce5 | |||
9beddc941a | |||
3a6a01d2d6 | |||
e0e4bdbdbc | |||
b3daf79b6a | |||
81aa21915b | |||
5aadd80243 | |||
23350b1cbc | |||
daff0977cb | |||
c1e7d56ff8 | |||
61aef56f83 |
@ -1,6 +1,13 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
10.87.5
|
||||
----------
|
||||
* モバイル版でも連携サービスを表示するように
|
||||
* webfingerのacceptが反映されない問題を修正
|
||||
* 返信が遷移後も残り続ける問題を修正
|
||||
* デザインの調整
|
||||
|
||||
10.87.4
|
||||
----------
|
||||
* フォローリクエストを許可するときにエラーになる問題を修正
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "Following"
|
||||
followers: "Followers"
|
||||
is-bot: "This account is a Bot"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age} years old"
|
||||
year: "/"
|
||||
month: "/"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "Suit"
|
||||
followers: "Abonné·e·s"
|
||||
is-bot: "Ce compte est un Bot"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age} ans"
|
||||
year: "/"
|
||||
month: "/"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotや"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -214,7 +214,7 @@ common/views/pages/explore.vue:
|
||||
recently-registered-users: "신규 사용자"
|
||||
popular-tags: "인기 태그"
|
||||
federated: "연합"
|
||||
explore: "{host}를 탐색"
|
||||
explore: "{host}을(를) 탐색"
|
||||
users-info: "현재 {users} 사용자가 등록되어 있습니다"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "사용자가 없습니다"
|
||||
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "팔로잉"
|
||||
followers: "팔로워"
|
||||
is-bot: "이 계정은 Bot입니다"
|
||||
no-description: "자기소개가 없습니다"
|
||||
years-old: "{age}세"
|
||||
year: "년"
|
||||
month: "월"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "Følger"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "Śledzeni"
|
||||
followers: "Śledzący"
|
||||
is-bot: "To konto jest botem"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age} lat"
|
||||
year: "/"
|
||||
month: "/"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotです"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1353,6 +1353,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "关注中"
|
||||
followers: "关注者"
|
||||
is-bot: "这个账户是Bot"
|
||||
no-description: "没有自我介绍"
|
||||
years-old: "{age}岁"
|
||||
year: "年"
|
||||
month: "月"
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "10.87.4",
|
||||
"version": "10.87.5",
|
||||
"codename": "nighthike",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<a class="zxrjzpcj" :href="url" :class="service" target="_blank">
|
||||
<fa :icon="icon" size="lg" fixed-width /><span>{{ text }}</span>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['url', 'text', 'icon', 'service']
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.zxrjzpcj
|
||||
padding 6px 8px 6px 6px
|
||||
border-radius 32px
|
||||
|
||||
&:hover
|
||||
text-decoration none
|
||||
|
||||
&.twitter
|
||||
color #fff
|
||||
background #1da1f3
|
||||
|
||||
&:hover
|
||||
background #0c87cf
|
||||
|
||||
&.github
|
||||
color #fff
|
||||
background #171515
|
||||
|
||||
&:hover
|
||||
background #000
|
||||
|
||||
&.discord
|
||||
color #fff
|
||||
background #7289da
|
||||
|
||||
&:hover
|
||||
background #4968ce
|
||||
|
||||
</style>
|
26
src/client/app/common/views/components/integrations.vue
Normal file
26
src/client/app/common/views/components/integrations.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="nbogcrmo" :v-if="user.twitter || user.github || user.discord">
|
||||
<x-integration v-if="user.twitter" service="twitter" :url="`https://twitter.com/${user.twitter.screenName}`" :text="user.twitter.screenName" :icon="['fab', 'twitter']"/>
|
||||
<x-integration v-if="user.github" service="github" :url="`https://github.com/${user.github.login}`" :text="user.github.login" :icon="['fab', 'github']"/>
|
||||
<x-integration v-if="user.discord" service="discord" :url="`https://discordapp.com/users/${user.discord.id}`" :text="`${user.discord.username}#${user.discord.discriminator}`" :icon="['fab', 'discord']"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import XIntegration from './integrations.integration.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XIntegration
|
||||
},
|
||||
props: ['user']
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.nbogcrmo
|
||||
> *
|
||||
margin-right 10px
|
||||
|
||||
</style>
|
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
</ui-container>
|
||||
|
||||
<ui-container :body-togglable="true" ref="tags">
|
||||
<ui-container :body-togglable="true" :expanded="tag == null" ref="tags">
|
||||
<template #header><fa :icon="faHashtag" fixed-width/>{{ $t('popular-tags') }}</template>
|
||||
|
||||
<div class="vxjfqztj">
|
||||
|
@ -30,6 +30,10 @@ export default Vue.extend({
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
expanded: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
inject: {
|
||||
inDeck: {
|
||||
@ -38,7 +42,7 @@ export default Vue.extend({
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showBody: true
|
||||
showBody: this.expanded
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -23,6 +23,7 @@
|
||||
<div class="description">
|
||||
<mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
|
||||
<p v-else class="empty">{{ $t('no-description') }}</p>
|
||||
<x-integrations :user="user" style="margin-top:16px;"/>
|
||||
</div>
|
||||
<div class="fields" v-if="user.fields">
|
||||
<dl class="field" v-for="(field, i) in user.fields" :key="i">
|
||||
@ -52,9 +53,13 @@ import Vue from 'vue';
|
||||
import i18n from '../../../../i18n';
|
||||
import * as age from 's-age';
|
||||
import XUserMenu from '../../../../common/views/components/user-menu.vue';
|
||||
import XIntegrations from '../../../../common/views/components/integrations.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('desktop/views/pages/user/user.header.vue'),
|
||||
components: {
|
||||
XIntegrations
|
||||
},
|
||||
props: ['user'],
|
||||
computed: {
|
||||
style(): any {
|
||||
@ -215,6 +220,8 @@ export default Vue.extend({
|
||||
color var(--text)
|
||||
|
||||
> .description
|
||||
font-size 15px
|
||||
|
||||
> .empty
|
||||
margin 0
|
||||
opacity 0.5
|
||||
@ -251,6 +258,7 @@ export default Vue.extend({
|
||||
margin-top 16px
|
||||
padding-top 16px
|
||||
border-top solid 1px var(--faceDivider)
|
||||
font-size 15px
|
||||
|
||||
&:empty
|
||||
display none
|
||||
|
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="lnctpgve">
|
||||
<x-integrations :user="user" v-if="user.twitter || user.github || user.discord"/>
|
||||
<mk-note-detail v-for="n in user.pinnedNotes" :key="n.id" :note="n" :compact="true"/>
|
||||
<!--<mk-calendar @chosen="warp" :start="new Date(user.createdAt)"/>-->
|
||||
<div class="activity">
|
||||
@ -17,11 +16,8 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../../../i18n';
|
||||
import parseAcct from '../../../../../../misc/acct/parse';
|
||||
import Progress from '../../../../common/scripts/loading';
|
||||
import XTimeline from './user.timeline.vue';
|
||||
import XPhotos from './user.photos.vue';
|
||||
import XIntegrations from './user.integrations.vue';
|
||||
import XActivity from '../../../../common/views/components/activity.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
@ -29,7 +25,6 @@ export default Vue.extend({
|
||||
components: {
|
||||
XTimeline,
|
||||
XPhotos,
|
||||
XIntegrations,
|
||||
XActivity
|
||||
},
|
||||
props: {
|
||||
|
@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<a :href="url" :class="service" target="_blank">
|
||||
<fa :icon="icon" size="lg" fixed-width />
|
||||
<div>{{ text }}</div>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['url', 'text', 'icon', 'service']
|
||||
});
|
||||
</script>
|
@ -1,66 +0,0 @@
|
||||
<template>
|
||||
<div class="usertwitxxxgithxxdiscxxxintegrat" :v-if="user.twitter || user.github || user.discord">
|
||||
<x-integration v-if="user.twitter" service="twitter" :url="`https://twitter.com/${user.twitter.screenName}`" :text="user.twitter.screenName" :icon="['fab', 'twitter']"/>
|
||||
<x-integration v-if="user.github" service="github" :url="`https://github.com/${user.github.login}`" :text="user.github.login" :icon="['fab', 'github']"/>
|
||||
<x-integration v-if="user.discord" service="discord" :url="`https://discordapp.com/users/${user.discord.id}`" :text="`${user.discord.username}#${user.discord.discriminator}`" :icon="['fab', 'discord']"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import XIntegration from './user.integrations.integration.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XIntegration
|
||||
},
|
||||
props: ['user']
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.usertwitxxxgithxxdiscxxxintegrat
|
||||
display flex
|
||||
|
||||
> a
|
||||
display flex
|
||||
flex 1
|
||||
align-items center
|
||||
padding 16px
|
||||
box-shadow var(--shadow)
|
||||
border-radius var(--round)
|
||||
|
||||
&:not(:last-child)
|
||||
margin-right 16px
|
||||
|
||||
&:hover
|
||||
text-decoration none
|
||||
|
||||
> div
|
||||
padding-left .2em
|
||||
line-height 1.3em
|
||||
flex 1 0
|
||||
word-wrap anywhere
|
||||
|
||||
&.twitter
|
||||
color #fff
|
||||
background #1da1f3
|
||||
|
||||
&:hover
|
||||
background #0c87cf
|
||||
|
||||
&.github
|
||||
color #fff
|
||||
background #171515
|
||||
|
||||
&:hover
|
||||
background #000
|
||||
|
||||
&.discord
|
||||
color #fff
|
||||
background #7289da
|
||||
|
||||
&:hover
|
||||
background #4968ce
|
||||
|
||||
</style>
|
@ -122,19 +122,23 @@ export default Vue.extend({
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Get replies
|
||||
if (!this.compact) {
|
||||
watch: {
|
||||
note() {
|
||||
this.fetchReplies();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchReplies() {
|
||||
if (this.compact) return;
|
||||
this.$root.api('notes/replies', {
|
||||
noteId: this.appearNote.id,
|
||||
limit: 8
|
||||
}).then(replies => {
|
||||
this.replies = replies;
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchConversation() {
|
||||
this.conversationFetching = true;
|
||||
|
||||
|
@ -30,10 +30,14 @@ export default Vue.extend({
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
expanded: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showBody: true
|
||||
showBody: this.expanded
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -23,6 +23,7 @@
|
||||
</div>
|
||||
<div class="description">
|
||||
<mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
|
||||
<x-integrations :user="user" style="margin:24px 0;"/>
|
||||
</div>
|
||||
<div class="fields" v-if="user.fields">
|
||||
<dl class="field" v-for="(field, i) in user.fields" :key="i">
|
||||
@ -86,11 +87,13 @@ import Progress from '../../../../common/scripts/loading';
|
||||
import XUserMenu from '../../../../common/views/components/user-menu.vue';
|
||||
import XHome from './home.vue';
|
||||
import { getStaticImageUrl } from '../../../../common/scripts/get-static-image-url';
|
||||
import XIntegrations from '../../../../common/views/components/integrations.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('mobile/views/pages/user.vue'),
|
||||
components: {
|
||||
XHome
|
||||
XHome,
|
||||
XIntegrations
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -245,6 +248,12 @@ export default Vue.extend({
|
||||
margin 8px 0
|
||||
color var(--mobileUserPageDescription)
|
||||
|
||||
@media (max-width 450px)
|
||||
font-size 15px
|
||||
|
||||
@media (max-width 400px)
|
||||
font-size 14px
|
||||
|
||||
> .fields
|
||||
margin 8px 0
|
||||
|
||||
|
41
src/prelude/xml.ts
Normal file
41
src/prelude/xml.ts
Normal file
@ -0,0 +1,41 @@
|
||||
const map: Record<string, string> = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': '''
|
||||
};
|
||||
|
||||
const beginingOfCDATA = '<![CDATA[';
|
||||
const endOfCDATA = ']]>';
|
||||
|
||||
export function escapeValue(x: string): string {
|
||||
let insideOfCDATA = false;
|
||||
let builder = '';
|
||||
for (
|
||||
let i = 0;
|
||||
i < x.length;
|
||||
) {
|
||||
if (insideOfCDATA) {
|
||||
if (x.slice(i, i + beginingOfCDATA.length) === beginingOfCDATA) {
|
||||
insideOfCDATA = true;
|
||||
i += beginingOfCDATA.length;
|
||||
} else {
|
||||
builder += x[i++];
|
||||
}
|
||||
} else {
|
||||
if (x.slice(i, i + endOfCDATA.length) === endOfCDATA) {
|
||||
insideOfCDATA = false;
|
||||
i += endOfCDATA.length;
|
||||
} else {
|
||||
const b = x[i++];
|
||||
builder += map[b] || b;
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
export function escapeAttribute(x: string): string {
|
||||
return Object.entries(map).reduce((a, [k, v]) => a.replace(k, v), x);
|
||||
}
|
@ -6,27 +6,37 @@ import parseAcct from '../misc/acct/parse';
|
||||
import User from '../models/user';
|
||||
import Acct from '../misc/acct/type';
|
||||
import { links } from './nodeinfo';
|
||||
import { escapeAttribute, escapeValue } from '../prelude/xml';
|
||||
|
||||
// Init router
|
||||
const router = new Router();
|
||||
|
||||
const XRD = (...x: { element: string, value?: string, attributes?: Record<string, string> }[]) =>
|
||||
`<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">${x.map(({ element, value, attributes }) =>
|
||||
`<${
|
||||
Object.entries(typeof attributes === 'object' && attributes || {}).reduce((a, [k, v]) => `${a} ${k}="${escapeAttribute(v)}"`, element)
|
||||
}${
|
||||
typeof value === 'string' ? `>${escapeValue(value)}</${element}` : '/'
|
||||
}>`).reduce((a, c) => a + c, '')}</XRD>`;
|
||||
|
||||
const webFingerPath = '/.well-known/webfinger';
|
||||
const jrd = 'application/jrd+json';
|
||||
const xrd = 'application/xrd+xml';
|
||||
|
||||
router.get('/.well-known/host-meta', async ctx => {
|
||||
ctx.set('Content-Type', 'application/xrd+xml');
|
||||
ctx.body = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" type="application/xrd+xml" template="${config.url}${webFingerPath}?resource={uri}"/>
|
||||
</XRD>
|
||||
`;
|
||||
ctx.set('Content-Type', xrd);
|
||||
ctx.body = XRD({ element: 'Link', attributes: {
|
||||
type: xrd,
|
||||
template: `${config.url}${webFingerPath}?resource={uri}`
|
||||
}});
|
||||
});
|
||||
|
||||
router.get('/.well-known/host-meta.json', async ctx => {
|
||||
ctx.set('Content-Type', 'application/jrd+json');
|
||||
ctx.set('Content-Type', jrd);
|
||||
ctx.body = {
|
||||
links: [{
|
||||
rel: 'lrdd',
|
||||
type: 'application/xrd+xml',
|
||||
type: jrd,
|
||||
template: `${config.url}${webFingerPath}?resource={uri}`
|
||||
}]
|
||||
};
|
||||
@ -75,22 +85,38 @@ router.get(webFingerPath, async ctx => {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.body = {
|
||||
subject: `acct:${user.username}@${config.host}`,
|
||||
links: [{
|
||||
rel: 'self',
|
||||
type: 'application/activity+json',
|
||||
href: `${config.url}/users/${user._id}`
|
||||
}, {
|
||||
rel: 'http://webfinger.net/rel/profile-page',
|
||||
type: 'text/html',
|
||||
href: `${config.url}/@${user.username}`
|
||||
}, {
|
||||
rel: 'http://ostatus.org/schema/1.0/subscribe',
|
||||
template: `${config.url}/authorize-follow?acct={uri}`
|
||||
}]
|
||||
const subject = `acct:${user.username}@${config.host}`;
|
||||
const self = {
|
||||
rel: 'self',
|
||||
type: 'application/activity+json',
|
||||
href: `${config.url}/users/${user._id}`
|
||||
};
|
||||
const profilePage = {
|
||||
rel: 'http://webfinger.net/rel/profile-page',
|
||||
type: 'text/html',
|
||||
href: `${config.url}/@${user.username}`
|
||||
};
|
||||
const subscribe = {
|
||||
rel: 'http://ostatus.org/schema/1.0/subscribe',
|
||||
template: `${config.url}/authorize-follow?acct={uri}`
|
||||
};
|
||||
|
||||
if (ctx.accepts(jrd, xrd) === xrd) {
|
||||
ctx.body = XRD(
|
||||
{ element: 'Subject', value: subject },
|
||||
{ element: 'Link', attributes: self },
|
||||
{ element: 'Link', attributes: profilePage },
|
||||
{ element: 'Link', attributes: subscribe });
|
||||
ctx.type = xrd;
|
||||
} else {
|
||||
ctx.body = {
|
||||
subject,
|
||||
links: [self, profilePage, subscribe]
|
||||
};
|
||||
ctx.type = jrd;
|
||||
}
|
||||
|
||||
ctx.vary('Accept');
|
||||
ctx.set('Cache-Control', 'public, max-age=180');
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user