@salesforce/b2c-dx-mcp 1.0.8 → 1.0.10

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.
@@ -4,7 +4,8 @@
4
4
  * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
5
  */
6
6
  import { readFileSync, existsSync } from 'node:fs';
7
- import { join, dirname, basename } from 'node:path';
7
+ import nodePath from 'node:path';
8
+ const { join, dirname, basename } = nodePath;
8
9
  import { createRequire } from 'node:module';
9
10
  import { getLogger } from '@salesforce/b2c-tooling-sdk/logging';
10
11
  // Resolve the site-theming content directory from the package root
@@ -13,19 +14,19 @@ const packageRoot = dirname(require.resolve('@salesforce/b2c-dx-mcp/package.json
13
14
  const SITE_THEMING_CONTENT_DIR = join(packageRoot, 'content', 'site-theming');
14
15
  const logger = getLogger();
15
16
  function parseWorkflowSection(content) {
16
- const workflowMatch = content.match(/##\s*🔄\s*WORKFLOW[^#]*(?=##|$)/is);
17
+ const workflowMatch = content.match(/##\s*\u{1F504}\s*WORKFLOW[^#]*(?=##|$)/isu);
17
18
  if (!workflowMatch)
18
19
  return undefined;
19
- const workflowContent = workflowMatch[0].replace(/##\s*🔄\s*WORKFLOW[^\n]*\n?/i, '').trim();
20
+ const workflowContent = workflowMatch[0].replace(/##\s*\u{1F504}\s*WORKFLOW[^\n]*\n?/iu, '').trim();
20
21
  const stepMatches = workflowContent.match(/^\d+\.\s+(.+)$/gm);
21
22
  const steps = stepMatches ? stepMatches.map((step) => step.replace(/^\d+\.\s+/, '').trim()) : [];
22
- const extractionMatch = workflowContent.match(/###\s*📝\s*EXTRACTION[^#]*(?=###|$)/is);
23
+ const extractionMatch = workflowContent.match(/###\s*\u{1F4DD}\s*EXTRACTION[^#]*(?=###|$)/isu);
23
24
  const extractionInstructions = extractionMatch
24
- ? extractionMatch[0].replace(/###\s*📝\s*EXTRACTION[^\n]*\n?/i, '').trim()
25
+ ? extractionMatch[0].replace(/###\s*\u{1F4DD}\s*EXTRACTION[^\n]*\n?/iu, '').trim()
25
26
  : undefined;
26
- const checklistMatch = workflowContent.match(/###\s*✅\s*PRE-IMPLEMENTATION[^#]*(?=###|$)/is);
27
+ const checklistMatch = workflowContent.match(/###\s*\u2705\s*PRE-IMPLEMENTATION[^#]*(?=###|$)/is);
27
28
  const preImplementationChecklist = checklistMatch
28
- ? checklistMatch[0].replace(/###\s*✅\s*PRE-IMPLEMENTATION[^\n]*\n?/i, '').trim()
29
+ ? checklistMatch[0].replace(/###\s*\u2705\s*PRE-IMPLEMENTATION[^\n]*\n?/i, '').trim()
29
30
  : undefined;
30
31
  if (steps.length > 0 || extractionInstructions || preImplementationChecklist) {
31
32
  return { steps, extractionInstructions, preImplementationChecklist };
@@ -33,10 +34,10 @@ function parseWorkflowSection(content) {
33
34
  return undefined;
34
35
  }
35
36
  function parseValidationSection(content) {
36
- const validationMatch = content.match(/##\s*✅\s*VALIDATION[^#]*(?=##|$)/is);
37
+ const validationMatch = content.match(/##\s*\u2705\s*VALIDATION[^#]*(?=##|$)/is);
37
38
  if (!validationMatch)
38
39
  return undefined;
39
- const validationContent = validationMatch[0].replace(/##\s*✅\s*VALIDATION[^\n]*\n?/i, '').trim();
40
+ const validationContent = validationMatch[0].replace(/##\s*\u2705\s*VALIDATION[^\n]*\n?/i, '').trim();
40
41
  const colorValidationMatch = validationContent.match(/###\s*A\.\s*Color[^#]*(?=###|$)/is);
41
42
  const colorValidation = colorValidationMatch
42
43
  ? colorValidationMatch[0].replace(/###\s*A\.\s*Color[^\n]*\n?/i, '').trim()
@@ -282,25 +283,29 @@ function parseThemingMDC(content, filePath) {
282
283
  const validation = parseValidationSection(content);
283
284
  if (validation)
284
285
  guidance.validation = validation;
285
- const criticalSections = content.match(/##\s*⚠️\s*CRITICAL[^#]*/gi) || [];
286
- const specificationSections = content.match(/##\s*📋[^#]*/gi) || [];
286
+ // Emoji prefixes use explicit code points (U+26A0 WARNING SIGN with optional
287
+ // U+FE0F VARIATION SELECTOR-16; U+1F4CB CLIPBOARD) so that regex literals do
288
+ // not depend on how the source file is decoded by the TS/Node runtime on
289
+ // different platforms. Also tolerate \r before newlines for CRLF checkouts.
290
+ const criticalSections = content.match(/##\s*\u26A0\uFE0F?\s*CRITICAL[^#]*/gi) || [];
291
+ const specificationSections = content.match(/##\s*\u{1F4CB}[^#]*/giu) || [];
287
292
  for (const section of criticalSections) {
288
- const titleMatch = section.match(/##\s*⚠️\s*CRITICAL:\s*(.+?)\n/);
293
+ const titleMatch = section.match(/##\s*\u26A0\uFE0F?\s*CRITICAL:\s*(.+?)\r?\n/);
289
294
  const title = titleMatch ? titleMatch[1].trim() : 'Critical Rule';
290
295
  guidance.guidelines.push({
291
296
  category: 'critical',
292
297
  title,
293
- content: section.replace(/##\s*⚠️\s*CRITICAL[^\n]*\n/, '').trim(),
298
+ content: section.replace(/##\s*\u26A0\uFE0F?\s*CRITICAL[^\n]*\n/, '').trim(),
294
299
  critical: true,
295
300
  });
296
301
  }
297
302
  for (const section of specificationSections) {
298
- const titleMatch = section.match(/##\s*📋\s*(.+?)\n/);
303
+ const titleMatch = section.match(/##\s*\u{1F4CB}\s*(.+?)\r?\n/u);
299
304
  const title = titleMatch ? titleMatch[1].trim() : 'Specification Rule';
300
305
  guidance.guidelines.push({
301
306
  category: 'specification',
302
307
  title,
303
- content: section.replace(/##\s*📋[^\n]*\n/, '').trim(),
308
+ content: section.replace(/##\s*\u{1F4CB}[^\n]*\n/u, '').trim(),
304
309
  critical: false,
305
310
  });
306
311
  }
@@ -388,7 +393,9 @@ class ThemingStore {
388
393
  loadThemingFilesFromEnv(envValue, root) {
389
394
  const files = JSON.parse(envValue);
390
395
  for (const { key, path: filePath } of files) {
391
- const fullPath = filePath.startsWith('/') ? filePath : join(root, filePath);
396
+ // Use path.isAbsolute to detect absolute paths on both POSIX (/foo) and
397
+ // Windows (C:\foo); filePath.startsWith('/') misses Windows drive paths.
398
+ const fullPath = nodePath.isAbsolute(filePath) ? filePath : join(root, filePath);
392
399
  this.tryLoadEnvFile(key, fullPath);
393
400
  }
394
401
  }
@@ -390,5 +390,5 @@
390
390
  "enableJsonFlag": false
391
391
  }
392
392
  },
393
- "version": "1.0.8"
393
+ "version": "1.0.10"
394
394
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salesforce/b2c-dx-mcp",
3
3
  "description": "MCP server for B2C Commerce developer experience tools",
4
- "version": "1.0.8",
4
+ "version": "1.0.10",
5
5
  "author": "Salesforce",
6
6
  "license": "Apache-2.0",
7
7
  "repository": "SalesforceCommerceCloud/b2c-developer-tooling",
@@ -80,7 +80,7 @@
80
80
  "yaml": "2.8.1",
81
81
  "postcss": "8.5.6",
82
82
  "zod": "3.25.76",
83
- "@salesforce/b2c-tooling-sdk": "1.3.2"
83
+ "@salesforce/b2c-tooling-sdk": "1.5.0"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@eslint/compat": "^1",