chart2txt 0.6.0 → 0.7.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.
Files changed (49) hide show
  1. package/README.md +101 -34
  2. package/dist/chart2txt.d.ts +9 -0
  3. package/dist/chart2txt.js +30 -0
  4. package/dist/chart2txt.min.js +1 -1
  5. package/dist/config/ChartSettings.d.ts +12 -6
  6. package/dist/config/ChartSettings.js +36 -11
  7. package/dist/constants.d.ts +17 -2
  8. package/dist/constants.js +301 -34
  9. package/dist/core/analysis.d.ts +6 -0
  10. package/dist/core/analysis.js +235 -0
  11. package/dist/core/aspectPatterns.d.ts +8 -3
  12. package/dist/core/aspectPatterns.js +234 -218
  13. package/dist/core/aspects.d.ts +14 -11
  14. package/dist/core/aspects.js +49 -32
  15. package/dist/core/dignities.d.ts +2 -27
  16. package/dist/core/dignities.js +56 -121
  17. package/dist/core/dispositors.d.ts +6 -19
  18. package/dist/core/dispositors.js +45 -131
  19. package/dist/core/grouping.d.ts +9 -0
  20. package/dist/core/grouping.js +45 -0
  21. package/dist/core/signDistributions.d.ts +20 -30
  22. package/dist/core/signDistributions.js +22 -122
  23. package/dist/core/stelliums.d.ts +10 -0
  24. package/dist/core/stelliums.js +108 -0
  25. package/dist/formatters/text/sections/aspectPatterns.d.ts +3 -1
  26. package/dist/formatters/text/sections/aspectPatterns.js +118 -94
  27. package/dist/formatters/text/sections/aspects.d.ts +3 -6
  28. package/dist/formatters/text/sections/aspects.js +35 -52
  29. package/dist/formatters/text/sections/dispositors.d.ts +4 -3
  30. package/dist/formatters/text/sections/dispositors.js +7 -8
  31. package/dist/formatters/text/sections/houseOverlays.d.ts +11 -6
  32. package/dist/formatters/text/sections/houseOverlays.js +37 -44
  33. package/dist/formatters/text/sections/metadata.d.ts +2 -0
  34. package/dist/formatters/text/sections/metadata.js +54 -0
  35. package/dist/formatters/text/sections/planets.d.ts +3 -5
  36. package/dist/formatters/text/sections/planets.js +11 -22
  37. package/dist/formatters/text/sections/signDistributions.d.ts +9 -25
  38. package/dist/formatters/text/sections/signDistributions.js +9 -55
  39. package/dist/formatters/text/textFormatter.d.ts +4 -5
  40. package/dist/formatters/text/textFormatter.js +81 -141
  41. package/dist/index.d.ts +7 -4
  42. package/dist/index.js +11 -6
  43. package/dist/types.d.ts +100 -15
  44. package/dist/types.js +15 -0
  45. package/dist/utils/formatting.d.ts +4 -0
  46. package/dist/utils/formatting.js +43 -0
  47. package/dist/utils/houseCalculations.d.ts +10 -13
  48. package/dist/utils/houseCalculations.js +15 -57
  49. package/package.json +1 -1
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.groupAspects = groupAspects;
4
+ /**
5
+ * Provides a default grouping of aspects into "Tight", "Moderate", and "Wide" categories
6
+ * based on orb thresholds. This is used by the simple chart2txt() function.
7
+ * @param aspects The raw list of aspects to group.
8
+ * @param settings The chart settings, containing aspectStrengthThresholds.
9
+ * @returns A map of category names to aspect data arrays.
10
+ */
11
+ function groupAspects(aspects, settings) {
12
+ const grouped = new Map();
13
+ const thresholds = settings.aspectStrengthThresholds;
14
+ const tight = [];
15
+ const moderate = [];
16
+ const wide = [];
17
+ aspects.forEach((aspect) => {
18
+ if (aspect.orb <= thresholds.tight) {
19
+ tight.push(aspect);
20
+ }
21
+ else if (aspect.orb <= thresholds.moderate) {
22
+ moderate.push(aspect);
23
+ }
24
+ else {
25
+ wide.push(aspect);
26
+ }
27
+ });
28
+ // Sort each category by orb tightness
29
+ tight.sort((a, b) => a.orb - b.orb);
30
+ moderate.sort((a, b) => a.orb - b.orb);
31
+ wide.sort((a, b) => a.orb - b.orb);
32
+ if (tight.length > 0) {
33
+ const title = `[TIGHT ASPECTS: orb under ${thresholds.tight.toFixed(1)}°]`;
34
+ grouped.set(title, tight);
35
+ }
36
+ if (moderate.length > 0) {
37
+ const title = `[MODERATE ASPECTS: orb ${thresholds.tight.toFixed(1)}-${thresholds.moderate.toFixed(1)}°]`;
38
+ grouped.set(title, moderate);
39
+ }
40
+ if (wide.length > 0) {
41
+ const title = `[WIDE ASPECTS: orb over ${thresholds.moderate.toFixed(1)}°]`;
42
+ grouped.set(title, wide);
43
+ }
44
+ return grouped;
45
+ }
@@ -1,31 +1,21 @@
1
1
  import { Point } from '../types';
2
- export interface SignDistributions {
3
- elements: Record<string, string[]>;
4
- modalities: Record<string, number>;
5
- polarities: Record<string, number>;
6
- }
7
- /**
8
- * Analyzes the distribution of planets across elements, modalities, and polarities
9
- * @param planets Array of planet points
10
- * @param includeAscendant Optional ascendant degree to include in analysis
11
- * @returns Sign distribution analysis
12
- */
13
- export declare function analyzeSignDistributions(planets: Point[], includeAscendant?: number): SignDistributions;
14
- /**
15
- * Formats element distribution for display
16
- * @param elements Element distribution data
17
- * @returns Array of formatted strings
18
- */
19
- export declare function formatElementDistribution(elements: Record<string, string[]>): string[];
20
- /**
21
- * Formats modality distribution for display
22
- * @param modalities Modality distribution data
23
- * @returns Array of formatted strings
24
- */
25
- export declare function formatModalityDistribution(modalities: Record<string, number>): string[];
26
- /**
27
- * Formats polarity distribution for display
28
- * @param polarities Polarity distribution data
29
- * @returns Array of formatted strings
30
- */
31
- export declare function formatPolarityDistribution(polarities: Record<string, number>): string[];
2
+ export declare function calculateSignDistributions(planets: Point[], ascendant?: number): {
3
+ elements: {
4
+ [key: string]: string[];
5
+ };
6
+ modalities: {
7
+ [key: string]: number;
8
+ };
9
+ polarities: {
10
+ [key: string]: number;
11
+ };
12
+ };
13
+ export declare function formatElementDistribution(elements: {
14
+ [key: string]: string[];
15
+ }): string[];
16
+ export declare function formatModalityDistribution(modalities: {
17
+ [key: string]: number;
18
+ }): string[];
19
+ export declare function formatPolarityDistribution(polarities: {
20
+ [key: string]: number;
21
+ }): string[];
@@ -1,60 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.analyzeSignDistributions = analyzeSignDistributions;
3
+ exports.calculateSignDistributions = calculateSignDistributions;
4
4
  exports.formatElementDistribution = formatElementDistribution;
5
5
  exports.formatModalityDistribution = formatModalityDistribution;
6
6
  exports.formatPolarityDistribution = formatPolarityDistribution;
7
- const astrology_1 = require("./astrology");
8
- // Sign classifications
9
- const SIGN_ELEMENTS = {
10
- Aries: 'Fire',
11
- Leo: 'Fire',
12
- Sagittarius: 'Fire',
13
- Taurus: 'Earth',
14
- Virgo: 'Earth',
15
- Capricorn: 'Earth',
16
- Gemini: 'Air',
17
- Libra: 'Air',
18
- Aquarius: 'Air',
19
- Cancer: 'Water',
20
- Scorpio: 'Water',
21
- Pisces: 'Water',
22
- };
23
- const SIGN_MODALITIES = {
24
- Aries: 'Cardinal',
25
- Cancer: 'Cardinal',
26
- Libra: 'Cardinal',
27
- Capricorn: 'Cardinal',
28
- Taurus: 'Fixed',
29
- Leo: 'Fixed',
30
- Scorpio: 'Fixed',
31
- Aquarius: 'Fixed',
32
- Gemini: 'Mutable',
33
- Virgo: 'Mutable',
34
- Sagittarius: 'Mutable',
35
- Pisces: 'Mutable',
36
- };
37
- const SIGN_POLARITIES = {
38
- Aries: 'Masculine',
39
- Gemini: 'Masculine',
40
- Leo: 'Masculine',
41
- Libra: 'Masculine',
42
- Sagittarius: 'Masculine',
43
- Aquarius: 'Masculine',
44
- Taurus: 'Feminine',
45
- Cancer: 'Feminine',
46
- Virgo: 'Feminine',
47
- Scorpio: 'Feminine',
48
- Capricorn: 'Feminine',
49
- Pisces: 'Feminine',
50
- };
51
- /**
52
- * Analyzes the distribution of planets across elements, modalities, and polarities
53
- * @param planets Array of planet points
54
- * @param includeAscendant Optional ascendant degree to include in analysis
55
- * @returns Sign distribution analysis
56
- */
57
- function analyzeSignDistributions(planets, includeAscendant) {
7
+ const formatting_1 = require("../utils/formatting");
8
+ const constants_1 = require("../constants");
9
+ function calculateSignDistributions(planets, ascendant) {
10
+ const points = [...planets];
11
+ if (ascendant !== undefined) {
12
+ points.push({ name: 'Ascendant', degree: ascendant });
13
+ }
58
14
  const elements = {
59
15
  Fire: [],
60
16
  Earth: [],
@@ -66,85 +22,29 @@ function analyzeSignDistributions(planets, includeAscendant) {
66
22
  Fixed: 0,
67
23
  Mutable: 0,
68
24
  };
69
- const polarities = {
70
- Masculine: 0,
71
- Feminine: 0,
72
- };
73
- // Process planets
74
- planets.forEach((planet) => {
75
- const sign = (0, astrology_1.getDegreeSign)(planet.degree);
76
- const element = SIGN_ELEMENTS[sign];
77
- const modality = SIGN_MODALITIES[sign];
78
- const polarity = SIGN_POLARITIES[sign];
79
- if (element) {
80
- elements[element].push(planet.name);
81
- }
82
- if (modality) {
83
- modalities[modality]++;
84
- }
85
- if (polarity) {
86
- polarities[polarity]++;
87
- }
88
- });
89
- // Process ascendant if provided
90
- if (includeAscendant !== undefined) {
91
- const ascSign = (0, astrology_1.getDegreeSign)(includeAscendant);
92
- const ascElement = SIGN_ELEMENTS[ascSign];
93
- const ascModality = SIGN_MODALITIES[ascSign];
94
- const ascPolarity = SIGN_POLARITIES[ascSign];
95
- if (ascElement) {
96
- elements[ascElement].push('Ascendant');
97
- }
98
- if (ascModality) {
99
- modalities[ascModality]++;
100
- }
101
- if (ascPolarity) {
102
- polarities[ascPolarity]++;
25
+ const polarities = { Masculine: 0, Feminine: 0 };
26
+ for (const point of points) {
27
+ const sign = (0, formatting_1.getSign)(point.degree);
28
+ const signInfo = constants_1.ZODIAC_SIGN_DATA.find((s) => s.name === sign);
29
+ if (signInfo) {
30
+ elements[signInfo.element].push(point.name);
31
+ modalities[signInfo.modality]++;
32
+ polarities[signInfo.polarity]++;
103
33
  }
104
34
  }
105
35
  return { elements, modalities, polarities };
106
36
  }
107
- /**
108
- * Formats element distribution for display
109
- * @param elements Element distribution data
110
- * @returns Array of formatted strings
111
- */
112
37
  function formatElementDistribution(elements) {
113
- const output = [];
114
- Object.entries(elements).forEach(([element, planets]) => {
115
- if (planets.length > 0) {
116
- const planetList = planets.join(', ');
117
- output.push(`${element}: ${planets.length} (${planetList})`);
38
+ return Object.entries(elements).map(([element, planets]) => {
39
+ if (planets.length === 0) {
40
+ return `${element}: 0`;
118
41
  }
42
+ return `${element}: ${planets.length} (${planets.join(', ')})`;
119
43
  });
120
- return output;
121
44
  }
122
- /**
123
- * Formats modality distribution for display
124
- * @param modalities Modality distribution data
125
- * @returns Array of formatted strings
126
- */
127
45
  function formatModalityDistribution(modalities) {
128
- const output = [];
129
- Object.entries(modalities).forEach(([modality, count]) => {
130
- if (count > 0) {
131
- output.push(`${modality}: ${count}`);
132
- }
133
- });
134
- return output;
46
+ return Object.entries(modalities).map(([modality, count]) => `${modality}: ${count}`);
135
47
  }
136
- /**
137
- * Formats polarity distribution for display
138
- * @param polarities Polarity distribution data
139
- * @returns Array of formatted strings
140
- */
141
48
  function formatPolarityDistribution(polarities) {
142
- const output = [];
143
- if (polarities['Masculine'] > 0) {
144
- output.push(`Masculine (Active): ${polarities['Masculine']}`);
145
- }
146
- if (polarities['Feminine'] > 0) {
147
- output.push(`Feminine (Receptive): ${polarities['Feminine']}`);
148
- }
149
- return output;
49
+ return Object.entries(polarities).map(([polarity, count]) => `${polarity}: ${count}`);
150
50
  }
@@ -0,0 +1,10 @@
1
+ import { Point, Stellium } from '../types';
2
+ /**
3
+ * Detect Stellium patterns (3+ planets in same sign or adjacent houses)
4
+ * This function requires house information and is specific to single-chart analysis
5
+ */
6
+ export declare function detectStelliums(planets: Point[], houseCusps?: number[], minPlanets?: number): Stellium[];
7
+ /**
8
+ * Format a Stellium pattern for display in compact format
9
+ */
10
+ export declare function formatStellium(pattern: Stellium): string[];
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectStelliums = detectStelliums;
4
+ exports.formatStellium = formatStellium;
5
+ const astrology_1 = require("./astrology");
6
+ const houseCalculations_1 = require("../utils/houseCalculations");
7
+ const formatting_1 = require("../utils/formatting");
8
+ /**
9
+ * Convert Point to PlanetPosition
10
+ */
11
+ function pointToPlanetPosition(point, houseCusps) {
12
+ const sign = (0, astrology_1.getDegreeSign)(point.degree);
13
+ const house = houseCusps
14
+ ? (0, houseCalculations_1.getHouseForPoint)(point.degree, houseCusps) || undefined
15
+ : undefined;
16
+ return {
17
+ name: point.name,
18
+ degree: point.degree,
19
+ sign,
20
+ house,
21
+ };
22
+ }
23
+ /**
24
+ * Detect Stellium patterns (3+ planets in same sign or adjacent houses)
25
+ * This function requires house information and is specific to single-chart analysis
26
+ */
27
+ function detectStelliums(planets, houseCusps, minPlanets = 3) {
28
+ const patterns = [];
29
+ // Group by sign
30
+ const signGroups = new Map();
31
+ planets.forEach((planet) => {
32
+ const sign = (0, astrology_1.getDegreeSign)(planet.degree);
33
+ if (!signGroups.has(sign)) {
34
+ signGroups.set(sign, []);
35
+ }
36
+ signGroups.get(sign).push(planet);
37
+ });
38
+ // Check sign-based stelliums
39
+ signGroups.forEach((planetsInSign, sign) => {
40
+ if (planetsInSign.length >= minPlanets) {
41
+ const planetPositions = planetsInSign.map((p) => pointToPlanetPosition(p, houseCusps));
42
+ const houses = planetPositions
43
+ .map((p) => p.house)
44
+ .filter((h) => h !== undefined);
45
+ const degrees = planetsInSign.map((p) => p.degree);
46
+ const span = Math.max(...degrees) - Math.min(...degrees);
47
+ patterns.push({
48
+ type: 'Stellium',
49
+ planets: planetPositions,
50
+ sign,
51
+ houses: [...new Set(houses)].sort(),
52
+ span,
53
+ });
54
+ }
55
+ });
56
+ // Check house-based stelliums (if house cusps available)
57
+ if (houseCusps) {
58
+ const houseGroups = new Map();
59
+ planets.forEach((planet) => {
60
+ const house = (0, houseCalculations_1.getHouseForPoint)(planet.degree, houseCusps);
61
+ if (house) {
62
+ if (!houseGroups.has(house)) {
63
+ houseGroups.set(house, []);
64
+ }
65
+ houseGroups.get(house).push(planet);
66
+ }
67
+ });
68
+ houseGroups.forEach((planetsInHouse, house) => {
69
+ if (planetsInHouse.length >= minPlanets) {
70
+ const planetPositions = planetsInHouse.map((p) => pointToPlanetPosition(p, houseCusps));
71
+ const degrees = planetsInHouse.map((p) => p.degree);
72
+ const span = Math.max(...degrees) - Math.min(...degrees);
73
+ // Only add if not already covered by sign stellium
74
+ const existingSignStellium = patterns.find((p) => p.type === 'Stellium' &&
75
+ p.planets.some((planet) => planetPositions.some((pp) => pp.name === planet.name)));
76
+ if (!existingSignStellium) {
77
+ patterns.push({
78
+ type: 'Stellium',
79
+ planets: planetPositions,
80
+ houses: [house],
81
+ span,
82
+ });
83
+ }
84
+ }
85
+ });
86
+ }
87
+ return patterns;
88
+ }
89
+ /**
90
+ * Format a Stellium pattern for display in compact format
91
+ */
92
+ function formatStellium(pattern) {
93
+ const planetNames = pattern.planets.map((p) => p.name).join(', ');
94
+ let location = '';
95
+ if (pattern.sign) {
96
+ location = pattern.sign;
97
+ }
98
+ if (pattern.houses && pattern.houses.length > 0) {
99
+ const houseStr = pattern.houses.length === 1
100
+ ? `${(0, formatting_1.getOrdinal)(pattern.houses[0])} House`
101
+ : pattern.houses.map((h) => `${(0, formatting_1.getOrdinal)(h)} House`).join('-');
102
+ location += location ? ` (${houseStr})` : houseStr;
103
+ }
104
+ const locationStr = location ? ` in ${location}` : '';
105
+ return [
106
+ `Stellium (${pattern.span.toFixed(1)}°): ${planetNames}${locationStr}`,
107
+ ];
108
+ }
@@ -2,6 +2,8 @@ import { AspectPattern } from '../../../types';
2
2
  /**
3
3
  * Generates the [ASPECT PATTERNS] section of the chart output.
4
4
  * @param patterns Array of detected aspect patterns
5
+ * @param customTitle Optional custom title for the section
6
+ * @param showChartNames Whether to show chart names for planets (false for single charts, true for multi-chart)
5
7
  * @returns An array of strings for the output.
6
8
  */
7
- export declare function generateAspectPatternsOutput(patterns: AspectPattern[]): string[];
9
+ export declare function generateAspectPatternsOutput(patterns: AspectPattern[], customTitle?: string, showChartNames?: boolean): string[];