refactor external links

This commit is contained in:
Nolan Lawson 2018-01-28 19:01:51 -08:00
parent cda9566eb0
commit 689cd97071
9 changed files with 80 additions and 29 deletions

View File

@ -19,4 +19,5 @@ module.exports = [
{id:'fa-user-times', src:'node_modules/font-awesome-svg-png/white/svg/user-times.svg', title: 'Stop Following'}, {id:'fa-user-times', src:'node_modules/font-awesome-svg-png/white/svg/user-times.svg', title: 'Stop Following'},
{id:'fa-user-plus', src:'node_modules/font-awesome-svg-png/white/svg/user-plus.svg', title: 'Follow'}, {id:'fa-user-plus', src:'node_modules/font-awesome-svg-png/white/svg/user-plus.svg', title: 'Follow'},
{id:'fa-comments', src:'node_modules/font-awesome-svg-png/white/svg/comments.svg', title: 'Statuses'}, {id:'fa-comments', src:'node_modules/font-awesome-svg-png/white/svg/comments.svg', title: 'Statuses'},
{id:'fa-external-link', src:'node_modules/font-awesome-svg-png/white/svg/external-link.svg', title: 'External Link'},
] ]

View File

@ -6,9 +6,9 @@
<img src="{{profile.avatar}}" aria-hidden="true"> <img src="{{profile.avatar}}" aria-hidden="true">
</div> </div>
<div class="account-profile-name"> <div class="account-profile-name">
<a rel="noopener" target="_blank" href="{{profile.url}}"> <ExternalLink href="{{profile.url}}">
{{profile.display_name}} {{profile.display_name}}
</a> </ExternalLink>
</div> </div>
<div class="account-profile-username"> <div class="account-profile-username">
{{'@' + profile.acct}} {{'@' + profile.acct}}
@ -129,11 +129,11 @@
text-overflow: ellipsis; text-overflow: ellipsis;
min-width: 0; min-width: 0;
} }
.account-profile-name a { :global(.account-profile-name a) {
color: var(--body-text-color); color: var(--body-text-color);
text-decoration: none; text-decoration: none;
} }
.account-profile-name a:hover { :global(.account-profile-name a:hover) {
color: var(--body-text-color); color: var(--body-text-color);
text-decoration: underline; text-decoration: underline;
} }
@ -175,13 +175,15 @@
</style> </style>
<script> <script>
import IconButton from './IconButton.html' import IconButton from './IconButton.html'
import ExternalLink from './ExternalLink.html'
export default { export default {
computed: { computed: {
headerIsMissing: (profile) => profile.header.endsWith('missing.png') headerIsMissing: (profile) => profile.header.endsWith('missing.png')
}, },
components: { components: {
IconButton IconButton,
ExternalLink
} }
} }
</script> </script>

View File

@ -0,0 +1,31 @@
{{#if class}}
<a rel="nofollow noopener" target="_blank" href="{{href}}" class="external-link {{class}}">
<slot></slot>
{{#if showIcon}}
<svg>
<use xlink:href="#fa-external-link" />
</svg>
{{/if}}
</a>
{{else}}
<a rel="nofollow noopener" target="_blank" href="{{href}}" class="external-link">
<slot></slot>
{{#if showIcon}}
<svg>
<use xlink:href="#fa-external-link" />
</svg>
{{/if}}
</a>
{{/if}}
<style>
.external-link {
display: inline-flex;
align-items: center;
}
.external-link svg {
margin-left: 4px;
width: 14px;
height: 14px;
fill: var(--deemphasized-text-color);
}
</style>

View File

@ -7,11 +7,11 @@
</svg> </svg>
<h1>Pinafore</h1> <h1>Pinafore</h1>
</div> </div>
<p>Pinafore is a web client for <a rel="noopener" target="_blank" href="https://joinmastodon.org">Mastodon</a>, optimized for speed and simplicity.</p> <p>Pinafore is a web client for <ExternalLink href="https://joinmastodon.org">Mastodon</ExternalLink>, optimized for speed and simplicity.</p>
<p>To get started, <a href="/settings/instances/add">log in to an instance</a>.</p> <p>To get started, <a href="/settings/instances/add">log in to an instance</a>.</p>
<p>Don't have an instance? <a rel="noopener" target="_blank" href="https://joinmastodon.org">Join Mastodon!</a></p> <p>Don't have an instance? <ExternalLink href="https://joinmastodon.org">Join Mastodon!</ExternalLink></p>
</div> </div>
</FreeTextLayout> </FreeTextLayout>
</HiddenFromSSR> </HiddenFromSSR>
@ -46,11 +46,13 @@
<script> <script>
import FreeTextLayout from './FreeTextLayout.html' import FreeTextLayout from './FreeTextLayout.html'
import HiddenFromSSR from './HiddenFromSSR.html' import HiddenFromSSR from './HiddenFromSSR.html'
import ExternalLink from './ExternalLink.html'
export default { export default {
components: { components: {
FreeTextLayout, FreeTextLayout,
HiddenFromSSR HiddenFromSSR,
ExternalLink
} }
} }
</script> </script>

View File

@ -8,7 +8,7 @@
</svg> </svg>
<span> <span>
{{#if timelineType === 'account' && timelineValue === status.account.id}} {{#if timelineType === 'account' && timelineValue === status.account.id}}
<a rel="noopener" target="_blank" href="{{status.account.url}}">{{status.account.username}}</a> <ExternalLink href="{{status.account.url}}">{{status.account.username}}</ExternalLink>
{{else}} {{else}}
<a href="/accounts/{{status.account.id}}">{{status.account.username}}</a> <a href="/accounts/{{status.account.id}}">{{status.account.username}}</a>
{{/if}} {{/if}}
@ -18,9 +18,9 @@
{{/if}} {{/if}}
<div class="status-author"> <div class="status-author">
{{#if timelineType === 'account' && timelineValue === originalAccount.id}} {{#if timelineType === 'account' && timelineValue === originalAccount.id}}
<a class="status-author-name" rel="noopener" target="_blank" href="{{originalAccount.url}}"> <ExternalLink class="status-author-name" href="{{originalAccount.url}}">
{{originalAccount.display_name || originalAccount.username}} {{originalAccount.display_name || originalAccount.username}}
</a> </ExternalLink>
{{else}} {{else}}
<a class="status-author-name" href="/accounts/{{originalAccount.id}}"> <a class="status-author-name" href="/accounts/{{originalAccount.id}}">
{{originalAccount.display_name || originalAccount.username}} {{originalAccount.display_name || originalAccount.username}}
@ -30,9 +30,9 @@
{{'@' + originalAccount.acct}} {{'@' + originalAccount.acct}}
</span> </span>
{{#if timelineType === 'status'}} {{#if timelineType === 'status'}}
<a class="status-author-date" rel="noopener" target="_blank" href="{{originalStatus.url}}"> <ExternalLink class="status-author-date" href="{{originalStatus.url}}" showIcon="true">
<time datetime={{createdAtDate}} title="{{relativeDate}}">{{relativeDate}}</time> <time datetime={{createdAtDate}} title="{{relativeDate}}">{{relativeDate}}</time>
</a> </ExternalLink>
{{else}} {{else}}
<a class="status-author-date" href="/statuses/{{originalStatus.id}}"> <a class="status-author-date" href="/statuses/{{originalStatus.id}}">
<time datetime={{createdAtDate}} title="{{relativeDate}}">{{relativeDate}}</time> <time datetime={{createdAtDate}} title="{{relativeDate}}">{{relativeDate}}</time>
@ -139,11 +139,11 @@
min-width: 0; min-width: 0;
} }
.status-author a, .status-author a:visited, .status-author a:hover, .status-author .status-author-handle { :global(.status-author a, .status-author a:visited, .status-author a:hover, .status-author .status-author-handle) {
color: var(--deemphasized-text-color); color: var(--deemphasized-text-color);
} }
.status-author .status-author-name { :global(.status-author .status-author-name) {
min-width: 0; min-width: 0;
flex-shrink: 1; flex-shrink: 1;
color: var(--body-text-color); color: var(--body-text-color);
@ -153,7 +153,7 @@
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.status-author .status-author-name:hover { :global(.status-author .status-author-name:hover) {
color: var(--body-text-color); color: var(--body-text-color);
} }
@ -166,12 +166,16 @@
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.status-author-date { :global(.status-author-date) {
color: var(--deemphasized-text-color);
flex-shrink: 1; flex-shrink: 1;
text-align: right; text-align: right;
margin-left: 5px; margin-left: 5px;
white-space: nowrap; white-space: nowrap;
} }
:global(.status-author-date:hover) {
color: var(--deemphasized-text-color);
}
.status-content { .status-content {
margin: 10px 10px 10px 5px; margin: 10px 10px 10px 5px;
@ -204,7 +208,7 @@
margin-left: 5px; margin-left: 5px;
} }
.status-boosted span, .status-boosted a, .status-boosted a:visited, .status-boosted a:hover { :global(.status-boosted span, .status-boosted a, .status-boosted a:visited, .status-boosted a:hover) {
color: var(--deemphasized-text-color); color: var(--deemphasized-text-color);
} }
@ -313,6 +317,7 @@
import IntlRelativeFormat from 'intl-relativeformat' import IntlRelativeFormat from 'intl-relativeformat'
import { replaceAll } from '../../_utils/strings' import { replaceAll } from '../../_utils/strings'
import { store } from '../../_store/store' import { store } from '../../_store/store'
import ExternalLink from '../ExternalLink.html'
const relativeFormat = new IntlRelativeFormat('en-US'); const relativeFormat = new IntlRelativeFormat('en-US');
@ -323,7 +328,8 @@
components: { components: {
Avatar, Avatar,
Media, Media,
Toolbar Toolbar,
ExternalLink
}, },
store: () => store, store: () => store,
computed: { computed: {

View File

@ -6,22 +6,24 @@
<SettingsLayout page='settings/about' label="About Pinafore"> <SettingsLayout page='settings/about' label="About Pinafore">
<h1>About Pinafore</h1> <h1>About Pinafore</h1>
<p>Pinafore is <a rel="noopener" target="_blank" href="https://github.com/nolanlawson/pinafore/">open-source software</a> created by <a rel="noopener" target="_blank" href="https://nolanlawson.com/">Nolan Lawson</a>.</p> <p>Pinafore is <ExternalLink href="https://github.com/nolanlawson/pinafore/">open-source software</ExternalLink> created by <ExternalLink href="https://nolanlawson.com/">Nolan Lawson</ExternalLink>.</p>
<p>Icons provided by <a rel="noopener" target="_blank" href="http://fontawesome.io/">Font Awesome</a>.</p> <p>Icons provided by <ExternalLink href="http://fontawesome.io/">Font Awesome</ExternalLink>.</p>
<p>Logo thanks to "sailboat" by Gregor Cresnar from <a rel="noopener" target="_blank" href="https://thenounproject.com/">the Noun Project</a>.</p> <p>Logo thanks to "sailboat" by Gregor Cresnar from <ExternalLink href="https://thenounproject.com/">the Noun Project</ExternalLink>.</p>
</SettingsLayout> </SettingsLayout>
</Layout> </Layout>
<script> <script>
import Layout from '../_components/Layout.html'; import Layout from '../_components/Layout.html';
import SettingsLayout from './_components/SettingsLayout.html' import SettingsLayout from './_components/SettingsLayout.html'
import ExternalLink from '../_components/ExternalLink.html'
export default { export default {
components: { components: {
Layout, Layout,
SettingsLayout SettingsLayout,
ExternalLink
} }
}; };
</script> </script>

View File

@ -11,8 +11,10 @@
<div class="acct-current-user"> <div class="acct-current-user">
<img alt="Profile picture for {{'@' + verifyCredentials.acct}}" <img alt="Profile picture for {{'@' + verifyCredentials.acct}}"
class="acct-avatar" src="{{verifyCredentials.avatar}}" /> class="acct-avatar" src="{{verifyCredentials.avatar}}" />
<a class="acct-handle" rel="noopener" target="_blank" <ExternalLink class="acct-handle"
href="{{verifyCredentials.url}}">{{'@' + verifyCredentials.acct}}</a> href="{{verifyCredentials.url}}">
{{'@' + verifyCredentials.acct}}
</ExternalLink>
<span class="acct-display-name">{{verifyCredentials.display_name}}</span> <span class="acct-display-name">{{verifyCredentials.display_name}}</span>
</div> </div>
<h2>Theme:</h2> <h2>Theme:</h2>
@ -59,7 +61,7 @@
border-radius: 4px; border-radius: 4px;
grid-area: avatar; grid-area: avatar;
} }
.acct-handle { :global(.acct-handle) {
grid-area: handle; grid-area: handle;
} }
.theme-chooser { .theme-chooser {
@ -97,6 +99,7 @@
import { store } from '../../_store/store' import { store } from '../../_store/store'
import Layout from '../../_components/Layout.html' import Layout from '../../_components/Layout.html'
import SettingsLayout from '../_components/SettingsLayout.html' import SettingsLayout from '../_components/SettingsLayout.html'
import ExternalLink from '../../_components/ExternalLink.html'
import { import {
changeTheme, changeTheme,
switchToInstance, switchToInstance,
@ -108,7 +111,8 @@
export default { export default {
components: { components: {
Layout, Layout,
SettingsLayout SettingsLayout,
ExternalLink
}, },
store: () => store, store: () => store,
data: () => ({ data: () => ({

View File

@ -30,7 +30,7 @@
</form> </form>
{{#if !$isUserLoggedIn}} {{#if !$isUserLoggedIn}}
<p>Don't have an instance? <a rel="noopener" target="_blank" href="https://joinmastodon.org">Join Mastodon!</a></p> <p>Don't have an instance? <ExternalLink href="https://joinmastodon.org">Join Mastodon!</ExternalLink></p>
{{/if}} {{/if}}
</SettingsLayout> </SettingsLayout>
</Layout> </Layout>
@ -73,6 +73,7 @@
import { store } from '../../_store/store' import { store } from '../../_store/store'
import LoadingMask from '../../_components/LoadingMask' import LoadingMask from '../../_components/LoadingMask'
import { logInToInstance, handleOauthCode } from './_actions/add' import { logInToInstance, handleOauthCode } from './_actions/add'
import ExternalLink from '../../_components/ExternalLink.html'
export default { export default {
async oncreate () { async oncreate () {
@ -84,7 +85,8 @@
components: { components: {
Layout, Layout,
SettingsLayout, SettingsLayout,
LoadingMask LoadingMask,
ExternalLink
}, },
store: () => store, store: () => store,
methods: { methods: {

View File

@ -84,6 +84,7 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
<symbol id="fa-user-times" viewBox="0 0 2048 1792"><title>Stop Following</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm1077 320l249 249q9 9 9 23 0 13-9 22l-136 136q-9 9-22 9-14 0-23-9l-249-249-249 249q-9 9-23 9-13 0-22-9l-136-136q-9-9-9-22 0-14 9-23l249-249-249-249q-9-9-9-23 0-13 9-22l136-136q9-9 22-9 14 0 23 9l249 249 249-249q9-9 23-9 13 0 22 9l136 136q9 9 9 22 0 14-9 23zm-498 0l-181 181q-37 37-37 91 0 53 37 90l83 83q-21 3-44 3H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 154 122 319 122t319-122q20-17 39-17 28 0 57 6-28 27-41 50t-13 56q0 54 37 91z"></path></symbol> <symbol id="fa-user-times" viewBox="0 0 2048 1792"><title>Stop Following</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm1077 320l249 249q9 9 9 23 0 13-9 22l-136 136q-9 9-22 9-14 0-23-9l-249-249-249 249q-9 9-23 9-13 0-22-9l-136-136q-9-9-9-22 0-14 9-23l249-249-249-249q-9-9-9-23 0-13 9-22l136-136q9-9 22-9 14 0 23 9l249 249 249-249q9-9 23-9 13 0 22 9l136 136q9 9 9 22 0 14-9 23zm-498 0l-181 181q-37 37-37 91 0 53 37 90l83 83q-21 3-44 3H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 154 122 319 122t319-122q20-17 39-17 28 0 57 6-28 27-41 50t-13 56q0 54 37 91z"></path></symbol>
<symbol id="fa-user-plus" viewBox="0 0 2048 1792"><title>Follow</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm960 128h352q13 0 22.5 9.5t9.5 22.5v192q0 13-9.5 22.5t-22.5 9.5h-352v352q0 13-9.5 22.5t-22.5 9.5h-192q-13 0-22.5-9.5t-9.5-22.5v-352h-352q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h352V672q0-13 9.5-22.5t22.5-9.5h192q13 0 22.5 9.5t9.5 22.5v352zm-736 224q0 52 38 90t90 38h256v238q-68 50-171 50H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 79 61 154.5 91.5T704 971t164.5-30.5T1023 849q20-17 39-17 132 0 217 96h-223q-52 0-90 38t-38 90v192z"></path></symbol> <symbol id="fa-user-plus" viewBox="0 0 2048 1792"><title>Follow</title><path d="M704 896q-159 0-271.5-112.5T320 512t112.5-271.5T704 128t271.5 112.5T1088 512 975.5 783.5 704 896zm960 128h352q13 0 22.5 9.5t9.5 22.5v192q0 13-9.5 22.5t-22.5 9.5h-352v352q0 13-9.5 22.5t-22.5 9.5h-192q-13 0-22.5-9.5t-9.5-22.5v-352h-352q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h352V672q0-13 9.5-22.5t22.5-9.5h192q13 0 22.5 9.5t9.5 22.5v352zm-736 224q0 52 38 90t90 38h256v238q-68 50-171 50H267q-121 0-194-69T0 1405q0-53 3.5-103.5t14-109T44 1084t43-97.5 62-81 85.5-53.5T346 832q19 0 39 17 79 61 154.5 91.5T704 971t164.5-30.5T1023 849q20-17 39-17 132 0 217 96h-223q-52 0-90 38t-38 90v192z"></path></symbol>
<symbol id="fa-comments" viewBox="0 0 1792 1792"><title>Statuses</title><path d="M1408 768q0 139-94 257t-256.5 186.5T704 1280q-86 0-176-16-124 88-278 128-36 9-86 16h-3q-11 0-20.5-8t-11.5-21q-1-3-1-6.5t.5-6.5 2-6l2.5-5 3.5-5.5 4-5 4.5-5 4-4.5q5-6 23-25t26-29.5 22.5-29 25-38.5 20.5-44q-124-72-195-177T0 768q0-139 94-257t256.5-186.5T704 256t353.5 68.5T1314 511t94 257zm384 256q0 120-71 224.5T1526 1425q10 24 20.5 44t25 38.5 22.5 29 26 29.5 23 25q1 1 4 4.5t4.5 5 4 5 3.5 5.5l2.5 5 2 6 .5 6.5-1 6.5q-3 14-13 22t-22 7q-50-7-86-16-154-40-278-128-90 16-176 16-271 0-472-132 58 4 88 4 161 0 309-45t264-129q125-92 192-212t67-254q0-77-23-152 129 71 204 178t75 230z"></path></symbol> <symbol id="fa-comments" viewBox="0 0 1792 1792"><title>Statuses</title><path d="M1408 768q0 139-94 257t-256.5 186.5T704 1280q-86 0-176-16-124 88-278 128-36 9-86 16h-3q-11 0-20.5-8t-11.5-21q-1-3-1-6.5t.5-6.5 2-6l2.5-5 3.5-5.5 4-5 4.5-5 4-4.5q5-6 23-25t26-29.5 22.5-29 25-38.5 20.5-44q-124-72-195-177T0 768q0-139 94-257t256.5-186.5T704 256t353.5 68.5T1314 511t94 257zm384 256q0 120-71 224.5T1526 1425q10 24 20.5 44t25 38.5 22.5 29 26 29.5 23 25q1 1 4 4.5t4.5 5 4 5 3.5 5.5l2.5 5 2 6 .5 6.5-1 6.5q-3 14-13 22t-22 7q-50-7-86-16-154-40-278-128-90 16-176 16-271 0-472-132 58 4 88 4 161 0 309-45t264-129q125-92 192-212t67-254q0-77-23-152 129 71 204 178t75 230z"></path></symbol>
<symbol id="fa-external-link" viewBox="0 0 1792 1792"><title>External Link</title><path d="M1408 928v320q0 119-84.5 203.5T1120 1536H288q-119 0-203.5-84.5T0 1248V416q0-119 84.5-203.5T288 128h704q14 0 23 9t9 23v64q0 14-9 23t-23 9H288q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113V928q0-14 9-23t23-9h64q14 0 23 9t9 23zm384-864v512q0 26-19 45t-45 19-45-19l-176-176-652 652q-10 10-23 10t-23-10L695 983q-10-10-10-23t10-23l652-652-176-176q-19-19-19-45t19-45 45-19h512q26 0 45 19t19 45z"></path></symbol>
</svg><!-- end insert svg here --> </svg><!-- end insert svg here -->
</svg> </svg>
<!-- The application will be rendered inside this element, <!-- The application will be rendered inside this element,