astro-tractstack 2.0.0-rc.24 → 2.0.0-rc.25

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-tractstack",
3
- "version": "2.0.0-rc.24",
3
+ "version": "2.0.0-rc.25",
4
4
  "description": "Astro integration for TractStack - redeeming the web from boring experiences",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,7 @@ const SettingsPanel = ({ config, availableCodeHooks }: SettingsPanelProps) => {
23
23
 
24
24
  return (
25
25
  <div
26
- className="bg-mydarkgrey rounded-xl bg-opacity-20 p-0.5 backdrop-blur-sm"
26
+ className="bg-mydarkgrey max-w-md rounded-xl bg-opacity-20 p-0.5 backdrop-blur-sm"
27
27
  style={
28
28
  {
29
29
  animation: window.matchMedia(
@@ -14,9 +14,11 @@ import {
14
14
  } from '@/stores/storykeep';
15
15
  import { startLoadingAnimation } from '@/utils/helpers';
16
16
  import type {
17
+ FlatNode,
17
18
  BaseNode,
18
19
  PaneNode,
19
20
  StoryFragmentNode,
21
+ MarkdownPaneFragmentNode,
20
22
  } from '@/types/compositorTypes';
21
23
 
22
24
  type SaveStage =
@@ -317,6 +319,56 @@ export default function SaveModal({
317
319
  isContext
318
320
  );
319
321
 
322
+ // This ensures css generation in the next phase uses fresh values
323
+ payload.optionsPayload.nodes.forEach((transformedNode) => {
324
+ const liveNode = ctx.allNodes.get().get(transformedNode.id);
325
+ if (!liveNode) return;
326
+
327
+ let needsUpdate = false;
328
+ let updatedNode: BaseNode = { ...liveNode };
329
+
330
+ // Update elementCss for TagElement nodes (FlatNode)
331
+ if (
332
+ transformedNode.nodeType === 'TagElement' &&
333
+ transformedNode.elementCss
334
+ ) {
335
+ const flatNode = liveNode as FlatNode;
336
+ if (flatNode.elementCss !== transformedNode.elementCss) {
337
+ (updatedNode as FlatNode).elementCss =
338
+ transformedNode.elementCss;
339
+ needsUpdate = true;
340
+ }
341
+ }
342
+
343
+ // Update parentCss for Markdown nodes (MarkdownPaneFragmentNode)
344
+ if (
345
+ transformedNode.nodeType === 'Markdown' &&
346
+ transformedNode.parentCss
347
+ ) {
348
+ const markdownNode = liveNode as MarkdownPaneFragmentNode;
349
+ const currentParentCss = markdownNode.parentCss;
350
+ const newParentCss = transformedNode.parentCss as string[];
351
+
352
+ const isDifferent =
353
+ !currentParentCss ||
354
+ currentParentCss.length !== newParentCss.length ||
355
+ currentParentCss.some(
356
+ (css, index) => css !== newParentCss[index]
357
+ );
358
+
359
+ if (isDifferent) {
360
+ (updatedNode as MarkdownPaneFragmentNode).parentCss =
361
+ newParentCss;
362
+ needsUpdate = true;
363
+ }
364
+ }
365
+
366
+ // Only update the live node if there are actual changes
367
+ if (needsUpdate) {
368
+ ctx.allNodes.get().set(transformedNode.id, updatedNode);
369
+ }
370
+ });
371
+
320
372
  // Check if this pane exists or is new
321
373
  const paneExistsInBackend = contentMap.some(
322
374
  (item) => item.type === 'Pane' && item.id === paneNode.id
@@ -45,8 +45,6 @@ const {
45
45
  impressions = [],
46
46
  } = Astro.props;
47
47
 
48
- const isDev = import.meta.env.DEV;
49
-
50
48
  // Get site status from the store
51
49
  const isInitialized = !freshInstallStore.get().needsSetup;
52
50
 
@@ -60,13 +58,12 @@ const brandConfig = propBrandConfig || (await getBrandConfig(tenantId));
60
58
  const cssBasePath = isInitialized ? '/media/css' : '/styles';
61
59
  const fontBasePath = isInitialized ? '/media/fonts' : '/fonts';
62
60
  const mainStylesUrl = (() => {
63
- const baseUrl =
64
- isStoryKeep || isDev
65
- ? `${cssBasePath}/storykeep.css`
66
- : `${cssBasePath}/frontend.css`;
61
+ const baseUrl = isStoryKeep // || isDev
62
+ ? `${cssBasePath}/storykeep.css`
63
+ : `${cssBasePath}/frontend.css`;
67
64
 
68
65
  // Only add version for frontend.css (the dynamic one)
69
- if (!isStoryKeep && !isDev && brandConfig?.STYLES_VER) {
66
+ if (!isStoryKeep && brandConfig?.STYLES_VER) {
70
67
  return `${baseUrl}?v=${brandConfig.STYLES_VER}`;
71
68
  }
72
69
 
@@ -11,24 +11,6 @@ export const POST: APIRoute = async ({ request }) => {
11
11
  request.headers.get('X-Tenant-ID') ||
12
12
  import.meta.env.PUBLIC_TENANTID ||
13
13
  'default';
14
- const isMultiTenant =
15
- import.meta.env.PUBLIC_ENABLE_MULTI_TENANT === 'true' &&
16
- tenantId !== 'default';
17
-
18
- if (isMultiTenant) {
19
- return new Response('CSS generation disabled in multi-tenant mode', {
20
- status: 403,
21
- });
22
- }
23
-
24
- // Read tailwind config from project root
25
- const configPath = path.join(process.cwd(), 'tailwind.config.cjs');
26
- const configContent = await fs.readFile(configPath, 'utf-8');
27
- const tailwindConfig = new Function(
28
- 'module',
29
- 'exports',
30
- configContent + '; return module.exports;'
31
- )({ exports: {} }, {});
32
14
 
33
15
  const goBackend =
34
16
  import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
@@ -63,18 +45,29 @@ export const POST: APIRoute = async ({ request }) => {
63
45
  ...new Set([...(cleanClasses || []), ...(dirtyClasses || [])]),
64
46
  ];
65
47
 
66
- // Generate CSS using JIT
67
- const tailwindCss = createTailwindcss({ tailwindConfig });
68
- const baseClasses = allClasses.filter(
69
- (c) => !c.startsWith('md:') && !c.startsWith('xl:')
70
- );
71
- const mdClasses = allClasses.filter((c) => c.startsWith('md:'));
72
- const xlClasses = allClasses.filter((c) => c.startsWith('xl:'));
73
- const htmlContent = [
74
- `<div class="${baseClasses.join(' ')}"></div>`,
75
- `<div class="md:block ${mdClasses.join(' ')}"></div>`,
76
- `<div class="xl:block ${xlClasses.join(' ')}"></div>`,
77
- ];
48
+ // Read base tailwind config from project root
49
+ const configPath = path.join(process.cwd(), 'tailwind.config.cjs');
50
+ const configContent = await fs.readFile(configPath, 'utf-8');
51
+ const baseTailwindConfig = new Function(
52
+ 'module',
53
+ 'exports',
54
+ configContent + '; return module.exports;'
55
+ )({ exports: {} }, {});
56
+
57
+ // Create config with safelist
58
+ const tailwindConfigWithSafelist = {
59
+ ...baseTailwindConfig,
60
+ safelist: allClasses,
61
+ };
62
+
63
+ // Generate CSS using JIT with safelist
64
+ const tailwindCss = createTailwindcss({
65
+ tailwindConfig: tailwindConfigWithSafelist,
66
+ });
67
+
68
+ // Use simple HTML content since safelist should handle class generation
69
+ const htmlContent = ['<div>Using the safelist</div>'];
70
+
78
71
  const generatedCss = await tailwindCss.generateStylesFromContent(
79
72
  `@tailwind base; @tailwind utilities;`,
80
73
  htmlContent