@jjlmoya/utils-developer 1.15.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/index.ts +2 -1
- package/src/entries.ts +4 -1
- package/src/index.ts +2 -0
- package/src/tests/locale_completeness.test.ts +2 -3
- package/src/tests/pagespeed_best_practices.test.ts +198 -0
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/aspectRatio/component.astro +3 -1
- package/src/tool/colorConverter/component.astro +3 -3
- package/src/tool/llmCostCalculator/component.astro +1 -2
- package/src/tool/mobileMockupGenerator/component.astro +4 -5
- package/src/tool/placeholderGenerator/component.astro +2 -2
- package/src/tool/readabilityCalculator/component.astro +4 -4
- package/src/tool/serpPixelSimulator/bibliography.astro +7 -0
- package/src/tool/serpPixelSimulator/bibliography.ts +16 -0
- package/src/tool/serpPixelSimulator/component.astro +84 -0
- package/src/tool/serpPixelSimulator/controller.ts +323 -0
- package/src/tool/serpPixelSimulator/entry.ts +30 -0
- package/src/tool/serpPixelSimulator/i18n/de.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/en.ts +213 -0
- package/src/tool/serpPixelSimulator/i18n/es.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/fr.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/id.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/it.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/ja.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/ko.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/nl.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/pl.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/pt.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/ru.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/sv.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/tr.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/zh.ts +214 -0
- package/src/tool/serpPixelSimulator/index.ts +12 -0
- package/src/tool/serpPixelSimulator/logic.ts +18 -0
- package/src/tool/serpPixelSimulator/seo.astro +12 -0
- package/src/tool/serpPixelSimulator/serp-pixel-simulator.css +335 -0
- package/src/tool/serpPixelSimulator/ui.ts +33 -0
- package/src/tools.ts +2 -2
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { SerpPixelSimulatorUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
5
|
+
|
|
6
|
+
const slug = 'simulador-serp-contador-pixels';
|
|
7
|
+
const title = 'Simulador SERP e Contador de Píxeis SEO';
|
|
8
|
+
const description = 'Pré-visualize snippets de pesquisa ao estilo Google em tempo real, meça a largura em píxeis do título e da meta description e veja exatamente onde o seu texto será truncado.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Introduza a tag title',
|
|
13
|
+
text: 'Digite ou cole o título da página que pretende testar. A pré-visualização SERP e o medidor de píxeis atualizam-se a cada tecla premida.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Adicione o URL visível',
|
|
17
|
+
text: 'Use um domínio e caminho realistas para que o snippet se pareça com o resultado que um utilizador analisaria.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Escreva a meta description',
|
|
21
|
+
text: 'Adicione o texto da descrição e observe a barra de píxeis. Quando excede a largura visual recomendada, a pré-visualização trunca-a com reticências.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Alterne entre desktop e mobile',
|
|
25
|
+
text: 'Compare a renderização do título com a largura do cartão de desktop ou mobile antes de publicar os metadados.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: 'Porquê contar píxeis em vez de caracteres para títulos SEO?',
|
|
32
|
+
answer: 'Os cartões de resultados do Google são limitados pela largura visual. Um título com muitas letras estreitas pode conter mais caracteres do que um com letras largas, maiúsculas ou glifos de aspeto espesso. A medição em píxeis oferece uma pré-visualização mais fiel do resultado visível.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: 'Isto garante exatamente como o Google irá truncar o meu snippet?',
|
|
36
|
+
answer: 'Não. O Google pode reescrever os links de título e os snippets, e a renderização pode variar consoante a consulta, o dispositivo, o idioma e as experiências. A ferramenta foi concebida como um guia visual prático para escrever metadados com menor probabilidade de serem cortados.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: 'Que limites de píxeis utiliza o simulador?',
|
|
40
|
+
answer: 'O limite predefinido do título em desktop é de 580 px, o do título em mobile é de 600 px e o limite da meta description é de 920 px. São metas de redação, não limites oficiais do Google.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: 'Porque é que a pré-visualização adiciona reticências?',
|
|
44
|
+
answer: 'Quando o texto medido excede a largura de píxeis disponível, o simulador trunca a string no último caractere que cabe e acrescenta três pontos, reproduzindo o comportamento prático de que as equipas de SEO precisam para detetar perda de significado.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: SerpPixelSimulatorUI = {
|
|
49
|
+
titleLabel: 'Tag title',
|
|
50
|
+
titlePlaceholder: 'GameBob | Estúdio de Desenvolvimento Independente',
|
|
51
|
+
urlLabel: 'URL visível',
|
|
52
|
+
urlPlaceholder: 'https://www.gamebob.dev/pt/',
|
|
53
|
+
descriptionLabel: 'Meta description',
|
|
54
|
+
descriptionPlaceholder: 'Descubra a nossa coleção de ferramentas e jogos concebidos para elevar o seu fluxo de trabalho digital e entretenimento.',
|
|
55
|
+
deviceLabel: 'Modo de pré-visualização',
|
|
56
|
+
desktopLabel: 'Desktop',
|
|
57
|
+
mobileLabel: 'Mobile',
|
|
58
|
+
titlePixelsLabel: 'Largura do título',
|
|
59
|
+
descriptionPixelsLabel: 'Largura da descrição',
|
|
60
|
+
charactersLabel: 'caracteres',
|
|
61
|
+
previewLabel: 'Pré-visualização ao vivo estilo Google',
|
|
62
|
+
tooLongLabel: 'Demasiado largo',
|
|
63
|
+
goodLabel: 'Ok',
|
|
64
|
+
emptyTitle: 'O seu título aparecerá aqui',
|
|
65
|
+
emptyDescription: 'A pré-visualização da sua meta description aparecerá aqui enquanto digita.',
|
|
66
|
+
defaultTitle: 'GameBob | Estúdio de Desenvolvimento Independente',
|
|
67
|
+
defaultUrl: 'https://www.gamebob.dev/pt/',
|
|
68
|
+
defaultDescription: 'Descubra a nossa coleção de ferramentas e jogos concebidos para elevar o seu fluxo de trabalho digital e entretenimento.',
|
|
69
|
+
fallbackUrl: 'exemplo.com',
|
|
70
|
+
fallbackFaviconText: 'G',
|
|
71
|
+
pixelUnit: 'px',
|
|
72
|
+
ellipsis: '...',
|
|
73
|
+
fetchButtonLabel: 'Obter',
|
|
74
|
+
fetchLoadingLabel: 'A obter...',
|
|
75
|
+
fetchSuccessLabel: 'Metadados carregados a partir do URL.',
|
|
76
|
+
fetchCorsError: 'O navegador não conseguiu ler esta página. Pode estar bloqueada por CORS, um redireccionamento, conteúdo misto ou uma regra de rede. Pode colar ou editar os metadados manualmente.',
|
|
77
|
+
fetchInvalidUrlError: 'Introduza um URL válido antes de obter os metadados.',
|
|
78
|
+
fetchNoMetadataError: 'A página foi obtida, mas não foi encontrado título nem meta description.',
|
|
79
|
+
fetchGenericError: 'Não foi possível obter os metadados deste URL. Verifique o endereço ou preencha os campos manualmente.',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
83
|
+
'@context': 'https://schema.org',
|
|
84
|
+
'@type': 'FAQPage',
|
|
85
|
+
mainEntity: faq.map((item) => ({
|
|
86
|
+
'@type': 'Question',
|
|
87
|
+
name: item.question,
|
|
88
|
+
acceptedAnswer: {
|
|
89
|
+
'@type': 'Answer',
|
|
90
|
+
text: item.answer,
|
|
91
|
+
},
|
|
92
|
+
})),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const howToSchema: WithContext<HowTo> = {
|
|
96
|
+
'@context': 'https://schema.org',
|
|
97
|
+
'@type': 'HowTo',
|
|
98
|
+
name: title,
|
|
99
|
+
description,
|
|
100
|
+
step: howTo.map((step, index) => ({
|
|
101
|
+
'@type': 'HowToStep',
|
|
102
|
+
position: index + 1,
|
|
103
|
+
name: step.name,
|
|
104
|
+
text: step.text,
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
109
|
+
'@context': 'https://schema.org',
|
|
110
|
+
'@type': 'SoftwareApplication',
|
|
111
|
+
name: title,
|
|
112
|
+
description,
|
|
113
|
+
applicationCategory: 'BusinessApplication',
|
|
114
|
+
operatingSystem: 'Any',
|
|
115
|
+
offers: {
|
|
116
|
+
'@type': 'Offer',
|
|
117
|
+
price: '0',
|
|
118
|
+
priceCurrency: 'EUR',
|
|
119
|
+
},
|
|
120
|
+
inLanguage: 'pt',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const content: ToolLocaleContent<SerpPixelSimulatorUI> = {
|
|
124
|
+
slug,
|
|
125
|
+
title,
|
|
126
|
+
description,
|
|
127
|
+
ui,
|
|
128
|
+
faqTitle: 'Perguntas frequentes sobre o simulador SERP',
|
|
129
|
+
faq,
|
|
130
|
+
bibliographyTitle: 'Documentação sobre resultados de pesquisa',
|
|
131
|
+
bibliography,
|
|
132
|
+
howTo,
|
|
133
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
134
|
+
seo: [
|
|
135
|
+
{
|
|
136
|
+
type: 'title',
|
|
137
|
+
text: 'Deixe de adivinhar como será o seu resultado no Google',
|
|
138
|
+
level: 2,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'paragraph',
|
|
142
|
+
html: 'Uma tag title pode parecer perfeita numa folha de cálculo e mesmo assim falhar no resultado de pesquisa. O Google não reserva espaço por contagem de caracteres; renderiza o texto dentro de um cartão visual. Isso significa que <strong>GameBob | Estúdio de Desenvolvimento Independente</strong> e outro título com o mesmo número de caracteres podem ocupar larguras muito diferentes consoante as letras, maiúsculas, pontuação e espaçamento.',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'tip',
|
|
146
|
+
title: 'A regra que realmente ajuda',
|
|
147
|
+
html: 'Escreva o snippet para que a promessa importante sobreviva às reticências. Coloque o tipo de página, a intenção de pesquisa e o motivo mais forte para clicar antes do limite de píxeis. Os nomes de marca são úteis, mas não devem empurrar o benefício principal para fora de vista.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'title',
|
|
151
|
+
text: 'O que o contador de píxeis está a medir',
|
|
152
|
+
level: 3,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: 'table',
|
|
156
|
+
headers: ['Elemento', 'O que importa', 'Como usar o resultado'],
|
|
157
|
+
rows: [
|
|
158
|
+
['Tag title', 'Largura renderizada em píxeis, não a contagem bruta de caracteres', 'Mantenha a palavra-chave principal e a promessa de clique visíveis antes do truncamento.'],
|
|
159
|
+
['URL visível', 'Confiança visual e clareza do tópico', 'Use um caminho legível que reforce o destino do resultado.'],
|
|
160
|
+
['Meta description', 'Uma área de snippet mais ampla com comportamento dependente da consulta', 'Coloque o benefício em primeiro plano, pois o Google pode encurtá-la ou reescrevê-la.'],
|
|
161
|
+
['Modo dispositivo', 'Os cartões de desktop e mobile podem parecer diferentes', 'Verifique ambos antes de publicar metadados de páginas importantes.'],
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
type: 'title',
|
|
166
|
+
text: 'Porque é que os limites de caracteres são um mau hábito de SEO',
|
|
167
|
+
level: 3,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'paragraph',
|
|
171
|
+
html: 'O conselho tradicional como "mantenha os títulos abaixo dos 60 caracteres" é conveniente, mas esconde o verdadeiro problema. Letras largas como W e M, palavras em maiúsculas, separadores, números e nomes de marca longos consomem todos espaços diferentes. A medição em píxeis torna o compromisso visível de imediato: pode ver se uma frase merece o seu lugar ou rouba espaço a uma mensagem mais forte.',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: 'title',
|
|
175
|
+
text: 'Um fluxo de trabalho prático para melhores snippets',
|
|
176
|
+
level: 3,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'list',
|
|
180
|
+
items: [
|
|
181
|
+
'<strong>Comece pela intenção:</strong> descreva o que o utilizador obtém, não apenas como a página se chama.',
|
|
182
|
+
'<strong>Teste o título completo:</strong> cole-o no simulador e observe a barra antes de publicar.',
|
|
183
|
+
'<strong>Remova palavras fracas:</strong> se a barra ficar vermelha, elimine o enchimento antes de cortar termos valiosos.',
|
|
184
|
+
'<strong>Verifique as reticências:</strong> se a pré-visualização truncada perder sentido, reescreva o título em vez de aceitar o corte.',
|
|
185
|
+
'<strong>Repita para a descrição:</strong> certifique-se de que a primeira frase transmite a proposta de valor por si só.',
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: 'diagnostic',
|
|
190
|
+
variant: 'info',
|
|
191
|
+
title: 'Quando a barra fica vermelha',
|
|
192
|
+
html: 'Uma barra vermelha não é um aviso de penalização. Significa que o texto atual é mais largo do que o alvo visual selecionado, pelo que o simulador o trunca com pontos. Trate isso como um sinal editorial: decida se as palavras ocultas são dispensáveis ou se o snippet precisa de uma estrutura mais afiada.',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
type: 'title',
|
|
196
|
+
text: 'Limites, reescritas e expectativas realistas',
|
|
197
|
+
level: 3,
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
type: 'paragraph',
|
|
201
|
+
html: 'Nenhum simulador pode garantir o snippet exato que o Google mostrará. O Google pode reescrever links de título, colocar termos da consulta em negrito, escolher texto da página em vez da meta description ou mostrar snippets diferentes para pesquisas diferentes. Esta ferramenta é mais útil como uma etapa rápida de redação e controlo de qualidade: deteta transbordos visuais óbvios antes de a página chegar à produção.',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
type: 'summary',
|
|
205
|
+
title: 'Melhor utilização deste simulador SERP',
|
|
206
|
+
items: [
|
|
207
|
+
'Use a barra de píxeis para detetar transbordos visuais antes de publicar metadados.',
|
|
208
|
+
'Mantenha a intenção de pesquisa principal e a promessa de clique visíveis antes de qualquer reticência.',
|
|
209
|
+
'Obtenha metadados de URLs que permitam CORS e edite o resultado manualmente quando necessário.',
|
|
210
|
+
'Considere a pré-visualização como um guia de redação, pois o Google ainda pode reescrever snippets por consulta.',
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { SerpPixelSimulatorUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
5
|
+
|
|
6
|
+
const slug = 'simulyator-serp-schetchik-pikselej';
|
|
7
|
+
const title = 'Симулятор SERP и Счётчик Пикселей для SEO';
|
|
8
|
+
const description = 'Предпросматривайте поисковые сниппеты в стиле Google в реальном времени, измеряйте ширину заголовка и мета-описания в пикселях и точно видите, где ваш текст будет обрезан.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Введите тег title',
|
|
13
|
+
text: 'Введите или вставьте заголовок страницы, который хотите протестировать. Предпросмотр SERP и счётчик пикселей обновляются при каждом нажатии клавиши.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Добавьте видимый URL',
|
|
17
|
+
text: 'Используйте реалистичный домен и путь, чтобы сниппет был похож на результат, который просканирует пользователь.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Напишите мета-описание',
|
|
21
|
+
text: 'Добавьте текст описания и следите за полосой пикселей. Когда она превышает рекомендуемую визуальную ширину, предпросмотр обрезает её многоточием.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Переключайтесь между компьютером и мобильным',
|
|
25
|
+
text: 'Сравните отображение заголовка с шириной карточки на компьютере или мобильном устройстве перед публикацией метаданных.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: 'Почему считать пиксели, а не символы для SEO-заголовков?',
|
|
32
|
+
answer: 'Карточки результатов Google ограничены визуальной шириной. Заголовок с большим количеством узких букв может вместить больше символов, чем заголовок с широкими буквами, прописными или жирно выглядящими глифами. Измерение в пикселях даёт более точное представление о видимом результате.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: 'Гарантирует ли это, как именно Google обрежет мой сниппет?',
|
|
36
|
+
answer: 'Нет. Google может переписывать ссылки заголовков и сниппеты, а отображение может варьироваться в зависимости от запроса, устройства, языка и экспериментов. Инструмент задуман как практическое визуальное руководство для написания метаданных, которые с меньшей вероятностью будут обрезаны.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: 'Какие лимиты пикселей использует симулятор?',
|
|
40
|
+
answer: 'Лимит заголовка по умолчанию для компьютера составляет 580 пикселей, для мобильных - 600 пикселей, а лимит мета-описания - 920 пикселей. Это цели написания, а не официальные лимиты Google.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: 'Почему предпросмотр добавляет многоточие?',
|
|
44
|
+
answer: 'Когда измеренный текст превышает доступную ширину в пикселях, симулятор обрезает строку по последнему вмещающемуся символу и добавляет три точки, имитируя практическое поведение, необходимое SEO-командам для обнаружения потери смысла.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: SerpPixelSimulatorUI = {
|
|
49
|
+
titleLabel: 'Тег title',
|
|
50
|
+
titlePlaceholder: 'GameBob | Независимая Студия Разработки',
|
|
51
|
+
urlLabel: 'Видимый URL',
|
|
52
|
+
urlPlaceholder: 'https://www.gamebob.dev/ru/',
|
|
53
|
+
descriptionLabel: 'Мета-описание',
|
|
54
|
+
descriptionPlaceholder: 'Откройте для себя нашу коллекцию инструментов и игр, созданных для улучшения вашего цифрового рабочего процесса и развлечений.',
|
|
55
|
+
deviceLabel: 'Режим предпросмотра',
|
|
56
|
+
desktopLabel: 'Компьютер',
|
|
57
|
+
mobileLabel: 'Мобильный',
|
|
58
|
+
titlePixelsLabel: 'Ширина заголовка',
|
|
59
|
+
descriptionPixelsLabel: 'Ширина описания',
|
|
60
|
+
charactersLabel: 'символов',
|
|
61
|
+
previewLabel: 'Предпросмотр в стиле Google',
|
|
62
|
+
tooLongLabel: 'Слишком широкий',
|
|
63
|
+
goodLabel: 'Помещается',
|
|
64
|
+
emptyTitle: 'Ваш заголовок появится здесь',
|
|
65
|
+
emptyDescription: 'Предпросмотр вашего мета-описания появится здесь по мере ввода.',
|
|
66
|
+
defaultTitle: 'GameBob | Независимая Студия Разработки',
|
|
67
|
+
defaultUrl: 'https://www.gamebob.dev/ru/',
|
|
68
|
+
defaultDescription: 'Откройте для себя нашу коллекцию инструментов и игр, созданных для улучшения вашего цифрового рабочего процесса и развлечений.',
|
|
69
|
+
fallbackUrl: 'пример.рф',
|
|
70
|
+
fallbackFaviconText: 'G',
|
|
71
|
+
pixelUnit: 'px',
|
|
72
|
+
ellipsis: '...',
|
|
73
|
+
fetchButtonLabel: 'Загрузить',
|
|
74
|
+
fetchLoadingLabel: 'Загрузка...',
|
|
75
|
+
fetchSuccessLabel: 'Метаданные загружены с URL.',
|
|
76
|
+
fetchCorsError: 'Браузер не смог прочитать эту страницу. Возможно, она заблокирована CORS, перенаправлением, смешанным содержимым или сетевым правилом. Вы всё ещё можете вставить или отредактировать метаданные вручную.',
|
|
77
|
+
fetchInvalidUrlError: 'Введите корректный URL перед загрузкой метаданных.',
|
|
78
|
+
fetchNoMetadataError: 'Страница загружена, но заголовок или мета-описание не найдены.',
|
|
79
|
+
fetchGenericError: 'Не удалось загрузить метаданные с этого URL. Проверьте адрес или заполните поля вручную.',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
83
|
+
'@context': 'https://schema.org',
|
|
84
|
+
'@type': 'FAQPage',
|
|
85
|
+
mainEntity: faq.map((item) => ({
|
|
86
|
+
'@type': 'Question',
|
|
87
|
+
name: item.question,
|
|
88
|
+
acceptedAnswer: {
|
|
89
|
+
'@type': 'Answer',
|
|
90
|
+
text: item.answer,
|
|
91
|
+
},
|
|
92
|
+
})),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const howToSchema: WithContext<HowTo> = {
|
|
96
|
+
'@context': 'https://schema.org',
|
|
97
|
+
'@type': 'HowTo',
|
|
98
|
+
name: title,
|
|
99
|
+
description,
|
|
100
|
+
step: howTo.map((step, index) => ({
|
|
101
|
+
'@type': 'HowToStep',
|
|
102
|
+
position: index + 1,
|
|
103
|
+
name: step.name,
|
|
104
|
+
text: step.text,
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
109
|
+
'@context': 'https://schema.org',
|
|
110
|
+
'@type': 'SoftwareApplication',
|
|
111
|
+
name: title,
|
|
112
|
+
description,
|
|
113
|
+
applicationCategory: 'BusinessApplication',
|
|
114
|
+
operatingSystem: 'Any',
|
|
115
|
+
offers: {
|
|
116
|
+
'@type': 'Offer',
|
|
117
|
+
price: '0',
|
|
118
|
+
priceCurrency: 'EUR',
|
|
119
|
+
},
|
|
120
|
+
inLanguage: 'ru',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const content: ToolLocaleContent<SerpPixelSimulatorUI> = {
|
|
124
|
+
slug,
|
|
125
|
+
title,
|
|
126
|
+
description,
|
|
127
|
+
ui,
|
|
128
|
+
faqTitle: 'Часто задаваемые вопросы о симуляторе SERP',
|
|
129
|
+
faq,
|
|
130
|
+
bibliographyTitle: 'Документация по поисковым результатам',
|
|
131
|
+
bibliography,
|
|
132
|
+
howTo,
|
|
133
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
134
|
+
seo: [
|
|
135
|
+
{
|
|
136
|
+
type: 'title',
|
|
137
|
+
text: 'Перестаньте гадать, как будет выглядеть ваш результат в Google',
|
|
138
|
+
level: 2,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'paragraph',
|
|
142
|
+
html: 'Тег title может выглядеть идеально в таблице и всё равно провалиться в поисковой выдаче. Google резервирует пространство не по количеству символов; он отображает текст внутри визуальной карточки. Это означает, что <strong>GameBob | Независимая Студия Разработки</strong> и другой заголовок с тем же количеством символов могут занимать очень разную ширину в зависимости от букв, регистра, пунктуации и пробелов.',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'tip',
|
|
146
|
+
title: 'Правило, которое действительно помогает',
|
|
147
|
+
html: 'Пишите сниппет так, чтобы важное обещание пережило многоточие. Разместите тип страницы, поисковое намерение и самую сильную причину кликнуть до пиксельного лимита. Названия брендов полезны, но они не должны вытеснять главное преимущество из поля зрения.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'title',
|
|
151
|
+
text: 'Что измеряет счётчик пикселей',
|
|
152
|
+
level: 3,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: 'table',
|
|
156
|
+
headers: ['Элемент', 'Что важно', 'Как использовать результат'],
|
|
157
|
+
rows: [
|
|
158
|
+
['Тег title', 'Отображаемая ширина в пикселях, а не количество символов', 'Держите основное ключевое слово и обещание клика видимыми до обрезки.'],
|
|
159
|
+
['Видимый URL', 'Визуальное доверие и ясность темы', 'Используйте читаемый путь, который подкрепляет, куда ведёт результат.'],
|
|
160
|
+
['Мета-описание', 'Более широкая область сниппета с поведением, зависящим от запроса', 'Выносите преимущество вперёд, поскольку Google может сократить или переписать его.'],
|
|
161
|
+
['Режим устройства', 'Карточки на компьютере и мобильном могут выглядеть по-разному', 'Проверьте оба режима перед публикацией метаданных для важных страниц.'],
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
type: 'title',
|
|
166
|
+
text: 'Почему ограничения по символам - плохая SEO-привычка',
|
|
167
|
+
level: 3,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'paragraph',
|
|
171
|
+
html: 'Традиционный совет вроде "держите заголовки до 60 символов" удобен, но скрывает реальную проблему. Широкие буквы, такие как W и M, заглавные буквы, разделители, цифры и длинные названия брендов занимают разное пространство. Измерение в пикселях немедленно делает компромисс видимым: вы можете увидеть, заслуживает ли фраза своего места или крадёт пространство у более сильного сообщения.',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: 'title',
|
|
175
|
+
text: 'Практический рабочий процесс для лучших сниппетов',
|
|
176
|
+
level: 3,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'list',
|
|
180
|
+
items: [
|
|
181
|
+
'<strong>Начните с намерения:</strong> опишите, что получает пользователь, а не только как называется страница.',
|
|
182
|
+
'<strong>Протестируйте полный заголовок:</strong> вставьте его в симулятор и следите за полосой перед публикацией.',
|
|
183
|
+
'<strong>Уберите слабые слова:</strong> если полоса стала красной, удалите наполнители, прежде чем обрезать ценные термины.',
|
|
184
|
+
'<strong>Проверьте многоточие:</strong> если обрезанный предпросмотр теряет смысл, перепишите заголовок, а не принимайте обрезку.',
|
|
185
|
+
'<strong>Повторите для описания:</strong> убедитесь, что первое предложение само по себе несёт ценностное предложение.',
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: 'diagnostic',
|
|
190
|
+
variant: 'info',
|
|
191
|
+
title: 'Когда полоса становится красной',
|
|
192
|
+
html: 'Красная полоса не является предупреждением о штрафе. Она означает, что текущий текст шире выбранной визуальной цели, поэтому симулятор обрезает его точками. Относитесь к этому как к редакционному сигналу: решите, можно ли пожертвовать скрытыми словами, или сниппет нуждается в более чёткой структуре.',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
type: 'title',
|
|
196
|
+
text: 'Ограничения, переписывания и реалистичные ожидания',
|
|
197
|
+
level: 3,
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
type: 'paragraph',
|
|
201
|
+
html: 'Ни один симулятор не может гарантировать точный сниппет, который покажет Google. Google может переписывать ссылки заголовков, выделять жирным термины запроса, выбирать текст страницы вместо мета-описания или показывать разные сниппеты для разных поисковых запросов. Этот инструмент лучше всего использовать как быстрый этап написания и контроля качества: он выявляет явные визуальные переполнения до того, как страница попадёт в продакшн.',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
type: 'summary',
|
|
205
|
+
title: 'Наилучшее использование этого симулятора SERP',
|
|
206
|
+
items: [
|
|
207
|
+
'Используйте полосу пикселей для обнаружения визуальных переполнений перед публикацией метаданных.',
|
|
208
|
+
'Держите основное поисковое намерение и обещание клика видимыми до любого многоточия.',
|
|
209
|
+
'Загружайте метаданные с URL, которые разрешают CORS, затем редактируйте результат вручную при необходимости.',
|
|
210
|
+
'Рассматривайте предпросмотр как руководство по написанию, поскольку Google всё ещё может переписывать сниппеты под каждый запрос.',
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { SerpPixelSimulatorUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
5
|
+
|
|
6
|
+
const slug = 'serp-pixel-simulator-raknare';
|
|
7
|
+
const title = 'SERP Simulator och SEO Pixelräknare';
|
|
8
|
+
const description = 'Förhandsgranska Google-liknande söksnuttar i realtid, mät bredden på titel och metabeskrivning i pixlar och se exakt var din text kommer att kapas.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Ange title-taggen',
|
|
13
|
+
text: 'Skriv eller klistra in sidtiteln du vill testa. SERP-förhandsgranskningen och pixelmätaren uppdateras vid varje tangenttryckning.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Lägg till den synliga URL:en',
|
|
17
|
+
text: 'Använd en realistisk domän och sökväg så att snutten liknar resultatet en sökare skulle skanna.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Skriv metabeskrivningen',
|
|
21
|
+
text: 'Lägg till beskrivningstexten och titta på pixelfältet. När den överskrider den rekommenderade visuella bredden kapar förhandsgranskningen den med ellipser.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Växla mellan dator och mobil',
|
|
25
|
+
text: 'Jämför titelrenderingen med kortbredden för dator eller mobil innan du publicerar metadata.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: 'Varför räkna pixlar istället för tecken för SEO-titlar?',
|
|
32
|
+
answer: 'Googles sökresultatkort begränsas av visuell bredd. En titel med många smala bokstäver kan rymma fler tecken än en titel med breda bokstäver, versaler eller fetstilta glyfer. Pixelmätning ger en mer exakt förhandsvisning av det synliga resultatet.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: 'Garanterar detta exakt hur Google kommer att kapa min snutt?',
|
|
36
|
+
answer: 'Nej. Google kan skriva om titellänkar och snuttar, och renderingen kan variera beroende på sökfråga, enhet, språk och experiment. Verktyget är utformat som en praktisk visuell vägledning för att skriva metadata som är mindre troligt att kapas.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: 'Vilka pixelgränser använder simulatorn?',
|
|
40
|
+
answer: 'Standardgränsen för titel på dator är 580 px, på mobil 600 px och gränsen för metabeskrivning är 920 px. Dessa är skrivmål, inte officiella Google-gränser.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: 'Varför lägger förhandsgranskningen till ellipser?',
|
|
44
|
+
answer: 'När den uppmätta texten överskrider den tillgängliga pixelbredden kapar simulatorn strängen vid det sista passande tecknet och lägger till tre punkter, vilket matchar det praktiska beteende SEO-team behöver för att upptäcka meningsförlust.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: SerpPixelSimulatorUI = {
|
|
49
|
+
titleLabel: 'Title-tagg',
|
|
50
|
+
titlePlaceholder: 'GameBob | Oberoende Utvecklingsstudio',
|
|
51
|
+
urlLabel: 'Synlig URL',
|
|
52
|
+
urlPlaceholder: 'https://www.gamebob.dev/sv/',
|
|
53
|
+
descriptionLabel: 'Metabeskrivning',
|
|
54
|
+
descriptionPlaceholder: 'Upptäck vår samling av verktyg och spel som är utformade för att lyfta ditt digitala arbetsflöde och underhållning.',
|
|
55
|
+
deviceLabel: 'Förhandsgranskningsläge',
|
|
56
|
+
desktopLabel: 'Dator',
|
|
57
|
+
mobileLabel: 'Mobil',
|
|
58
|
+
titlePixelsLabel: 'Titelbredd',
|
|
59
|
+
descriptionPixelsLabel: 'Beskrivningsbredd',
|
|
60
|
+
charactersLabel: 'tecken',
|
|
61
|
+
previewLabel: 'Live-förhandsgranskning i Google-stil',
|
|
62
|
+
tooLongLabel: 'För bred',
|
|
63
|
+
goodLabel: 'Passar',
|
|
64
|
+
emptyTitle: 'Din titel visas här',
|
|
65
|
+
emptyDescription: 'Förhandsgranskningen av din metabeskrivning visas här medan du skriver.',
|
|
66
|
+
defaultTitle: 'GameBob | Oberoende Utvecklingsstudio',
|
|
67
|
+
defaultUrl: 'https://www.gamebob.dev/sv/',
|
|
68
|
+
defaultDescription: 'Upptäck vår samling av verktyg och spel som är utformade för att lyfta ditt digitala arbetsflöde och underhållning.',
|
|
69
|
+
fallbackUrl: 'exempel.se',
|
|
70
|
+
fallbackFaviconText: 'G',
|
|
71
|
+
pixelUnit: 'px',
|
|
72
|
+
ellipsis: '...',
|
|
73
|
+
fetchButtonLabel: 'Hämta',
|
|
74
|
+
fetchLoadingLabel: 'Hämtar...',
|
|
75
|
+
fetchSuccessLabel: 'Metadata laddades från URL:en.',
|
|
76
|
+
fetchCorsError: 'Webbläsaren kunde inte läsa denna sida. Den kan vara blockerad av CORS, en omdirigering, blandat innehåll eller en nätverksregel. Du kan fortfarande klistra in eller redigera metadata manuellt.',
|
|
77
|
+
fetchInvalidUrlError: 'Ange en giltig URL innan du hämtar metadata.',
|
|
78
|
+
fetchNoMetadataError: 'Sidan hämtades, men ingen titel eller metabeskrivning hittades.',
|
|
79
|
+
fetchGenericError: 'Metadata kunde inte hämtas från denna URL. Kontrollera adressen eller fyll i fälten manuellt.',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
83
|
+
'@context': 'https://schema.org',
|
|
84
|
+
'@type': 'FAQPage',
|
|
85
|
+
mainEntity: faq.map((item) => ({
|
|
86
|
+
'@type': 'Question',
|
|
87
|
+
name: item.question,
|
|
88
|
+
acceptedAnswer: {
|
|
89
|
+
'@type': 'Answer',
|
|
90
|
+
text: item.answer,
|
|
91
|
+
},
|
|
92
|
+
})),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const howToSchema: WithContext<HowTo> = {
|
|
96
|
+
'@context': 'https://schema.org',
|
|
97
|
+
'@type': 'HowTo',
|
|
98
|
+
name: title,
|
|
99
|
+
description,
|
|
100
|
+
step: howTo.map((step, index) => ({
|
|
101
|
+
'@type': 'HowToStep',
|
|
102
|
+
position: index + 1,
|
|
103
|
+
name: step.name,
|
|
104
|
+
text: step.text,
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
109
|
+
'@context': 'https://schema.org',
|
|
110
|
+
'@type': 'SoftwareApplication',
|
|
111
|
+
name: title,
|
|
112
|
+
description,
|
|
113
|
+
applicationCategory: 'BusinessApplication',
|
|
114
|
+
operatingSystem: 'Any',
|
|
115
|
+
offers: {
|
|
116
|
+
'@type': 'Offer',
|
|
117
|
+
price: '0',
|
|
118
|
+
priceCurrency: 'EUR',
|
|
119
|
+
},
|
|
120
|
+
inLanguage: 'sv',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const content: ToolLocaleContent<SerpPixelSimulatorUI> = {
|
|
124
|
+
slug,
|
|
125
|
+
title,
|
|
126
|
+
description,
|
|
127
|
+
ui,
|
|
128
|
+
faqTitle: 'Vanliga frågor om SERP simulatorn',
|
|
129
|
+
faq,
|
|
130
|
+
bibliographyTitle: 'Dokumentation om sökresultat',
|
|
131
|
+
bibliography,
|
|
132
|
+
howTo,
|
|
133
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
134
|
+
seo: [
|
|
135
|
+
{
|
|
136
|
+
type: 'title',
|
|
137
|
+
text: 'Sluta gissa hur ditt Google-resultat kommer att se ut',
|
|
138
|
+
level: 2,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'paragraph',
|
|
142
|
+
html: 'En title-tagg kan se perfekt ut i ett kalkylblad och ändå misslyckas i sökresultatet. Google reserverar inte utrymme efter teckenantal; det renderar text inuti ett visuellt kort. Det betyder att <strong>GameBob | Oberoende Utvecklingsstudio</strong> och en annan titel med samma antal tecken kan uppta mycket olika bredder beroende på bokstäverna, versaler, interpunktion och mellanrum.',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'tip',
|
|
146
|
+
title: 'Regeln som verkligen hjälper',
|
|
147
|
+
html: 'Skriv snutten så att det viktiga löftet överlever ellipsen. Placera sidtypen, sökintentionen och den starkaste anledningen att klicka före pixelgränsen. Varumärkesnamn är användbara, men de ska inte trycka ut huvudfördelen ur sikte.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'title',
|
|
151
|
+
text: 'Vad pixelräknaren mäter',
|
|
152
|
+
level: 3,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: 'table',
|
|
156
|
+
headers: ['Element', 'Vad som spelar roll', 'Hur du använder resultatet'],
|
|
157
|
+
rows: [
|
|
158
|
+
['Title-tagg', 'Renderad bredd i pixlar, inte antal tecken', 'Håll det primära nyckelordet och klicklöftet synliga före kapningen.'],
|
|
159
|
+
['Synlig URL', 'Visuellt förtroende och ämnestydehet', 'Använd en läsbar sökväg som förstärker vart resultatet leder.'],
|
|
160
|
+
['Metabeskrivning', 'Ett bredare snuttområde med frågeberoende beteende', 'Placera fördelen först eftersom Google kan förkorta eller skriva om den.'],
|
|
161
|
+
['Enhetsläge', 'Dator- och mobilkort kan kännas olika', 'Kontrollera båda innan du publicerar metadata för viktiga sidor.'],
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
type: 'title',
|
|
166
|
+
text: 'Varför teckengränser är en svag SEO-vana',
|
|
167
|
+
level: 3,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'paragraph',
|
|
171
|
+
html: 'Traditionella råd som "håll titlar under 60 tecken" är bekväma, men döljer det verkliga problemet. Breda bokstäver som W och M, versaler, avgränsare, siffror och långa varumärkesnamn tar alla olika utrymme. Pixelmätning gör avvägningen omedelbart synlig: du kan se om en fras förtjänar sin plats eller stjäl utrymme från ett starkare budskap.',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: 'title',
|
|
175
|
+
text: 'Ett praktiskt arbetsflöde för bättre snuttar',
|
|
176
|
+
level: 3,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'list',
|
|
180
|
+
items: [
|
|
181
|
+
'<strong>Börja med intentionen:</strong> beskriv vad användaren får, inte bara vad sidan heter.',
|
|
182
|
+
'<strong>Testa hela titeln:</strong> klistra in den i simulatorn och titta på fältet innan publicering.',
|
|
183
|
+
'<strong>Ta bort svaga ord:</strong> om fältet blir rött, ta bort utfyllnadsord innan du kapar värdefulla termer.',
|
|
184
|
+
'<strong>Kontrollera ellipsen:</strong> om den kapade förhandsgranskningen tappar mening, skriv om titeln istället för att acceptera kapningen.',
|
|
185
|
+
'<strong>Upprepa för beskrivningen:</strong> se till att den första meningen bär värdeerbjudandet på egen hand.',
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: 'diagnostic',
|
|
190
|
+
variant: 'info',
|
|
191
|
+
title: 'När fältet blir rött',
|
|
192
|
+
html: 'Ett rött fält är inte en straffvarning. Det betyder att den aktuella texten är bredare än det valda visuella målet, så simulatorn kapar den med punkter. Behandla det som en redaktionell signal: avgör om de dolda orden är onödiga eller om snutten behöver en skarpare struktur.',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
type: 'title',
|
|
196
|
+
text: 'Begränsningar, omskrivningar och realistiska förväntningar',
|
|
197
|
+
level: 3,
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
type: 'paragraph',
|
|
201
|
+
html: 'Ingen simulator kan garantera den exakta snutt Google kommer att visa. Google kan skriva om titellänkar, fetstilta söktermer, välja sidtext istället för metabeskrivningen eller visa olika snuttar för olika sökningar. Detta verktyg är bäst lämpat som ett snabbt skriv- och QA-steg: det fångar uppenbar visuell överskridning innan sidan når produktion.',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
type: 'summary',
|
|
205
|
+
title: 'Bästa användning av denna SERP simulator',
|
|
206
|
+
items: [
|
|
207
|
+
'Använd pixelfältet för att fånga visuell överskridning innan du publicerar metadata.',
|
|
208
|
+
'Håll den huvudsakliga sökintentionen och klicklöftet synliga före någon ellips.',
|
|
209
|
+
'Hämta metadata från URL:er som tillåter CORS och redigera sedan resultatet manuellt vid behov.',
|
|
210
|
+
'Betrakta förhandsgranskningen som en skrivguide, eftersom Google fortfarande kan skriva om snuttar per sökfråga.',
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|