1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-02-21 07:29:37 +01:00

fix: missing version on footer (#3674)

* fix: missing version on fotter

* add tests

* fix version

* Delete Footer.test.tsx.snap

* Update renderHTML.ts
This commit is contained in:
Juan Picado 2023-03-11 22:28:58 +01:00 committed by GitHub
parent 83ef80c668
commit f6a538f06d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 519 deletions

@ -12,6 +12,11 @@ describe('home spec', () => {
cy.title().should('eq', 'verdaccio-server-e2e');
});
it('version should be displayed', () => {
cy.visit(ctx.url);
cy.getByTestId('version-footer').contains('Powered by');
});
it('should match title with no packages published', () => {
cy.visit(ctx.url);
cy.getByTestId('help-card').contains('No Package Published Yet.');

@ -75,16 +75,6 @@ export type RateLimit = {
max?: number;
};
// export interface WebConf {
// enable?: boolean;
// title?: string;
// logo?: string;
// favicon?: string;
// gravatar?: boolean;
// sort_packages?: string;
// rateLimit?: RateLimit;
// }
export type FlagsConfig = {
searchRemote?: boolean;
changePassword?: boolean;
@ -105,6 +95,14 @@ export type CommonWebConf = {
login?: boolean;
scope?: string;
pkgManagers?: PackageManagers[];
showInfo?: boolean;
showSettings?: boolean;
showSearch?: boolean;
showFooter?: boolean;
showThemeSwitch?: boolean;
showDownloadTarball?: boolean;
primaryColor: string;
showRaw?: boolean;
};
/**
@ -112,21 +110,11 @@ export type CommonWebConf = {
*/
export type TemplateUIOptions = {
uri?: string;
darkMode?: boolean;
protocol?: string;
host?: string;
// deprecated
// @deprecated use base instead
basename?: string;
scope?: string;
showInfo?: boolean;
showSettings?: boolean;
showSearch?: boolean;
showFooter?: boolean;
showThemeSwitch?: boolean;
showDownloadTarball?: boolean;
showRaw?: boolean;
base: string;
primaryColor: string;
version?: string;
flags: FlagsConfig;
} & CommonWebConf;
@ -135,14 +123,18 @@ export type TemplateUIOptions = {
* Options on config.yaml for web
*/
export type WebConf = {
// FIXME: rename to primaryColor and move it to CommonWebConf
// @deprecated use primaryColor
primary_color?: string;
primaryColor?: string;
enable?: boolean;
scriptsHead?: string[];
scriptsBodyAfter?: string[];
scriptsbodyBefore?: string[];
metaScripts?: string[];
bodyBefore?: string[];
bodyAfter?: string[];
rateLimit?: RateLimit;
html_cache?: boolean;
} & CommonWebConf;
export interface UpLinksConfList {
@ -267,10 +259,13 @@ export interface ConfigYaml {
url_prefix?: string;
server?: ServerSettingsConf;
flags?: FlagsConfig;
// @deprecated use flags instead
experiments?: FlagsConfig;
userRateLimit?: RateLimit;
// internal objects, added by internal yaml to JS config parser
// save the configuration file path
configPath?: string;
i18n?: { web: string };
}
/**

@ -5,7 +5,7 @@ import { URL } from 'url';
import { WEB_TITLE } from '@verdaccio/config';
import { HEADERS } from '@verdaccio/core';
import { TemplateUIOptions } from '@verdaccio/types';
import { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';
import { isURLhasValidProtocol } from '@verdaccio/url';
import { getPublicUrl } from '@verdaccio/url';
@ -22,7 +22,10 @@ const defaultManifestFiles = {
ico: 'favicon.ico',
};
export function resolveLogo(config, req) {
export function resolveLogo(config: ConfigYaml, req) {
if (typeof config?.web?.logo !== 'string') {
return '';
}
const isLocalFile = config?.web?.logo && !isURLhasValidProtocol(config?.web?.logo);
if (isLocalFile) {
@ -34,27 +37,29 @@ export function resolveLogo(config, req) {
}
}
export default function renderHTML(config, manifest, manifestFiles, req, res) {
export default function renderHTML(config: ConfigYaml, manifest, manifestFiles, req, res) {
const { url_prefix } = config;
const base = getPublicUrl(config?.url_prefix, req);
const basename = new URL(base).pathname;
const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;
// @ts-ignore
const needHtmlCache = [undefined, null].includes(config?.web?.html_cache)
? true
: config.web.html_cache;
: config?.web?.html_cache;
const darkMode = config?.web?.darkMode ?? false;
const title = config?.web?.title ?? WEB_TITLE;
const login = hasLogin(config);
const scope = config?.web?.scope ?? '';
const logo = resolveLogo(config, req);
const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm'];
const version = config?.web?.version;
const version = res.locals.app_version ?? '';
const flags = {
...config.flags,
// legacy from 5.x
...config.experiments,
};
const primaryColor = validatePrimaryColor(config?.web?.primary_color) ?? '#4b5e40';
const primaryColor =
validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? '#4b5e40';
const {
scriptsBodyAfter,
metaScripts,
@ -111,6 +116,7 @@ export default function renderHTML(config, manifest, manifestFiles, req, res) {
},
manifest
);
if (needHtmlCache) {
cache.set('template', webPage);
debug('set template cache');

@ -22,6 +22,7 @@ import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/cust
import hookDebug from './debug';
const debug = buildDebug('verdaccio:server');
const { version } = require('../package.json');
const defineAPI = async function (config: IConfig, storage: Storage): Promise<any> {
const auth: Auth = new Auth(config);
@ -81,6 +82,10 @@ const defineAPI = async function (config: IConfig, storage: Storage): Promise<an
// For WebUI & WebUI API
if (_.get(config, 'web.enable', true)) {
app.use((_req, res, next) => {
res.locals.app_version = version ?? '';
next();
});
app.use(await webMiddleware(config, auth, storage));
} else {
app.get('/', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {

@ -1,11 +1,11 @@
import React from 'react';
import { render } from '../../test/test-react-testing-library';
import { render, screen } from '../../test/test-react-testing-library';
import Footer from './Footer';
describe('<Footer /> component', () => {
beforeAll(() => {
window.__VERDACCIO_BASENAME_UI_OPTIONS.version = 'v.1.0.0';
window.__VERDACCIO_BASENAME_UI_OPTIONS.version = 'v1.0.0';
});
afterAll(() => {
@ -13,7 +13,8 @@ describe('<Footer /> component', () => {
});
test('should load the initial state of Footer component', () => {
const { container } = render(<Footer />);
expect(container.firstChild).toMatchSnapshot();
render(<Footer />);
expect(screen.getByTestId('footer')).toBeInTheDocument();
expect(screen.getByTestId('version-footer')).toBeInTheDocument();
});
});

@ -56,7 +56,7 @@ const Footer = () => {
<Right>
{configOptions?.version && (
<>
{t('footer.powered-by')}
<span data-testid="version-footer">{t('footer.powered-by')}</span>
<Logo isDefault={true} onClick={goToVerdaccioWebsite} size="x-small" />
{`/ ${configOptions.version}`}
</>

@ -1,486 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Footer /> component should load the initial state of Footer component 1`] = `
.emotion-0 {
background: #f9f9f9;
border-top: 1px solid #e3e3e3;
color: #999999;
font-size: 14px;
padding: 20px;
}
.emotion-2 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: end;
-ms-flex-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
width: 100%;
}
@media (min-width: 768px) {
.emotion-2 {
min-width: 400px;
max-width: 800px;
margin: auto;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
}
}
@media (min-width: 1024px) {
.emotion-2 {
max-width: 1240px;
}
}
.emotion-4 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: none;
}
@media (min-width: 768px) {
.emotion-4 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
}
.emotion-6 {
position: relative;
height: 18px;
}
.emotion-6:hover .emotion-12 {
visibility: visible;
}
.emotion-10 {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
width: 1em;
height: 1em;
display: inline-block;
fill: currentColor;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
-webkit-transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
font-size: 1.5rem;
width: 18px;
height: 18px;
margin: 0px 8px;
}
.emotion-11 {
display: inline-grid;
grid-template-columns: repeat(8, max-content);
grid-gap: 0px 8px;
position: absolute;
background: #d3dddd;
padding: 1px 4px;
border-radius: 3px;
height: 20px;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
visibility: hidden;
top: -2px;
}
.emotion-11:before {
content: '';
position: absolute;
top: 29%;
left: -4px;
margin-left: -5px;
border: 5px solid;
border-color: #d3dddd transparent transparent transparent;
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.emotion-13 {
width: 10px;
}
.emotion-29 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
@media (min-width: 768px) {
.emotion-29 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
}
.emotion-31 {
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
-webkit-background-position: center;
background-position: center;
-webkit-background-size: contain;
background-size: contain;
background-image: url([object Object]);
background-repeat: no-repeat;
width: 30px;
height: 30px;
}
<div
class="emotion-0 emotion-1"
data-testid="footer"
>
<div
class="emotion-2 emotion-3"
>
<div
class="emotion-4 emotion-5"
>
footer.made-with-love-on
<span
class="emotion-6 emotion-7"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium emotion-8 emotion-9 emotion-10"
focusable="false"
viewBox="0 0 45 45"
>
<defs>
<clippath
id="prefix__a"
>
<path
d="M0 36h36V0H0v36z"
/>
</clippath>
<clippath
id="prefix__b"
>
<path
d="M18 36C8.059 36 0 27.941 0 18S8.059 0 18 0s18 8.059 18 18-8.059 18-18 18z"
/>
</clippath>
</defs>
<g
clip-path="url(#prefix__a)"
transform="matrix(1.25 0 0 -1.25 0 45)"
>
<path
d="M36 18c0-9.941-8.059-18-18-18S0 8.059 0 18s8.059 18 18 18 18-8.059 18-18"
fill="#88c9f9"
/>
</g>
<g
clip-path="url(#prefix__b)"
transform="matrix(1.25 0 0 -1.25 0 45)"
>
<path
d="M3.627 28.952c-.45 2.93 2.195 4.156 3.607 4.47 1.412.314 2.776.62 2.933-.006.156-.628.311-1.46 1.173-1.148.862.314 3.043.56 4.063 1.342 1.02.783 2.244.787 3.264.473 1.02-.313 3.877-.227 3.25-1.167-.627-.94-1.825-.827-2.45-1.924-.628-1.099.171-1.826 1.033-1.826.865 0 1.71-.135 2.26.727.548.863-.383 2.463.324 2.357.706-.106 1.477-.866 2.03-2.043.547-1.176 1.408-.47 1.723-1.176.313-.705 2.04-2.039 1.177-1.804-.864.236-1.726.392-1.96-.47-.237-.863.388-1.726-.237-1.647-.627.08-.86-.089-1.725-.004-.862.083-1.333.631-2.039-.545-.705-1.175-1.254-1.96-1.567-2.509-.315-.549-.785-.86-.55-1.96.235-1.099-.628-.785-.628.156 0 .94-.548 1.098-1.253.942-.706-.157-1.803-.313-1.724-1.098.077-.784-.315-1.725.313-2.352.627-.629 1.33.076 1.723-.158.393-.237 1.525-.023 1.133-.416-.393-.39-1.76-.88-.976-1.509a4.831 4.831 0 011.893-.907c.313-.08.062.774 1.083 1.166 1.017.392 2.608 1.29 3 .584.391-.705.338-.595 1.75-.75 1.41-.156 1.79-.585 2.417-1.917.626-1.333.446-1.192 1.462-1.58 1.021-.394 1.678-.223.737-1.087-.94-.86-1.65-.814-2.199-1.833-.55-1.017-.153-1.73-1.25-2.75A20.755 20.755 0 0024 4c-.618-.37-2.162-2.07-3.083-2.667-.834-.54-1.083 0-1.083 0s.256 1.667.964 2.372c.704.705 1.105 3.344.87 4.128-.235.783-1.36 1.02-1.75 1.333-.393.312-1.418 1.548-1.418 2.334 0 .784 1.71 2.81 1.71 2.81.218-1.089-1.039.328-1.627.523-.47.157-1.542 1.656-2.459 1.814-.916.16-1.363.7-2.068 1.25-.706.55-2.43 1.332-2.353 2.195.08.862-1.725 1.568-2.038 1.568-.314 0-1.019 0-1.647 1.098-.627 1.098-1.725 2.196-1.41 2.98.312.783.391 1.726.233 2.588-.156.862-1.332 1.176-1.567.941-.235-.236-1.489-1.335-1.647-.315"
fill="#5c913b"
/>
</g>
</svg>
<span
class="emotion-11 emotion-12"
>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 0 22.5 15"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 0h22.5v15H0V0z"
fill="#FFF"
/>
<path
d="M0 0h22.5v4H0V0zm0 11h22.5v4H0v-4z"
fill="#D03433"
/>
<path
d="M0 4h22.5v7H0V4z"
fill="#FBCA46"
/>
<path
d="M7.8 7h1v.5h-1V7z"
fill="#FFF"
/>
<path
d="M7.2 8.5c0 .3.3.5.6.5s.6-.2.6-.5L8.5 7H7.1l.1 1.5zM6.6 7c0-.3.2-.5.4-.5h1.5c.3 0 .5.2.5.4V7l-.1 1.5c-.1.6-.5 1-1.1 1-.6 0-1-.4-1.1-1L6.6 7z"
fill="#A41517"
/>
<path
d="M6.8 7.5h2V8h-.5l-.5 1-.5-1h-.5v-.5zM5.3 6h1v3.5h-1V6zm4 0h1v3.5h-1V6zm-2.5-.5c0-.3.2-.5.5-.5h1c.3 0 .5.2.5.5v.2c0 .2-.1.3-.3.3H7c-.1 0-.2-.1-.2-.2v-.3z"
fill="#A41517"
/>
</svg>
</div>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 85.333 512 341.333"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 85.337h512v341.326H0z"
fill="#FFF"
/>
<path
d="M0 85.337h512v113.775H0zm0 227.551h512v113.775H0z"
fill="#338AF3"
/>
<path
d="M256 214.447c-22.949 0-41.553 18.603-41.553 41.553S233.05 297.553 256 297.553c22.949 0 41.553-18.603 41.553-41.553S278.949 214.447 256 214.447zm0 65.298c-13.114 0-23.745-10.631-23.745-23.745s10.631-23.745 23.745-23.745 23.745 10.631 23.745 23.745-10.631 23.745-23.745 23.745z"
fill="#FFDA44"
/>
<path
d="M276.563 261.936 256 256l-20.563 5.936-6.855 11.873h54.836z"
fill="#0052B4"
/>
<path
d="m256 226.32-13.709 23.744L256 256l13.709-5.936z"
fill="#338AF3"
/>
<path
d="M235.437 261.936h41.126l-6.854-11.872h-27.418z"
fill="#6DA544"
/>
</svg>
</div>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 0 513 342"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.3 0h478.4v342H17.3V0z"
fill="#181A93"
/>
<path
d="M0 0h513v114H0V0z"
fill="#FFA44A"
/>
<path
d="M0 228h513v114H0V228z"
fill="#1A9F0B"
/>
<path
d="M0 114h513v114H0V114z"
fill="#FFF"
/>
<circle
cx="256.5"
cy="171"
fill="#FFF"
r="34.2"
/>
<path
d="M256.5 216.6c-25.1 0-45.6-20.5-45.6-45.6s20.5-45.6 45.6-45.6 45.6 20.5 45.6 45.6-20.5 45.6-45.6 45.6zm0-11.4c18.2 0 34.2-16 34.2-34.2s-15.9-34.2-34.2-34.2-34.2 16-34.2 34.2 16 34.2 34.2 34.2z"
fill="#181A93"
/>
<circle
cx="256.5"
cy="171"
fill="#181A93"
r="22.8"
/>
</svg>
</div>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 0 513 342"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 0h513v342H0z"
fill="#009b3a"
/>
<path
d="m256.5 19.3 204.9 151.4L256.5 322 50.6 170.7z"
fill="#fedf00"
/>
<circle
cx="256.5"
cy="171"
fill="#FFF"
r="80.4"
/>
<path
d="M215.9 165.7c-13.9 0-27.4 2.1-40.1 6 .6 43.9 36.3 79.3 80.3 79.3 27.2 0 51.3-13.6 65.8-34.3-24.9-31-63.2-51-106-51zm119 20.3c.9-5 1.5-10.1 1.5-15.4 0-44.4-36-80.4-80.4-80.4-33.1 0-61.5 20.1-73.9 48.6 10.9-2.2 22.1-3.4 33.6-3.4 46.8.1 89 19.5 119.2 50.6z"
fill="#002776"
/>
</svg>
</div>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 0 513 342"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 0h513v342H0z"
fill="#D80027"
/>
<path
d="m226.8 239.2-9.7-15.6-17.9 4.4 11.9-14.1-9.7-15.6 17.1 6.9 11.8-14.1-1.3 18.4 17.1 6.9-17.9 4.4zM290.6 82l-10.1 15.4 11.6 14.3-17.7-4.8-10.1 15.5-1-18.4-17.7-4.8 17.2-6.6-1-18.4 11.6 14.3zm-54.4-56.6-2 18.3 16.8 7.6-18 3.8-2 18.3-9.2-16-17.9 3.8 12.3-13.7-9.2-15.9 16.8 7.5zm56.6 136.4-14.9 10.9 5.8 17.5-14.9-10.8-14.9 11 5.6-17.6-14.9-10.7 18.4-.1 5.6-17.6 5.8 17.5zM115 46.3l17.3 53.5h56.2l-45.4 32.9 17.3 53.5-45.4-33-45.5 33 17.4-53.5-45.5-32.9h56.3z"
fill="#FFDA44"
/>
</svg>
</div>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 0 513 342"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 0h513v342H0z"
fill="#10338c"
/>
<g
fill="#FFF"
>
<path
d="M222.2 170.7c.3-.3.5-.6.8-.9-.2.3-.5.6-.8.9zM188 212.6l11 22.9 24.7-5.7-11 22.8 19.9 15.8-24.8 5.6.1 25.4-19.9-15.9-19.8 15.9.1-25.4-24.8-5.6 19.9-15.8-11.1-22.8 24.8 5.7zm197.9 28.5 5.2 10.9 11.8-2.7-5.3 10.9 9.5 7.5-11.8 2.6v12.2l-9.4-7.6-9.5 7.6.1-12.2-11.8-2.6 9.5-7.5-5.3-10.9 11.8 2.7zm-48.6-116 5.2 10.9 11.8-2.7-5.3 10.9 9.5 7.5-11.8 2.7v12.1l-9.4-7.6-9.5 7.6.1-12.1-11.9-2.7 9.5-7.5-5.3-10.9L332 136zm48.6-66.2 5.2 10.9 11.8-2.7-5.3 10.9 9.5 7.5-11.8 2.7v12.1l-9.4-7.6-9.5 7.6.1-12.1-11.8-2.7 9.5-7.5-5.3-10.9 11.8 2.7zm42.5 49.7 5.2 10.9 11.8-2.7-5.3 10.9 9.5 7.5-11.8 2.6V150l-9.4-7.6-9.5 7.6v-12.2l-11.8-2.6 9.5-7.5-5.3-10.9 11.8 2.7zM398 166.5l4.1 12.7h13.3l-10.8 7.8 4.2 12.7-10.8-7.9-10.8 7.9 4.1-12.7-10.7-7.8h13.3z"
/>
<path
d="M254.8 0v30.6l-45.1 25.1h45.1V115h-59.1l59.1 32.8v22.9h-26.7l-73.5-40.9v40.9H99v-48.6l-87.4 48.6H-1.2v-30.6L44 115H-1.2V55.7h59.1L-1.2 22.8V0h26.7L99 40.8V0h55.6v48.6L242.1 0z"
/>
</g>
<path
d="M142.8 0h-32v69.3h-112v32h112v69.4h32v-69.4h112v-32h-112z"
fill="#D80027"
/>
<path
d="m154.6 115 100.2 55.7v-15.8L183 115z"
fill="#0052B4"
/>
<path
d="m154.6 115 100.2 55.7v-15.8L183 115z"
fill="#FFF"
/>
<path
d="m154.6 115 100.2 55.7v-15.8L183 115zm-83.9 0-71.9 39.9v15.8L99 115z"
fill="#D80027"
/>
<path
d="M99 55.7-1.2 0v15.7l71.9 40z"
fill="#0052B4"
/>
<path
d="M99 55.7-1.2 0v15.7l71.9 40z"
fill="#FFF"
/>
<path
d="M99 55.7-1.2 0v15.7l71.9 40zm84 0 71.8-40V0L154.6 55.7z"
fill="#D80027"
/>
</svg>
</div>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 85.333 512 341.333"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 85.331h512v341.337H0z"
fill="#D80027"
/>
<path
d="M0 85.331h512v113.775H0z"
/>
<path
d="M0 312.882h512v113.775H0z"
fill="#FFDA44"
/>
</svg>
</div>
<div
class="emotion-13 emotion-14"
>
<svg
viewBox="0 85.333 512 341.333"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 85.337h512v341.326H0z"
fill="#D80027"
/>
<path
d="M0 85.337h256V256H0z"
fill="#0052B4"
/>
<path
d="M186.435 170.669 162.558 181.9l12.714 23.125-25.927-4.961-3.286 26.192L128 206.993l-18.06 19.263-3.285-26.192-25.927 4.96 12.714-23.125-23.877-11.23 23.877-11.231-12.714-23.125 25.927 4.96 3.286-26.192L128 134.344l18.06-19.263 3.285 26.192 25.928-4.96-12.715 23.125z"
fill="#FFF"
/>
<circle
cx="128"
cy="170.674"
fill="#0052B4"
r="29.006"
/>
<path
d="M128 190.06c-10.692 0-19.391-8.7-19.391-19.391 0-10.692 8.7-19.391 19.391-19.391 10.692 0 19.391 8.7 19.391 19.391 0 10.691-8.699 19.391-19.391 19.391z"
fill="#FFF"
/>
</svg>
</div>
</span>
</span>
</div>
<div
class="emotion-29 emotion-30"
>
footer.powered-by
<div
class="emotion-31 emotion-32"
/>
/ v.1.0.0
</div>
</div>
</div>
`;