Skip to content

Commit cb4b377

Browse files
[no-issue] fix semrush redirects i18n json files (#1468)
* wip: rgx with # * fix: 1282 processedCount update links 30x * wip: adjust to scan src/i18n with simple quote * fix: adjust 30x link url * chore: disable continue console.log * fix: async correction to process file i18n * fix: replace 30x links to the 200
1 parent 8a3fe28 commit cb4b377

6 files changed

Lines changed: 155 additions & 144 deletions

File tree

Lines changed: 101 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,121 @@
1-
import { parse } from 'csv-parse'
2-
import fs from 'fs'
3-
import { createReadStream } from 'fs'
4-
import path from 'path'
1+
import { parse } from 'csv-parse';
2+
import { promises as fs } from 'fs';
3+
import { createReadStream } from 'fs';
4+
import path from 'path';
55

6-
let counterFoundLinks = 0
7-
let PATH = {
8-
csv: './www.azion.com_permanent_redirects_20241225.csv',
9-
i18n: `${process.env.OLDPWD}/src/i18n`
10-
}
11-
const wwwazioncom = 'https://www.azion.com'
6+
let counterFoundLinks = 0;
7+
const PATH = {
8+
csv: './www.azion.com_permanent_redirects_20241225.csv',
9+
i18n: `${process.env.OLDPWD}/src/i18n`
10+
};
11+
const wwwazioncom = 'https://www.azion.com';
12+
const removeLangFromUrl = (url) => url.replace('/pt-br', '').replace('/en', '');
13+
const removeHostFromUrl = (url) => url.replace(wwwazioncom, '');
14+
const removeHostAndLangFromUrl = (url) => removeLangFromUrl(removeHostFromUrl(url));
15+
const isFromRoot = (url) => url === wwwazioncom;
1216

1317
async function loadRedirects() {
14-
const redirects = []
15-
const parser = createReadStream(PATH.csv).pipe(
16-
parse({
17-
columns: true,
18-
skip_empty_lines: true,
19-
})
20-
)
21-
22-
for await (const record of parser) {
23-
redirects.push({
24-
page: record.page,
25-
initialUrl: record.initial_url,
26-
destinationUrl: record.destination_url,
27-
statusCode: record.status,
28-
discovered: record.discovered
29-
})
30-
}
18+
const redirects = [];
19+
const parser = createReadStream(PATH.csv).pipe(
20+
parse({
21+
columns: true,
22+
skip_empty_lines: true,
23+
})
24+
);
3125

32-
return redirects
26+
try {
27+
for await (const record of parser) {
28+
redirects.push({
29+
page: record.page,
30+
initialUrl: record.initial_url,
31+
destinationUrl: record.destination_url,
32+
statusCode: record.status,
33+
discovered: record.discovered
34+
});
35+
}
36+
return redirects;
37+
} catch (error) {
38+
throw new Error(`Error loading redirects: ${error.message}`);
39+
}
3340
}
3441

3542
async function processFile(filePath, redirects) {
36-
fs.readFile(filePath, async (err, content) => {
37-
if(err) {
38-
console.error(err)
39-
return
40-
}
43+
try {
44+
const content = await fs.readFile(filePath, 'utf-8');
45+
let newContent = content;
46+
let fileModified = false;
4147

42-
const utf8Content = Buffer.from(content).toString('utf-8')
48+
for (const item of redirects) {
49+
const url30x = isFromRoot(item.initialUrl) ? wwwazioncom : removeHostAndLangFromUrl(item.initialUrl);
50+
const url200 = removeHostAndLangFromUrl(item.destinationUrl);
51+
const isRoot = isFromRoot(url30x);
52+
const rgx = new RegExp(`'${url30x}'`, 'g');
53+
const contentMatch = newContent.match(rgx);
4354

44-
for (const item of redirects) {
45-
const url30x = item.initialUrl === wwwazioncom ? wwwazioncom : item.initialUrl.replace(wwwazioncom, '')
46-
const url200 = item.destinationUrl.replace(wwwazioncom, '')
47-
const isRoot = url30x === wwwazioncom
48-
const rgx = new RegExp(`${url30x}`, 'g')
49-
const contentMatch = utf8Content.match(rgx)
55+
if (!contentMatch) continue;
5056

51-
if(!contentMatch) {
52-
// console.log(`NOT MATCH `, `${rgx} : ${url30x}`)
53-
continue
54-
} else {
55-
console.log(`MATCH`, `${rgx} : ${url30x}`)
56-
}
57-
counterFoundLinks++
57+
counterFoundLinks++;
58+
fileModified = true;
5859

59-
console.log(`{
60-
isRoot: ${isRoot},
61-
file: ${filePath},
62-
rgx: ${rgx},
63-
url30x: ${url30x},
64-
url200: ${url200},
65-
contentMatch: ${contentMatch},
66-
contentMatchCount: ${contentMatch.length},
67-
processedCount: ${counterFoundLinks}
68-
}`)
60+
console.log({
61+
isRoot,
62+
file: filePath,
63+
rgx: rgx.toString(),
64+
url30x,
65+
url200,
66+
contentMatchCount: contentMatch.length,
67+
processedCount: counterFoundLinks
68+
});
6969

70-
const newContent = utf8Content.replace(isRoot ? /'https\:\/\/www\.azion\.com\/'/ : rgx, `'${url200}'`)
71-
await fs.writeFile(filePath, newContent, async (err) => {
72-
if(err) throw err
73-
console.log(`[OK] ${filePath} updated`)
74-
})
75-
}
76-
})
77-
}
70+
newContent = newContent.replace(
71+
isRoot ? /'https\:\/\/www\.azion\.com\/'/ : rgx,
72+
`'${url200}'`
73+
);
74+
}
7875

79-
function processDirectory(directory, redirects) {
80-
fs.readdir(directory, { withFileTypes: true }, (err, entries) => {
81-
if (err) {
82-
console.error('[ERROR] directory can not be readed:', err)
83-
return
84-
}
76+
if (fileModified) {
77+
await fs.writeFile(filePath, newContent);
78+
console.log(`[OK] ${filePath} updated`);
79+
}
80+
} catch (error) {
81+
console.error(`[ERROR] Processing file ${filePath}:`, error);
82+
}
83+
}
8584

86-
for (const entry of entries) {
87-
const fullPath = path.join(directory, entry.name)
85+
async function processDirectory(directory, redirects) {
86+
try {
87+
const entries = await fs.readdir(directory, { withFileTypes: true });
88+
const processingPromises = entries.map(async (entry) => {
89+
const fullPath = path.join(directory, entry.name);
90+
91+
if (entry.isDirectory()) {
92+
return processDirectory(fullPath, redirects);
93+
} else if (entry.isFile()) {
94+
return processFile(fullPath, redirects);
95+
} else {
96+
console.warn(`[WARN] ${fullPath} is not a file or directory`);
97+
}
98+
});
8899

89-
if(entry.isDirectory()) {
90-
processDirectory(fullPath, redirects)
91-
} else if (entry.isFile()) {
92-
processFile(fullPath, redirects)
93-
} else {
94-
console.error(`[ERROR] ${fullPath} is not a file or directory`)
95-
}
96-
}
97-
})
100+
await Promise.all(processingPromises);
101+
} catch (error) {
102+
console.error(`[ERROR] Processing directory ${directory}:`, error);
103+
}
98104
}
99105

100106
async function main() {
101-
try {
102-
const redirects = await loadRedirects()
103-
processDirectory(PATH.i18n, redirects)
104-
} catch (error) {
105-
console.error('[ERROR] ', error)
106-
process.exit(1)
107-
}
107+
try {
108+
console.log('[INFO] Loading redirects...');
109+
const redirects = await loadRedirects();
110+
console.log(`[INFO] Loaded ${redirects.length} redirects`);
111+
112+
console.log('[INFO] Starting directory processing...');
113+
await processDirectory(PATH.i18n, redirects);
114+
console.log(`[INFO] Processing complete. Found and replaced ${counterFoundLinks} links`);
115+
} catch (error) {
116+
console.error('[ERROR] Fatal error:', error);
117+
process.exit(1);
118+
}
108119
}
109120

110-
main()
121+
main();

src/i18n/en/graphqlMenu.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
{ text: 'Features',header: true, anchor: true, type: 'learn', slug: '/documentation/devtools/graphql-api/features/', key: 'features' },
2222

2323
{ text: 'Fields', header: true, key: 'fields', type: 'learn', items: [
24-
{ text: 'Real-Time Events GQL', slug: '/documentation/products/graphql-api/features/events-fields/', key: 'fields/Events' },
25-
{ text: 'Real-Time Metrics GQL', slug: '/documentation/products/graphql-api/features/metrics-fields/', key: 'fields/Metrics' },
24+
{ text: 'Real-Time Events GQL', slug: '/documentation/devtools/graphql-api/features/gql-real-time-events-fields/', key: 'fields/Events' },
25+
{ text: 'Real-Time Metrics GQL', slug: '/documentation/devtools/graphql-api/features/gql-real-time-metrics-fields/', key: 'fields/Metrics' },
2626
{ text: 'Billing GQL', slug: '/documentation/devtools/graphql-api/features/gql-billing-fields/', key: 'fields/Billing' },
2727
{ text: 'Accounting GQL', slug: '/documentation/devtools/graphql-api/features/gql-accounting-fields/', key: 'fields/Accounting' },
2828
]

src/i18n/en/nav.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export default [
5151
{
5252
text: 'Developer tools', header: true, type: 'learn', key: 'developerTools', hasLabel: 'menu.addResources', items: [
5353
{ text: 'API', header: true, anchor: true, type: 'learn', key: 'devtools/api', slug: '/documentation/products/overview-azion-api/' },
54-
{ text: 'CLI', header: true, anchor: true, type: 'learn', key: 'devtools/cli', slug: '/documentation/products/cli/' },
54+
{ text: 'CLI', header: true, anchor: true, type: 'learn', key: 'devtools/cli', slug: '/documentation/products/azion-cli/overview/' },
5555
{ text: 'API GraphQL Playground', header: true, anchor: true, type: 'learn', slug: '/documentation/products/devtools/graphql-playground/', key: 'devtools/graphQLplayground' },
5656
{ text: 'SDK', header: true, anchor: true, type: 'learn', slug: '/documentation/devtools/sdk/go/', key: 'devtools/sdk' },
5757
{ text: 'Terraform', header: true, anchor: true, type: 'learn', slug: '/documentation/products/terraform-provider/', key: 'devtools/terraform' },
@@ -74,13 +74,13 @@ export default [
7474
text: 'Build', header: true, type: 'learn', key: 'buildRef', hasLabel: 'menu.reference', items: [
7575
{ text: 'Edge Application', header: true, anchor: true, type: 'learn', key: 'reference/edgeApplication', slug: '/documentation/products/build/edge-application/' },
7676
{ text: 'Application Accelerator', header: true, anchor: true, type: 'learn', key: 'reference/applicationAcceleration', slug: '/documentation/products/build/edge-application/application-accelerator/' },
77-
{ text: 'Edge Cache', header: true, anchor: true, type: 'learn', key: 'reference/edgeCaching', slug: '/documentation/products/build/edge-application/edge-caching/' },
77+
{ text: 'Edge Cache', header: true, anchor: true, type: 'learn', key: 'reference/edgeCaching', slug: '/documentation/products/build/edge-application/edge-cache/' },
7878
{ text: 'Edge Functions', header: true, anchor: true, type: 'learn', key: 'reference/edge Functions', slug: '/documentation/products/build/edge-application/edge-functions/' },
7979
{ text: 'Image Processor', header: true, anchor: true, type: 'learn', key: 'reference/imageProcessor', slug: '/documentation/products/build/edge-application/image-processor/' },
8080
{ text: 'Load Balancer', header: true, anchor: true, type: 'learn', key: 'reference/loadBalancer', slug: '/documentation/products/build/edge-application/load-balancer/' },
81-
{ text: 'Tiered Cache', header: true, anchor: true, type: 'learn', key: 'reference/l2Caching', slug: '/documentation/products/edge-application/l2-caching/' },
82-
{ text: 'Main Settings', header: true, anchor: true, type: 'learn', key: 'reference/mainSettings', slug: '/documentation/products/edge-application/build/main-settings/' },
83-
{ text: 'Cache Settings', header: true, anchor: true, type: 'learn', key: 'reference/cacheSettings', slug: '/documentation/products/edge-application/cache-settings/' },
81+
{ text: 'Tiered Cache', header: true, anchor: true, type: 'learn', key: 'reference/l2Caching', slug: '/documentation/products/build/edge-application/tiered-cache/' },
82+
{ text: 'Main Settings', header: true, anchor: true, type: 'learn', key: 'reference/mainSettings', slug: '/documentation/products/build/edge-application/main-settings/' },
83+
{ text: 'Cache Settings', header: true, anchor: true, type: 'learn', key: 'reference/cacheSettings', slug: '/documentation/products/build/edge-application/cache-settings/' },
8484
{ text: 'Edge Functions Instances', header: true, anchor: true, type: 'learn', key: 'reference/edgeFunctionsInstancesApplication', slug: '/documentation/products/build/edge-application/edge-functions-instances/' },
8585
{ text: 'Device Groups', header: true, anchor: true, type: 'learn', key: 'reference/deviceGroups', slug: '/documentation/products/build/edge-application/device-groups/' },
8686
{ text: 'Error Responses', header: true, anchor: true, type: 'learn', key: 'reference/errorResponses', slug: '/documentation/products/build/edge-application/error-responses/' },
@@ -104,7 +104,7 @@ export default [
104104
{ text: 'Network Layer Protection', header: true, anchor: true, type: 'learn', key: 'reference/networkLayerProtection', slug: '/documentation/products/secure/edge-firewall/network-layer-protection/' },
105105
{ text: 'Network Lists', header: true, anchor: true, type: 'learn', key: 'reference/networkLists', slug: '/documentation/products/secure/edge-firewall/network-layer-protection/network-lists/' },
106106
{ text: 'Web Application Firewall', header: true, anchor: true, type: 'learn', key: 'reference/webApplicationFirewall', slug: '/documentation/products/secure/edge-firewall/web-application-firewall/' },
107-
{ text: 'WAF Rule Sets', header: true, anchor: true, type: 'learn', key: 'reference/wafRuleSets', slug: '/documentation/products/secure/edge-firewall/web-application-firewall/rules-engine/' },
107+
{ text: 'WAF Rule Sets', header: true, anchor: true, type: 'learn', key: 'reference/wafRuleSets', slug: '/documentation/products/secure/edge-firewall/web-application-firewall/rules-set/' },
108108
{ text: 'WAF Custom Allowed Rules', header: true, anchor: true, type: 'learn', key: 'reference/wafCustomAllowedRules', slug: '/documentation/products/secure/edge-firewall/web-application-firewall/custom-allowed-rules/' },
109109
{ text: 'Edge Functions', header: true, anchor: true, type: 'learn', key: 'reference/edgeFunctionsFirewall', slug: '/documentation/products/secure/edge-firewall/edge-functions/' },
110110
{ text: 'Edge Functions Instances', header: true, anchor: true, type: 'learn', key: 'reference/edgeFunctionsInstancesFirewall', slug: '/documentation/products/secure/edge-firewall/edge-functions-instances/' },
@@ -129,14 +129,14 @@ export default [
129129
{ text: 'Edge Pulse', header: true, anchor: true, type: 'learn', key: 'reference/edgePulse', slug: '/documentation/products/observe/edge-pulse/' },
130130
{ text: 'Real-Time Events', header: true, anchor: true, type: 'learn', key: 'reference/realTimeEvents', slug: '/documentation/products/observe/real-time-events/' },
131131
{ text: 'Real-Time Metrics', header: true, anchor: true, type: 'learn', key: 'reference/realTimeMetrics', slug: '/documentation/products/observe/real-time-metrics/' },
132-
{ text: 'Historical Real-Time Metrics', header: true, anchor: true, type: 'learn', key: 'reference/historicalRealTimeMetrics', slug: '/documentation/products/historical-real-time-metrics/' },
132+
{ text: 'Historical Real-Time Metrics', header: true, anchor: true, type: 'learn', key: 'reference/historicalRealTimeMetrics', slug: '/documentation/products/observe/historical-real-time-metrics/' },
133133

134134
]
135135
},
136136
{
137137
text: 'Marketplace', header: true, type: 'learn', key: 'mktpRef', items: [
138138
{ text: 'Marketplace', header: true, anchor: true, type: 'learn', key: 'mktp', slug: '/documentation/products/marketplace/' },
139-
{ text: 'Permissions', header: true, anchor: true, type: 'learn', key: 'mktp/permissions', slug: '/documentation/products/guides/permissions-marketplace/' },
139+
{ text: 'Permissions', header: true, anchor: true, type: 'learn', key: 'mktp/permissions', slug: '/documentation/products/marketplace/permissions-marketplace/' },
140140
{ text: 'Marketplace Seller Guide', header: true, anchor: true, type: 'learn', key: 'mktp/sellerGuide', slug: '/documentation/products/marketplace/marketplace-seller-guide/' },
141141
]
142142
},

src/i18n/pt-br/graphqlMenu.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
{ text: 'Recursos', header: true, anchor: true, type: 'learn', slug: '/documentacao/produtos/graphql-api-recursos', key: 'features' },
2323

2424
{ text: 'Campos', header: true, key: 'fields', type: 'learn', items: [
25-
{ text: 'Real-Time Events GQL', slug: '/documentacao/produtos/graphql-api/recursos/campos-events/', key: 'fields/Events' },
26-
{ text: 'Real-Time Metrics GQL', slug: '/documentacao/produtos/graphql-api/recursos/campos-metrics/', key: 'fields/Metrics' },
25+
{ text: 'Real-Time Events GQL', slug: '/documentacao/devtools/graphql-api/recursos/campos-gql-real-time-events/', key: 'fields/Events' },
26+
{ text: 'Real-Time Metrics GQL', slug: '/documentacao/devtools/graphql-api/recursos/campos-gql-real-time-metrics/', key: 'fields/Metrics' },
2727
{ text: 'Billing GQL', slug: '/documentacao/devtools/graphql-api/recursos/campos-gql-billing/', key: 'fields/Billing' },
2828
{ text: 'Accounting GQL', slug: '/documentacao/devtools/graphql-api/recursos/campos-gql-accounting/', key: 'fields/Accounting' },
2929
]

0 commit comments

Comments
 (0)