chart2txt 0.3.1 → 0.4.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/dist/chart2txt.min.js +1 -1
- package/dist/config/ChartSettings.d.ts +10 -0
- package/dist/config/ChartSettings.js +18 -0
- package/dist/constants.d.ts +2 -1
- package/dist/constants.js +11 -10
- package/dist/core/aspects.d.ts +17 -0
- package/dist/core/aspects.js +86 -0
- package/dist/core/astrology.d.ts +12 -0
- package/dist/core/astrology.js +27 -0
- package/dist/formatters/text/sections/angles.d.ts +7 -0
- package/dist/formatters/text/sections/angles.js +26 -0
- package/dist/formatters/text/sections/aspects.d.ts +14 -0
- package/dist/formatters/text/sections/aspects.js +64 -0
- package/dist/formatters/text/sections/birthdata.d.ts +10 -0
- package/dist/formatters/text/sections/birthdata.js +21 -0
- package/dist/formatters/text/sections/chartHeader.d.ts +7 -0
- package/dist/formatters/text/sections/chartHeader.js +12 -0
- package/dist/formatters/text/sections/houseOverlays.d.ts +10 -0
- package/dist/formatters/text/sections/houseOverlays.js +85 -0
- package/dist/formatters/text/sections/metadata.d.ts +9 -0
- package/dist/formatters/text/sections/metadata.js +18 -0
- package/dist/formatters/text/sections/planets.d.ts +10 -0
- package/dist/formatters/text/sections/planets.js +53 -0
- package/dist/formatters/text/textFormatter.d.ts +8 -0
- package/dist/formatters/text/textFormatter.js +98 -0
- package/dist/index.d.ts +9 -8
- package/dist/index.js +36 -159
- package/dist/types.d.ts +19 -6
- package/dist/types.js +5 -0
- package/dist/utils/datetime.d.ts +13 -0
- package/dist/utils/datetime.js +46 -0
- package/package.json +1 -1
package/dist/chart2txt.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.chart2txt=n():e.chart2txt=n()}(this,(()=>(()=>{"use strict";var e={921:(e,n)=>{Object.defineProperty(n,"__esModule",{value:!0}),n.DEFAULT_SETTINGS=n.DEFAULT_ASPECTS=n.ZODIAC_SIGNS=void 0,n.ZODIAC_SIGNS=["Aries","Taurus","Gemini","Cancer","Leo","Virgo","Libra","Scorpio","Sagittarius","Capricorn","Aquarius","Pisces"],n.DEFAULT_ASPECTS=[{name:"conjunction",angle:0,orb:5},{name:"opposition",angle:180,orb:5},{name:"trine",angle:120,orb:5},{name:"square",angle:90,orb:5},{name:"sextile",angle:60,orb:3}],n.DEFAULT_SETTINGS={includeSignDegree:!0,omitSigns:!1,houseSystem:"equal",includeHouseDegree:!1,omitHouses:!1,includeAscendant:!0,omitPoints:!1,aspectDefinitions:n.DEFAULT_ASPECTS,omitAspects:!1}}},n={};function t(o){var s=n[o];if(void 0!==s)return s.exports;var i=n[o]={exports:{}};return e[o](i,i.exports,t),i.exports}var o={};return(()=>{var e=o;const n=t(921);function s(e,t,o=[],s=n.DEFAULT_SETTINGS.includeSignDegree){const i=[...t?[{name:"Ascendant",degree:t}]:[],...e,...o].map((e=>{const t=function(e){const t=Math.floor(e/30)%12;return n.ZODIAC_SIGNS[t]}(e.degree);if(s){const n=Math.floor(e.degree%30);return`${e.name} is at ${n}° ${t}`}return`${e.name} is in ${t}`})).join(". ");return i?`${i}.`:""}function i(e,t,o,s=[],i=n.DEFAULT_SETTINGS.includeHouseDegree){const r=[...o,...s].map((n=>{const o=function(e,n,t){switch(e){case"equal":{const e=(n-t+360)%360;return{house:Math.floor(e/30)+1,degree:e%30}}case"whole_sign":{const e=(n-Math.floor(t/30)%12*30+360)%360;return{house:Math.floor(e/30)+1,degree:e%30}}}}(e,n.degree,t);return i?`${n.name} is at ${o.degree}° in house ${o.house}`:`${n.name} is in house ${o.house}`})).join(". ");return r?`${r}.`:""}function r(e,t={}){const o=Object.assign({},n.DEFAULT_SETTINGS,t);let r="Astrology Chart";const a=(c=e.location,u=e.timestamp,[c?`location: ${c}`:"",u?`at: ${u.toLocaleString()}`:""].filter((e=>""!==e)).join(", "));var c,u;if(a&&(r+=` (${a})`),r+=":\n\n",o.omitSigns||(r+=s(e.planets,o.includeAscendant&&e.ascendant?e.ascendant:void 0,o.omitPoints?[]:e.points,o.includeSignDegree)),o.omitHouses||void 0===e.ascendant||(r+="\n\n"+i(o.houseSystem,e.ascendant,e.planets,o.omitPoints?[]:e.points,o.includeHouseDegree)),!o.omitAspects){const n=function(e,n){const t=[];for(let o=0;o<n.length;o++)for(let s=o+1;s<n.length;s++){const i=n[o],r=n[s];let a=Math.abs(i.degree-r.degree);a>180&&(a=360-a);for(const n of e){const e=Math.abs(a-n.angle);if(e<=n.orb){t.push({planetA:i.name,planetB:r.name,aspectType:n.name,orb:e});break}}}return t}(o.aspectDefinitions,e.planets);n.length>0&&(r+="\n\n"+function(e){const n=e.map((e=>`${e.planetA} is in ${e.aspectType} with ${e.planetB} (orb: ${e.orb.toFixed(1)}°)`)).join(". ");return n?`${n}.`:""}(n))}return r}e.default=r})(),o=o.default})()));
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.chart2txt=t():e.chart2txt=t()}(this,(()=>(()=>{"use strict";var e={75:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.calculateAspects=function(e,t){const n=[];if(!t||t.length<2)return n;for(let r=0;r<t.length;r++)for(let a=r+1;a<t.length;a++){const s=t[r],o=t[a];let u=Math.abs(s.degree-o.degree);u>180&&(u=360-u);let i=null;for(const t of e){const e=Math.abs(u-t.angle);e<=t.orb&&(!i||e<i.orb)&&(i={planetA:s.name,planetB:o.name,aspectType:t.name,orb:e})}i&&n.push(i)}return n},t.calculateMultichartAspects=function(e,t,n){const r=[];if(!t||!n||0===t.length||0===n.length)return r;for(const a of t)for(const t of n){let n=Math.abs(a.degree-t.degree);n>180&&(n=360-n);let s=null;for(const r of e){const e=Math.abs(n-r.angle);e<=r.orb&&(!s||e<s.orb)&&(s={planetA:a.name,planetB:t.name,aspectType:r.name,orb:e})}s&&r.push(s)}return r}},156:function(e,t,n){var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var a=Object.getOwnPropertyDescriptor(t,n);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,a)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),a=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),t.ChartSettings=t.ZODIAC_SIGNS=t.DEFAULT_ASPECT_CATEGORIES=t.DEFAULT_ASPECTS=t.DEFAULT_SETTINGS=t.chart2txt=void 0;var s=n(723);Object.defineProperty(t,"chart2txt",{enumerable:!0,get:function(){return s.formatChartToText}}),a(n(613),t);var o=n(921);Object.defineProperty(t,"DEFAULT_SETTINGS",{enumerable:!0,get:function(){return o.DEFAULT_SETTINGS}}),Object.defineProperty(t,"DEFAULT_ASPECTS",{enumerable:!0,get:function(){return o.DEFAULT_ASPECTS}}),Object.defineProperty(t,"DEFAULT_ASPECT_CATEGORIES",{enumerable:!0,get:function(){return o.DEFAULT_ASPECT_CATEGORIES}}),Object.defineProperty(t,"ZODIAC_SIGNS",{enumerable:!0,get:function(){return o.ZODIAC_SIGNS}});var u=n(230);Object.defineProperty(t,"ChartSettings",{enumerable:!0,get:function(){return u.ChartSettings}});const i=n(723);t.default=i.formatChartToText},172:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.generateChartHeaderOutput=function(e,t="CHART"){return[`[${t}: ${e||"Unknown"}]`]}},230:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ChartSettings=void 0;const r=n(921);t.ChartSettings=class{constructor(e={}){const t={...r.DEFAULT_SETTINGS,...e};this.includeSignDegree=t.includeSignDegree,this.includeAscendant=t.includeAscendant,this.includeHouseDegree=t.includeHouseDegree,this.aspectDefinitions=t.aspectDefinitions||r.DEFAULT_ASPECTS,this.aspectCategories=t.aspectCategories||r.DEFAULT_ASPECT_CATEGORIES,this.dateFormat=t.dateFormat}}},234:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.generatePlanetsOutput=function(e,t,n){const a=["[PLANETS]"];e.forEach((e=>{const n=(0,r.getDegreeSign)(e.degree),s=Math.floor((0,r.getDegreeInSign)(e.degree)),o=void 0!==e.speed&&e.speed<0?" Rx":"";let u=`${e.name}: ${s}° ${n}${o}`;if(t&&12===t.length){const n=function(e,t){if(!t||12!==t.length)return 0;for(let n=0;n<12;n++){const r=t[n],a=t[(n+1)%12];if(r<a){if(e>=r&&e<a)return n+1}else if(e>=r||e<a)return n+1}return 0}(e.degree,t);n>0&&(u+=`, House ${n}`)}a.push(u)})),0===e.length&&a.push("No planets listed.");return a};const r=n(904)},388:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.generateMetadataOutput=function(e,t,n){const r=["[METADATA]",`chart_type: ${t}`];n&&r.push(`house_system: ${n}`);return r.push(`date_format: ${e.dateFormat}`),r}},613:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isMultiChartData=function(e){return void 0!==e.chart1}},723:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.formatChartToText=function(e,t={}){const n=new r.ChartSettings(t),h=[];let g,d="natal";if("chart1"in e){const t=e;g=t.chart1.houseSystemName,t.chart2&&t.transit?d="synastry_with_transit":t.chart2?d="synastry":t.transit&&(d="natal_with_transit")}else g=e.houseSystemName;h.push(...(0,s.generateMetadataOutput)(n,d,g)),h.push("");const f=(e,t)=>{h.push(...(0,o.generateChartHeaderOutput)(e.name,t)),h.push(...(0,u.generateBirthdataOutput)(e.location,e.timestamp,n)),h.push(...(0,i.generateAnglesOutput)(e.ascendant,e.midheaven)),h.push(...(0,c.generatePlanetsOutput)(e.planets,e.houseCusps,n));const r=(0,a.calculateAspects)(n.aspectDefinitions,e.planets);h.push(...(0,p.generateAspectsOutput)("[ASPECTS]",r,n)),h.push("")};if("chart1"in e){const t=e,r=t.chart1,s=r.name||"Chart 1";if(f(r),t.chart2){const e=t.chart2,u=e.name||"Chart 2";f(e),h.push(...(0,o.generateChartHeaderOutput)(`${s}-${u}`,"SYNASTRY"));const i=(0,a.calculateMultichartAspects)(n.aspectDefinitions,r.planets,e.planets);h.push(...(0,p.generateAspectsOutput)("[PLANET-PLANET ASPECTS]",i,n,s,u)),h.push(""),h.push(...(0,l.generateHouseOverlaysOutput)(r,e,n)),h.push("")}if(t.transit){const e=t.transit,i=e.name||"Current";S=e,h.push(...(0,o.generateChartHeaderOutput)(S.name||"Current","TRANSIT")),h.push(...(0,u.generateBirthdataOutput)(S.location,S.timestamp,n,"[DATETIME]")),h.push(...(0,c.generatePlanetsOutput)(S.planets,S.houseCusps,n)),h.push("");const l=(0,a.calculateMultichartAspects)(n.aspectDefinitions,r.planets,e.planets);if(h.push(...(0,p.generateAspectsOutput)(`[TRANSIT ASPECTS: ${s}]`,l,n,s,i,!0)),h.push(""),t.chart2){const r=t.chart2.name||"Chart 2",s=(0,a.calculateMultichartAspects)(n.aspectDefinitions,t.chart2.planets,e.planets);h.push(...(0,p.generateAspectsOutput)(`[TRANSIT ASPECTS: ${r}]`,s,n,r,i,!0)),h.push("")}}}else f(e);var S;return h.join("\n").trimEnd()};const r=n(230),a=n(75),s=n(388),o=n(172),u=n(888),i=n(945),c=n(234),p=n(784),l=n(756)},756:(e,t)=>{function n(e,t){if(!t||12!==t.length)return 0;for(let n=0;n<12;n++){const r=t[n],a=t[(n+1)%12];if(r<a){if(e>=r&&e<a)return n+1}else if(e>=r||e<a)return n+1}return 0}Object.defineProperty(t,"__esModule",{value:!0}),t.generateHouseOverlaysOutput=function(e,t,r){const a=["[HOUSE OVERLAYS]"],s=e.name||"Chart 1",o=t.name||"Chart 2";t.houseCusps&&12===t.houseCusps.length?(a.push(`${s}'s planets in ${o}'s houses:`),e.planets&&e.planets.length>0?e.planets.forEach((e=>{const r=n(e.degree,t.houseCusps);r>0?a.push(`${e.name}: House ${r}`):a.push(`${e.name}: (Could not determine house in ${o})`)})):a.push("(No planets listed for overlay)")):a.push(`${s}'s planets in ${o}'s houses: (${o} house cusps not available)`);a.push(""),e.houseCusps&&12===e.houseCusps.length?(a.push(`${o}'s planets in ${s}'s houses:`),t.planets&&t.planets.length>0?t.planets.forEach((t=>{const r=n(t.degree,e.houseCusps);r>0?a.push(`${t.name}: House ${r}`):a.push(`${t.name}: (Could not determine house in ${s})`)})):a.push("(No planets listed for overlay)")):a.push(`${o}'s planets in ${s}'s houses: (${s} house cusps not available)`);return a}},784:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.generateAspectsOutput=function(e,t,n,r,a,s=!1){const o=[e];let u=!1;n.aspectCategories.forEach((e=>{const n=t.filter((t=>{const n=t.orb,r=void 0===e.minOrb||n>e.minOrb,a=n<=e.maxOrb;return r&&a}));if(n.length>0){u=!0;let t=`orb < ${e.maxOrb.toFixed(1)}°`;void 0!==e.minOrb&&(t=e.minOrb<e.maxOrb?`orb ${e.minOrb.toFixed(1)}-${e.maxOrb.toFixed(1)}°`:`orb > ${e.minOrb.toFixed(1)}° & < ${e.maxOrb.toFixed(1)}°`),o.push(`[${e.name.toUpperCase()}: ${t}]`),n.sort(((e,t)=>e.orb-t.orb)),n.forEach((e=>{const t=r?`${r}'s ${e.planetA}`:e.planetA;let n=e.planetB;s?n=`transiting ${e.planetB}`:a&&(n=`${a}'s ${e.planetB}`),o.push(`${t} ${e.aspectType} ${n}: ${e.orb.toFixed(1)}°`)}))}})),!u&&t.length>0?o.push("No aspects within defined categories."):0===t.length&&o.push("None");return o}},888:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.generateBirthdataOutput=function(e,t,n,a="[BIRTHDATA]"){if(!t)return[`${a} Not available`];const s=(0,r.formatDateCustom)(t,n.dateFormat),o=(0,r.formatTime)(t);return[`${a} ${e||"Unknown Location"}, ${s}, ${o}`]};const r=n(889)},889:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.formatDateCustom=function(e,t){const n=e.getMonth()+1,r=e.getDate(),a=e.getFullYear();switch(t.toUpperCase()){case"MM/DD/YYYY":return`${n.toString().padStart(2,"0")}/${r.toString().padStart(2,"0")}/${a}`;case"DD/MM/YYYY":return`${r.toString().padStart(2,"0")}/${n.toString().padStart(2,"0")}/${a}`;case"YYYY-MM-DD":return`${a}-${n.toString().padStart(2,"0")}-${r.toString().padStart(2,"0")}`;default:return console.warn(`Unrecognized date format: ${t}. Falling back to toLocaleDateString().`),e.toLocaleDateString()}},t.formatTime=function(e){return e.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!0})}},904:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getDegreeSign=function(e){const t=Math.floor(e/30)%12;if(t<0||t>=r.ZODIAC_SIGNS.length)return console.error(`Invalid sign index computed: ${t} for degree ${e}`),"Unknown Sign";return r.ZODIAC_SIGNS[t]},t.getDegreeInSign=function(e){return e%30};const r=n(921)},921:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_SETTINGS=t.DEFAULT_ASPECT_CATEGORIES=t.DEFAULT_ASPECTS=t.ZODIAC_SIGNS=void 0,t.ZODIAC_SIGNS=["Aries","Taurus","Gemini","Cancer","Leo","Virgo","Libra","Scorpio","Sagittarius","Capricorn","Aquarius","Pisces"],t.DEFAULT_ASPECTS=[{name:"conjunction",angle:0,orb:5},{name:"opposition",angle:180,orb:5},{name:"trine",angle:120,orb:5},{name:"square",angle:90,orb:5},{name:"sextile",angle:60,orb:3}],t.DEFAULT_ASPECT_CATEGORIES=[{name:"MAJOR",maxOrb:2},{name:"MODERATE",minOrb:2,maxOrb:4}],t.DEFAULT_SETTINGS={includeSignDegree:!0,includeHouseDegree:!1,includeAscendant:!0,aspectDefinitions:t.DEFAULT_ASPECTS,aspectCategories:t.DEFAULT_ASPECT_CATEGORIES,dateFormat:"MM/DD/YYYY"}},945:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.generateAnglesOutput=function(e,t){const n=["[ANGLES]"];void 0!==e?n.push(`ASC: ${Math.floor((0,r.getDegreeInSign)(e))}° ${(0,r.getDegreeSign)(e)}`):n.push("ASC: Not available");void 0!==t?n.push(`MC: ${Math.floor((0,r.getDegreeInSign)(t))}° ${(0,r.getDegreeSign)(t)}`):n.push("MC: Not available");return n};const r=n(904)}},t={};var n=function n(r){var a=t[r];if(void 0!==a)return a.exports;var s=t[r]={exports:{}};return e[r].call(s.exports,s,s.exports,n),s.exports}(156);return n=n.default})()));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Settings, PartialSettings, AspectCategory, Aspect } from '../types';
|
|
2
|
+
export declare class ChartSettings implements Settings {
|
|
3
|
+
includeSignDegree: boolean;
|
|
4
|
+
includeAscendant: boolean;
|
|
5
|
+
includeHouseDegree: boolean;
|
|
6
|
+
aspectDefinitions: Aspect[];
|
|
7
|
+
aspectCategories: AspectCategory[];
|
|
8
|
+
dateFormat: string;
|
|
9
|
+
constructor(customSettings?: PartialSettings);
|
|
10
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChartSettings = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
class ChartSettings {
|
|
6
|
+
constructor(customSettings = {}) {
|
|
7
|
+
const mergedSettings = { ...constants_1.DEFAULT_SETTINGS, ...customSettings };
|
|
8
|
+
this.includeSignDegree = mergedSettings.includeSignDegree;
|
|
9
|
+
this.includeAscendant = mergedSettings.includeAscendant;
|
|
10
|
+
this.includeHouseDegree = mergedSettings.includeHouseDegree;
|
|
11
|
+
this.aspectDefinitions =
|
|
12
|
+
mergedSettings.aspectDefinitions || constants_1.DEFAULT_ASPECTS; // Ensure array is not undefined
|
|
13
|
+
this.aspectCategories =
|
|
14
|
+
mergedSettings.aspectCategories || constants_1.DEFAULT_ASPECT_CATEGORIES; // Ensure array is not undefined
|
|
15
|
+
this.dateFormat = mergedSettings.dateFormat;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.ChartSettings = ChartSettings;
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Aspect, Settings } from './types';
|
|
1
|
+
import { Aspect, Settings, AspectCategory } from './types';
|
|
2
2
|
export declare const ZODIAC_SIGNS: string[];
|
|
3
3
|
export declare const DEFAULT_ASPECTS: Aspect[];
|
|
4
|
+
export declare const DEFAULT_ASPECT_CATEGORIES: AspectCategory[];
|
|
4
5
|
export declare const DEFAULT_SETTINGS: Settings;
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_SETTINGS = exports.DEFAULT_ASPECTS = exports.ZODIAC_SIGNS = void 0;
|
|
3
|
+
exports.DEFAULT_SETTINGS = exports.DEFAULT_ASPECT_CATEGORIES = exports.DEFAULT_ASPECTS = exports.ZODIAC_SIGNS = void 0;
|
|
4
4
|
exports.ZODIAC_SIGNS = [
|
|
5
5
|
'Aries',
|
|
6
6
|
'Taurus',
|
|
@@ -16,24 +16,25 @@ exports.ZODIAC_SIGNS = [
|
|
|
16
16
|
'Pisces',
|
|
17
17
|
];
|
|
18
18
|
exports.DEFAULT_ASPECTS = [
|
|
19
|
-
{ name: 'conjunction', angle: 0, orb: 5 },
|
|
19
|
+
{ name: 'conjunction', angle: 0, orb: 5 }, // Max orb for this aspect to be considered
|
|
20
20
|
{ name: 'opposition', angle: 180, orb: 5 },
|
|
21
21
|
{ name: 'trine', angle: 120, orb: 5 },
|
|
22
22
|
{ name: 'square', angle: 90, orb: 5 },
|
|
23
23
|
{ name: 'sextile', angle: 60, orb: 3 },
|
|
24
24
|
];
|
|
25
|
+
exports.DEFAULT_ASPECT_CATEGORIES = [
|
|
26
|
+
{ name: 'MAJOR', maxOrb: 2 }, // Orb < 2°
|
|
27
|
+
{ name: 'MODERATE', minOrb: 2, maxOrb: 4 }, // Orb 2-4°
|
|
28
|
+
];
|
|
25
29
|
exports.DEFAULT_SETTINGS = {
|
|
26
30
|
// sign settings
|
|
27
|
-
includeSignDegree: true,
|
|
28
|
-
omitSigns: false,
|
|
31
|
+
includeSignDegree: true, // For planets list: "Sun: 8° Cancer" vs "Sun: Cancer"
|
|
29
32
|
// house settings
|
|
30
|
-
|
|
31
|
-
includeHouseDegree: false,
|
|
32
|
-
omitHouses: false,
|
|
33
|
+
includeHouseDegree: false, // New format shows "House X", not degree in house for planets list
|
|
33
34
|
// point settings
|
|
34
|
-
includeAscendant: true,
|
|
35
|
-
omitPoints: false,
|
|
35
|
+
includeAscendant: true, // Legacy, ASC/MC now have dedicated [ANGLES] section
|
|
36
36
|
// orb + aspect settings
|
|
37
37
|
aspectDefinitions: exports.DEFAULT_ASPECTS,
|
|
38
|
-
|
|
38
|
+
aspectCategories: exports.DEFAULT_ASPECT_CATEGORIES,
|
|
39
|
+
dateFormat: 'MM/DD/YYYY', // As per example output
|
|
39
40
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Point, Aspect, AspectData } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Identifies aspects between planets in a single chart.
|
|
4
|
+
* @param aspectDefinitions Array of aspect types to check for.
|
|
5
|
+
* @param planets Array of planet points.
|
|
6
|
+
* @returns Array of found aspects.
|
|
7
|
+
*/
|
|
8
|
+
export declare function calculateAspects(aspectDefinitions: Aspect[], planets: Point[]): AspectData[];
|
|
9
|
+
/**
|
|
10
|
+
* Identifies aspects between planets across two charts.
|
|
11
|
+
* PlanetA is always from chart1Planets, PlanetB always from chart2Planets.
|
|
12
|
+
* @param aspectDefinitions Array of aspect types to check for.
|
|
13
|
+
* @param chart1Planets Array of planet points for the first chart.
|
|
14
|
+
* @param chart2Planets Array of planet points for the second chart.
|
|
15
|
+
* @returns Array of found aspects.
|
|
16
|
+
*/
|
|
17
|
+
export declare function calculateMultichartAspects(aspectDefinitions: Aspect[], chart1Planets: Point[], chart2Planets: Point[]): AspectData[];
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateAspects = calculateAspects;
|
|
4
|
+
exports.calculateMultichartAspects = calculateMultichartAspects;
|
|
5
|
+
/**
|
|
6
|
+
* Identifies aspects between planets in a single chart.
|
|
7
|
+
* @param aspectDefinitions Array of aspect types to check for.
|
|
8
|
+
* @param planets Array of planet points.
|
|
9
|
+
* @returns Array of found aspects.
|
|
10
|
+
*/
|
|
11
|
+
function calculateAspects(aspectDefinitions, planets) {
|
|
12
|
+
const aspects = [];
|
|
13
|
+
if (!planets || planets.length < 2)
|
|
14
|
+
return aspects;
|
|
15
|
+
for (let i = 0; i < planets.length; i++) {
|
|
16
|
+
for (let j = i + 1; j < planets.length; j++) {
|
|
17
|
+
const planetA = planets[i];
|
|
18
|
+
const planetB = planets[j];
|
|
19
|
+
let diff = Math.abs(planetA.degree - planetB.degree);
|
|
20
|
+
if (diff > 180)
|
|
21
|
+
diff = 360 - diff;
|
|
22
|
+
// Find the tightest valid aspect
|
|
23
|
+
let tightestAspect = null;
|
|
24
|
+
for (const aspectType of aspectDefinitions) {
|
|
25
|
+
const orb = Math.abs(diff - aspectType.angle);
|
|
26
|
+
if (orb <= aspectType.orb) {
|
|
27
|
+
if (!tightestAspect || orb < tightestAspect.orb) {
|
|
28
|
+
tightestAspect = {
|
|
29
|
+
planetA: planetA.name,
|
|
30
|
+
planetB: planetB.name,
|
|
31
|
+
aspectType: aspectType.name,
|
|
32
|
+
orb,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (tightestAspect) {
|
|
38
|
+
aspects.push(tightestAspect);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return aspects;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Identifies aspects between planets across two charts.
|
|
46
|
+
* PlanetA is always from chart1Planets, PlanetB always from chart2Planets.
|
|
47
|
+
* @param aspectDefinitions Array of aspect types to check for.
|
|
48
|
+
* @param chart1Planets Array of planet points for the first chart.
|
|
49
|
+
* @param chart2Planets Array of planet points for the second chart.
|
|
50
|
+
* @returns Array of found aspects.
|
|
51
|
+
*/
|
|
52
|
+
function calculateMultichartAspects(aspectDefinitions, chart1Planets, chart2Planets) {
|
|
53
|
+
const aspects = [];
|
|
54
|
+
if (!chart1Planets ||
|
|
55
|
+
!chart2Planets ||
|
|
56
|
+
chart1Planets.length === 0 ||
|
|
57
|
+
chart2Planets.length === 0) {
|
|
58
|
+
return aspects;
|
|
59
|
+
}
|
|
60
|
+
for (const p1 of chart1Planets) {
|
|
61
|
+
for (const p2 of chart2Planets) {
|
|
62
|
+
let diff = Math.abs(p1.degree - p2.degree);
|
|
63
|
+
if (diff > 180)
|
|
64
|
+
diff = 360 - diff;
|
|
65
|
+
// Find the tightest valid aspect
|
|
66
|
+
let tightestAspect = null;
|
|
67
|
+
for (const aspectType of aspectDefinitions) {
|
|
68
|
+
const orb = Math.abs(diff - aspectType.angle);
|
|
69
|
+
if (orb <= aspectType.orb) {
|
|
70
|
+
if (!tightestAspect || orb < tightestAspect.orb) {
|
|
71
|
+
tightestAspect = {
|
|
72
|
+
planetA: p1.name, // From chart1
|
|
73
|
+
planetB: p2.name, // From chart2
|
|
74
|
+
aspectType: aspectType.name,
|
|
75
|
+
orb,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (tightestAspect) {
|
|
81
|
+
aspects.push(tightestAspect);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return aspects;
|
|
86
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines the zodiac sign for a given degree.
|
|
3
|
+
* @param degree The absolute degree (0-359.99...).
|
|
4
|
+
* @returns The zodiac sign name.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getDegreeSign(degree: number): string;
|
|
7
|
+
/**
|
|
8
|
+
* Calculates the degree within its 30-degree sign (0-29.99...).
|
|
9
|
+
* @param degree The absolute degree (0-359.99...).
|
|
10
|
+
* @returns The degree within the sign.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getDegreeInSign(degree: number): number;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDegreeSign = getDegreeSign;
|
|
4
|
+
exports.getDegreeInSign = getDegreeInSign;
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
/**
|
|
7
|
+
* Determines the zodiac sign for a given degree.
|
|
8
|
+
* @param degree The absolute degree (0-359.99...).
|
|
9
|
+
* @returns The zodiac sign name.
|
|
10
|
+
*/
|
|
11
|
+
function getDegreeSign(degree) {
|
|
12
|
+
const signIndex = Math.floor(degree / 30) % 12;
|
|
13
|
+
if (signIndex < 0 || signIndex >= constants_1.ZODIAC_SIGNS.length) {
|
|
14
|
+
// This should ideally not happen with degree % 12 logic if degree is positive
|
|
15
|
+
console.error(`Invalid sign index computed: ${signIndex} for degree ${degree}`);
|
|
16
|
+
return 'Unknown Sign';
|
|
17
|
+
}
|
|
18
|
+
return constants_1.ZODIAC_SIGNS[signIndex];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Calculates the degree within its 30-degree sign (0-29.99...).
|
|
22
|
+
* @param degree The absolute degree (0-359.99...).
|
|
23
|
+
* @returns The degree within the sign.
|
|
24
|
+
*/
|
|
25
|
+
function getDegreeInSign(degree) {
|
|
26
|
+
return degree % 30;
|
|
27
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the [ANGLES] section of the chart output.
|
|
3
|
+
* @param ascDegree The degree of the Ascendant.
|
|
4
|
+
* @param mcDegree The degree of the Midheaven.
|
|
5
|
+
* @returns An array of strings for the output.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateAnglesOutput(ascDegree?: number, mcDegree?: number): string[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateAnglesOutput = generateAnglesOutput;
|
|
4
|
+
const astrology_1 = require("../../../core/astrology");
|
|
5
|
+
/**
|
|
6
|
+
* Generates the [ANGLES] section of the chart output.
|
|
7
|
+
* @param ascDegree The degree of the Ascendant.
|
|
8
|
+
* @param mcDegree The degree of the Midheaven.
|
|
9
|
+
* @returns An array of strings for the output.
|
|
10
|
+
*/
|
|
11
|
+
function generateAnglesOutput(ascDegree, mcDegree) {
|
|
12
|
+
const output = ['[ANGLES]'];
|
|
13
|
+
if (ascDegree !== undefined) {
|
|
14
|
+
output.push(`ASC: ${Math.floor((0, astrology_1.getDegreeInSign)(ascDegree))}° ${(0, astrology_1.getDegreeSign)(ascDegree)}`);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
output.push('ASC: Not available');
|
|
18
|
+
}
|
|
19
|
+
if (mcDegree !== undefined) {
|
|
20
|
+
output.push(`MC: ${Math.floor((0, astrology_1.getDegreeInSign)(mcDegree))}° ${(0, astrology_1.getDegreeSign)(mcDegree)}`);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
output.push('MC: Not available');
|
|
24
|
+
}
|
|
25
|
+
return output;
|
|
26
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AspectData } from '../../../types';
|
|
2
|
+
import { ChartSettings } from '../../../config/ChartSettings';
|
|
3
|
+
/**
|
|
4
|
+
* Generates aspect sections (e.g., [ASPECTS], [PLANET-PLANET ASPECTS], [TRANSIT ASPECTS: Name]).
|
|
5
|
+
* @param title The main title for this aspect block (e.g., "[ASPECTS]").
|
|
6
|
+
* @param aspects Array of calculated aspect data.
|
|
7
|
+
* @param settings The chart settings, containing aspect categories.
|
|
8
|
+
* @param p1ChartName Optional: Name of the first chart/entity for synastry/transit aspects.
|
|
9
|
+
* @param p2ChartName Optional: Name of the second chart/entity for synastry aspects.
|
|
10
|
+
* @param p2IsTransit Optional: Boolean indicating if p2 represents transiting points.
|
|
11
|
+
* @returns An array of strings for the output.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateAspectsOutput(title: string, aspects: AspectData[], settings: ChartSettings, p1ChartName?: string, p2ChartName?: string, // For synastry, this is the second person's name. For transits, it could be "Current" or the transit chart name.
|
|
14
|
+
p2IsTransit?: boolean): string[];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateAspectsOutput = generateAspectsOutput;
|
|
4
|
+
/**
|
|
5
|
+
* Generates aspect sections (e.g., [ASPECTS], [PLANET-PLANET ASPECTS], [TRANSIT ASPECTS: Name]).
|
|
6
|
+
* @param title The main title for this aspect block (e.g., "[ASPECTS]").
|
|
7
|
+
* @param aspects Array of calculated aspect data.
|
|
8
|
+
* @param settings The chart settings, containing aspect categories.
|
|
9
|
+
* @param p1ChartName Optional: Name of the first chart/entity for synastry/transit aspects.
|
|
10
|
+
* @param p2ChartName Optional: Name of the second chart/entity for synastry aspects.
|
|
11
|
+
* @param p2IsTransit Optional: Boolean indicating if p2 represents transiting points.
|
|
12
|
+
* @returns An array of strings for the output.
|
|
13
|
+
*/
|
|
14
|
+
function generateAspectsOutput(title, aspects, settings, p1ChartName, p2ChartName, // For synastry, this is the second person's name. For transits, it could be "Current" or the transit chart name.
|
|
15
|
+
p2IsTransit = false) {
|
|
16
|
+
const output = [title];
|
|
17
|
+
let aspectsFoundInAnyCategory = false;
|
|
18
|
+
settings.aspectCategories.forEach((category) => {
|
|
19
|
+
const categoryAspects = aspects.filter((asp) => {
|
|
20
|
+
const orb = asp.orb;
|
|
21
|
+
const minOrbCheck = category.minOrb === undefined ? true : orb > category.minOrb;
|
|
22
|
+
const maxOrbCheck = orb <= category.maxOrb;
|
|
23
|
+
return minOrbCheck && maxOrbCheck;
|
|
24
|
+
});
|
|
25
|
+
if (categoryAspects.length > 0) {
|
|
26
|
+
aspectsFoundInAnyCategory = true;
|
|
27
|
+
let orbRangeStr = `orb < ${category.maxOrb.toFixed(1)}°`;
|
|
28
|
+
if (category.minOrb !== undefined) {
|
|
29
|
+
// Ensure minOrb is less than maxOrb for sensible range string
|
|
30
|
+
orbRangeStr =
|
|
31
|
+
category.minOrb < category.maxOrb
|
|
32
|
+
? `orb ${category.minOrb.toFixed(1)}-${category.maxOrb.toFixed(1)}°`
|
|
33
|
+
: `orb > ${category.minOrb.toFixed(1)}° & < ${category.maxOrb.toFixed(1)}°`; // Fallback for unusual category def
|
|
34
|
+
}
|
|
35
|
+
output.push(`[${category.name.toUpperCase()}: ${orbRangeStr}]`);
|
|
36
|
+
categoryAspects.sort((a, b) => a.orb - b.orb); // Sort by orb tightness
|
|
37
|
+
categoryAspects.forEach((asp) => {
|
|
38
|
+
const p1NameStr = p1ChartName
|
|
39
|
+
? `${p1ChartName}'s ${asp.planetA}`
|
|
40
|
+
: asp.planetA;
|
|
41
|
+
let p2NameStr = asp.planetB;
|
|
42
|
+
if (p2IsTransit) {
|
|
43
|
+
// For "Transit Aspects: Alice", p1 is Alice, p2 is the transiting planet.
|
|
44
|
+
// Example: "Alice's Mercury opposition transiting Neptune: 0.3°" - here p2ChartName is not used for the planet itself.
|
|
45
|
+
p2NameStr = `transiting ${asp.planetB}`;
|
|
46
|
+
}
|
|
47
|
+
else if (p2ChartName) {
|
|
48
|
+
// For "Synastry: Alice-Bob", "Planet-Planet Aspects"
|
|
49
|
+
// Example: "Alice's Mercury opposition Bob's Neptune: 0.3°"
|
|
50
|
+
p2NameStr = `${p2ChartName}'s ${asp.planetB}`;
|
|
51
|
+
}
|
|
52
|
+
// If neither p2IsTransit nor p2ChartName, it's a natal chart aspect, e.g. "Venus opposition Pluto: 1.2°"
|
|
53
|
+
output.push(`${p1NameStr} ${asp.aspectType} ${p2NameStr}: ${asp.orb.toFixed(1)}°`);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
if (!aspectsFoundInAnyCategory && aspects.length > 0) {
|
|
58
|
+
output.push('No aspects within defined categories.');
|
|
59
|
+
}
|
|
60
|
+
else if (aspects.length === 0) {
|
|
61
|
+
output.push('None');
|
|
62
|
+
}
|
|
63
|
+
return output;
|
|
64
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ChartSettings } from '../../../config/ChartSettings';
|
|
2
|
+
/**
|
|
3
|
+
* Generates the [BIRTHDATA] or [DATETIME] section.
|
|
4
|
+
* @param location The location string.
|
|
5
|
+
* @param timestamp The Date object for the event.
|
|
6
|
+
* @param settings The chart settings, used for date formatting.
|
|
7
|
+
* @param sectionTitle The title for the section (e.g., "[BIRTHDATA]", "[DATETIME]").
|
|
8
|
+
* @returns An array of strings for the output.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateBirthdataOutput(location: string | undefined, timestamp: Date | undefined, settings: ChartSettings, sectionTitle?: string): string[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateBirthdataOutput = generateBirthdataOutput;
|
|
4
|
+
const datetime_1 = require("../../../utils/datetime");
|
|
5
|
+
/**
|
|
6
|
+
* Generates the [BIRTHDATA] or [DATETIME] section.
|
|
7
|
+
* @param location The location string.
|
|
8
|
+
* @param timestamp The Date object for the event.
|
|
9
|
+
* @param settings The chart settings, used for date formatting.
|
|
10
|
+
* @param sectionTitle The title for the section (e.g., "[BIRTHDATA]", "[DATETIME]").
|
|
11
|
+
* @returns An array of strings for the output.
|
|
12
|
+
*/
|
|
13
|
+
function generateBirthdataOutput(location, timestamp, settings, sectionTitle = '[BIRTHDATA]') {
|
|
14
|
+
if (!timestamp)
|
|
15
|
+
return [`${sectionTitle} Not available`];
|
|
16
|
+
const dateStr = (0, datetime_1.formatDateCustom)(timestamp, settings.dateFormat);
|
|
17
|
+
const timeStr = (0, datetime_1.formatTime)(timestamp);
|
|
18
|
+
return [
|
|
19
|
+
`${sectionTitle} ${location || 'Unknown Location'}, ${dateStr}, ${timeStr}`,
|
|
20
|
+
];
|
|
21
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates the chart header line (e.g., "[CHART: Alice]", "[SYNASTRY: Alice-Bob]").
|
|
3
|
+
* @param chartName The name of the chart or chart combination.
|
|
4
|
+
* @param prefix The prefix for the header (e.g., "CHART", "SYNASTRY", "TRANSIT").
|
|
5
|
+
* @returns An array containing a single string for the header line.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateChartHeaderOutput(chartName: string | undefined, prefix?: string): string[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateChartHeaderOutput = generateChartHeaderOutput;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the chart header line (e.g., "[CHART: Alice]", "[SYNASTRY: Alice-Bob]").
|
|
6
|
+
* @param chartName The name of the chart or chart combination.
|
|
7
|
+
* @param prefix The prefix for the header (e.g., "CHART", "SYNASTRY", "TRANSIT").
|
|
8
|
+
* @returns An array containing a single string for the header line.
|
|
9
|
+
*/
|
|
10
|
+
function generateChartHeaderOutput(chartName, prefix = 'CHART') {
|
|
11
|
+
return [`[${prefix}: ${chartName || 'Unknown'}]`];
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ChartData } from '../../../types';
|
|
2
|
+
import { ChartSettings } from '../../../config/ChartSettings';
|
|
3
|
+
/**
|
|
4
|
+
* Generates the [HOUSE OVERLAYS] section for synastry.
|
|
5
|
+
* @param chart1 The first chart data.
|
|
6
|
+
* @param chart2 The second chart data.
|
|
7
|
+
* @param settings The chart settings, containing the house system calculator.
|
|
8
|
+
* @returns An array of strings for the output.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateHouseOverlaysOutput(chart1: ChartData, chart2: ChartData, settings: ChartSettings): string[];
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateHouseOverlaysOutput = generateHouseOverlaysOutput;
|
|
4
|
+
// Helper function to determine which house a point falls into
|
|
5
|
+
function getHouseForPoint(pointDegree, houseCusps) {
|
|
6
|
+
if (!houseCusps || houseCusps.length !== 12) {
|
|
7
|
+
// console.error("Invalid or missing houseCusps array for getHouseForPoint.");
|
|
8
|
+
return 0; // Indicate failure or inability to calculate
|
|
9
|
+
}
|
|
10
|
+
for (let i = 0; i < 12; i++) {
|
|
11
|
+
const cuspStart = houseCusps[i]; // Cusp of current house (e.g., for House 1, i=0, cuspStart = Cusp 1)
|
|
12
|
+
const cuspEnd = houseCusps[(i + 1) % 12]; // Cusp of next house (e.g., for House 1, cuspEnd = Cusp 2)
|
|
13
|
+
// Check if the point degree falls between cuspStart and cuspEnd
|
|
14
|
+
if (cuspStart < cuspEnd) {
|
|
15
|
+
// Normal case: e.g., Cusp1=10, Cusp2=40. Point is between 10 and 40.
|
|
16
|
+
if (pointDegree >= cuspStart && pointDegree < cuspEnd) {
|
|
17
|
+
return i + 1; // House number is i+1 (cusps are 0-indexed, houses 1-indexed)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// Wrap-around case: e.g., Cusp12=330, Cusp1=20. Point is >=330 OR <20.
|
|
22
|
+
if (pointDegree >= cuspStart || pointDegree < cuspEnd) {
|
|
23
|
+
return i + 1; // House number is i+1
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// console.warn(`Point ${pointDegree} did not fall into any house with cusps: ${houseCusps.join(', ')}.`);
|
|
28
|
+
return 0; // Should ideally not be reached if cusps correctly cover 360 degrees
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generates the [HOUSE OVERLAYS] section for synastry.
|
|
32
|
+
* @param chart1 The first chart data.
|
|
33
|
+
* @param chart2 The second chart data.
|
|
34
|
+
* @param settings The chart settings, containing the house system calculator.
|
|
35
|
+
* @returns An array of strings for the output.
|
|
36
|
+
*/
|
|
37
|
+
function generateHouseOverlaysOutput(chart1, chart2, settings) {
|
|
38
|
+
const output = ['[HOUSE OVERLAYS]'];
|
|
39
|
+
const c1Name = chart1.name || 'Chart 1';
|
|
40
|
+
const c2Name = chart2.name || 'Chart 2';
|
|
41
|
+
// Chart 1's planets in Chart 2's houses
|
|
42
|
+
if (chart2.houseCusps && chart2.houseCusps.length === 12) {
|
|
43
|
+
output.push(`${c1Name}'s planets in ${c2Name}'s houses:`);
|
|
44
|
+
if (chart1.planets && chart1.planets.length > 0) {
|
|
45
|
+
chart1.planets.forEach((planet) => {
|
|
46
|
+
const houseNumber = getHouseForPoint(planet.degree, chart2.houseCusps);
|
|
47
|
+
if (houseNumber > 0) {
|
|
48
|
+
output.push(`${planet.name}: House ${houseNumber}`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
output.push(`${planet.name}: (Could not determine house in ${c2Name})`);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
output.push('(No planets listed for overlay)');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
output.push(`${c1Name}'s planets in ${c2Name}'s houses: (${c2Name} house cusps not available)`);
|
|
61
|
+
}
|
|
62
|
+
output.push(''); // Blank line between the two overlay sections
|
|
63
|
+
// Chart 2's planets in Chart 1's houses
|
|
64
|
+
if (chart1.houseCusps && chart1.houseCusps.length === 12) {
|
|
65
|
+
output.push(`${c2Name}'s planets in ${c1Name}'s houses:`);
|
|
66
|
+
if (chart2.planets && chart2.planets.length > 0) {
|
|
67
|
+
chart2.planets.forEach((planet) => {
|
|
68
|
+
const houseNumber = getHouseForPoint(planet.degree, chart1.houseCusps);
|
|
69
|
+
if (houseNumber > 0) {
|
|
70
|
+
output.push(`${planet.name}: House ${houseNumber}`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
output.push(`${planet.name}: (Could not determine house in ${c1Name})`);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
output.push('(No planets listed for overlay)');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
output.push(`${c2Name}'s planets in ${c1Name}'s houses: (${c1Name} house cusps not available)`);
|
|
83
|
+
}
|
|
84
|
+
return output;
|
|
85
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ChartSettings } from '../../../config/ChartSettings';
|
|
2
|
+
/**
|
|
3
|
+
* Generates the [METADATA] section of the chart output.
|
|
4
|
+
* @param settings The chart settings.
|
|
5
|
+
* @param chartType A string describing the type of chart (e.g., "natal", "synastry").
|
|
6
|
+
* @param houseSystemName Optional: The name of the house system used.
|
|
7
|
+
* @returns An array of strings, each representing a line in the output.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateMetadataOutput(settings: ChartSettings, chartType: string, houseSystemName?: string): string[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMetadataOutput = generateMetadataOutput;
|
|
4
|
+
/**
|
|
5
|
+
* Generates the [METADATA] section of the chart output.
|
|
6
|
+
* @param settings The chart settings.
|
|
7
|
+
* @param chartType A string describing the type of chart (e.g., "natal", "synastry").
|
|
8
|
+
* @param houseSystemName Optional: The name of the house system used.
|
|
9
|
+
* @returns An array of strings, each representing a line in the output.
|
|
10
|
+
*/
|
|
11
|
+
function generateMetadataOutput(settings, chartType, houseSystemName) {
|
|
12
|
+
const output = ['[METADATA]', `chart_type: ${chartType}`];
|
|
13
|
+
if (houseSystemName) {
|
|
14
|
+
output.push(`house_system: ${houseSystemName}`);
|
|
15
|
+
}
|
|
16
|
+
output.push(`date_format: ${settings.dateFormat}`);
|
|
17
|
+
return output;
|
|
18
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Point } from '../../../types';
|
|
2
|
+
import { ChartSettings } from '../../../config/ChartSettings';
|
|
3
|
+
/**
|
|
4
|
+
* Generates the [PLANETS] section of the chart output.
|
|
5
|
+
* @param planets Array of planet points.
|
|
6
|
+
* @param houseCusps Array of 12 house cusp degrees, or undefined if not available.
|
|
7
|
+
* @param settings The chart settings.
|
|
8
|
+
* @returns An array of strings for the output.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generatePlanetsOutput(planets: Point[], houseCusps: number[] | undefined, settings: ChartSettings): string[];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generatePlanetsOutput = generatePlanetsOutput;
|
|
4
|
+
const astrology_1 = require("../../../core/astrology");
|
|
5
|
+
// Helper function to determine which house a point falls into
|
|
6
|
+
// (Copied from houseOverlays.ts - consider moving to a shared util if used in more places)
|
|
7
|
+
function getHouseForPoint(pointDegree, houseCusps) {
|
|
8
|
+
if (!houseCusps || houseCusps.length !== 12) {
|
|
9
|
+
return 0; // Indicate failure or inability to calculate
|
|
10
|
+
}
|
|
11
|
+
for (let i = 0; i < 12; i++) {
|
|
12
|
+
const cuspStart = houseCusps[i];
|
|
13
|
+
const cuspEnd = houseCusps[(i + 1) % 12];
|
|
14
|
+
if (cuspStart < cuspEnd) {
|
|
15
|
+
if (pointDegree >= cuspStart && pointDegree < cuspEnd) {
|
|
16
|
+
return i + 1;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
if (pointDegree >= cuspStart || pointDegree < cuspEnd) {
|
|
21
|
+
return i + 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return 0; // Should not be reached if cusps cover 360 degrees
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Generates the [PLANETS] section of the chart output.
|
|
29
|
+
* @param planets Array of planet points.
|
|
30
|
+
* @param houseCusps Array of 12 house cusp degrees, or undefined if not available.
|
|
31
|
+
* @param settings The chart settings.
|
|
32
|
+
* @returns An array of strings for the output.
|
|
33
|
+
*/
|
|
34
|
+
function generatePlanetsOutput(planets, houseCusps, settings) {
|
|
35
|
+
const output = ['[PLANETS]'];
|
|
36
|
+
planets.forEach((planet) => {
|
|
37
|
+
const sign = (0, astrology_1.getDegreeSign)(planet.degree);
|
|
38
|
+
const degInSign = Math.floor((0, astrology_1.getDegreeInSign)(planet.degree));
|
|
39
|
+
const retrogradeIndicator = planet.speed !== undefined && planet.speed < 0 ? ' Rx' : '';
|
|
40
|
+
let line = `${planet.name}: ${degInSign}° ${sign}${retrogradeIndicator}`;
|
|
41
|
+
if (houseCusps && houseCusps.length === 12) {
|
|
42
|
+
const houseNumber = getHouseForPoint(planet.degree, houseCusps);
|
|
43
|
+
if (houseNumber > 0) {
|
|
44
|
+
line += `, House ${houseNumber}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
output.push(line);
|
|
48
|
+
});
|
|
49
|
+
if (planets.length === 0) {
|
|
50
|
+
output.push('No planets listed.');
|
|
51
|
+
}
|
|
52
|
+
return output;
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChartData, MultiChartData, PartialSettings } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Orchestrates the generation of a complete astrological chart report in text format.
|
|
4
|
+
* @param data The chart data, can be for a single chart or multiple charts (synastry, transits).
|
|
5
|
+
* @param partialSettings Optional: Custom settings to override defaults.
|
|
6
|
+
* @returns A string representing the full chart report.
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatChartToText(data: ChartData | MultiChartData, partialSettings?: PartialSettings): string;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatChartToText = formatChartToText;
|
|
4
|
+
const ChartSettings_1 = require("../../config/ChartSettings");
|
|
5
|
+
const aspects_1 = require("../../core/aspects");
|
|
6
|
+
const metadata_1 = require("./sections/metadata");
|
|
7
|
+
const chartHeader_1 = require("./sections/chartHeader");
|
|
8
|
+
const birthdata_1 = require("./sections/birthdata");
|
|
9
|
+
const angles_1 = require("./sections/angles");
|
|
10
|
+
const planets_1 = require("./sections/planets");
|
|
11
|
+
const aspects_2 = require("./sections/aspects");
|
|
12
|
+
const houseOverlays_1 = require("./sections/houseOverlays");
|
|
13
|
+
/**
|
|
14
|
+
* Orchestrates the generation of a complete astrological chart report in text format.
|
|
15
|
+
* @param data The chart data, can be for a single chart or multiple charts (synastry, transits).
|
|
16
|
+
* @param partialSettings Optional: Custom settings to override defaults.
|
|
17
|
+
* @returns A string representing the full chart report.
|
|
18
|
+
*/
|
|
19
|
+
function formatChartToText(data, partialSettings = {}) {
|
|
20
|
+
const settings = new ChartSettings_1.ChartSettings(partialSettings);
|
|
21
|
+
const outputLines = [];
|
|
22
|
+
let baseChartType = 'natal';
|
|
23
|
+
let primaryHouseSystemName;
|
|
24
|
+
if ('chart1' in data) {
|
|
25
|
+
// Check if it's MultiChartData
|
|
26
|
+
const multiData = data;
|
|
27
|
+
primaryHouseSystemName = multiData.chart1.houseSystemName; // Use chart1's house system name for overall metadata
|
|
28
|
+
if (multiData.chart2 && multiData.transit)
|
|
29
|
+
baseChartType = 'synastry_with_transit';
|
|
30
|
+
else if (multiData.chart2)
|
|
31
|
+
baseChartType = 'synastry';
|
|
32
|
+
else if (multiData.transit)
|
|
33
|
+
baseChartType = 'natal_with_transit';
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Single ChartData object
|
|
37
|
+
primaryHouseSystemName = data.houseSystemName;
|
|
38
|
+
}
|
|
39
|
+
outputLines.push(...(0, metadata_1.generateMetadataOutput)(settings, baseChartType, primaryHouseSystemName));
|
|
40
|
+
outputLines.push(''); // Blank line after metadata
|
|
41
|
+
const processSingleChartOutput = (chartData, chartTitlePrefix) => {
|
|
42
|
+
outputLines.push(...(0, chartHeader_1.generateChartHeaderOutput)(chartData.name, chartTitlePrefix));
|
|
43
|
+
outputLines.push(...(0, birthdata_1.generateBirthdataOutput)(chartData.location, chartData.timestamp, settings));
|
|
44
|
+
outputLines.push(...(0, angles_1.generateAnglesOutput)(chartData.ascendant, chartData.midheaven));
|
|
45
|
+
outputLines.push(...(0, planets_1.generatePlanetsOutput)(chartData.planets, chartData.houseCusps, settings));
|
|
46
|
+
const aspects = (0, aspects_1.calculateAspects)(settings.aspectDefinitions, chartData.planets);
|
|
47
|
+
// For single chart, p1ChartName and p2ChartName are not needed for aspect string generation
|
|
48
|
+
outputLines.push(...(0, aspects_2.generateAspectsOutput)('[ASPECTS]', aspects, settings));
|
|
49
|
+
outputLines.push('');
|
|
50
|
+
};
|
|
51
|
+
const processTransitChartInfoOutput = (transitData) => {
|
|
52
|
+
outputLines.push(...(0, chartHeader_1.generateChartHeaderOutput)(transitData.name || 'Current', 'TRANSIT'));
|
|
53
|
+
outputLines.push(...(0, birthdata_1.generateBirthdataOutput)(transitData.location, transitData.timestamp, settings, '[DATETIME]'));
|
|
54
|
+
// For transit chart's own planets, houses are usually not shown unless it's a full natal chart for that moment.
|
|
55
|
+
outputLines.push(...(0, planets_1.generatePlanetsOutput)(transitData.planets, transitData.houseCusps, settings));
|
|
56
|
+
outputLines.push('');
|
|
57
|
+
};
|
|
58
|
+
if ('chart1' in data) {
|
|
59
|
+
// MultiChartData
|
|
60
|
+
const multiData = data;
|
|
61
|
+
const chart1 = multiData.chart1;
|
|
62
|
+
const chart1Name = chart1.name || 'Chart 1';
|
|
63
|
+
processSingleChartOutput(chart1);
|
|
64
|
+
if (multiData.chart2) {
|
|
65
|
+
const chart2 = multiData.chart2;
|
|
66
|
+
const chart2Name = chart2.name || 'Chart 2';
|
|
67
|
+
processSingleChartOutput(chart2);
|
|
68
|
+
// Synastry Section
|
|
69
|
+
outputLines.push(...(0, chartHeader_1.generateChartHeaderOutput)(`${chart1Name}-${chart2Name}`, 'SYNASTRY'));
|
|
70
|
+
const synastryAspects = (0, aspects_1.calculateMultichartAspects)(settings.aspectDefinitions, chart1.planets, chart2.planets);
|
|
71
|
+
outputLines.push(...(0, aspects_2.generateAspectsOutput)('[PLANET-PLANET ASPECTS]', synastryAspects, settings, chart1Name, chart2Name));
|
|
72
|
+
outputLines.push('');
|
|
73
|
+
outputLines.push(...(0, houseOverlays_1.generateHouseOverlaysOutput)(chart1, chart2, settings));
|
|
74
|
+
outputLines.push('');
|
|
75
|
+
}
|
|
76
|
+
if (multiData.transit) {
|
|
77
|
+
const transit = multiData.transit;
|
|
78
|
+
const transitName = transit.name || 'Current'; // Used for p2ChartName in transit aspects
|
|
79
|
+
processTransitChartInfoOutput(transit);
|
|
80
|
+
// Transit Aspects to Chart 1
|
|
81
|
+
const transitAspectsC1 = (0, aspects_1.calculateMultichartAspects)(settings.aspectDefinitions, chart1.planets, transit.planets);
|
|
82
|
+
outputLines.push(...(0, aspects_2.generateAspectsOutput)(`[TRANSIT ASPECTS: ${chart1Name}]`, transitAspectsC1, settings, chart1Name, transitName, true));
|
|
83
|
+
outputLines.push('');
|
|
84
|
+
if (multiData.chart2) {
|
|
85
|
+
const chart2Name = multiData.chart2.name || 'Chart 2';
|
|
86
|
+
// Transit Aspects to Chart 2
|
|
87
|
+
const transitAspectsC2 = (0, aspects_1.calculateMultichartAspects)(settings.aspectDefinitions, multiData.chart2.planets, transit.planets);
|
|
88
|
+
outputLines.push(...(0, aspects_2.generateAspectsOutput)(`[TRANSIT ASPECTS: ${chart2Name}]`, transitAspectsC2, settings, chart2Name, transitName, true));
|
|
89
|
+
outputLines.push('');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Single ChartData object
|
|
95
|
+
processSingleChartOutput(data);
|
|
96
|
+
}
|
|
97
|
+
return outputLines.join('\n').trimEnd();
|
|
98
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* chart2txt
|
|
3
|
-
* A library to convert astrological chart data to human-readable text
|
|
3
|
+
* A library to convert astrological chart data to human-readable text.
|
|
4
|
+
*
|
|
5
|
+
* This is the main entry point for the library.
|
|
4
6
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
export default chart2txt;
|
|
7
|
+
export { formatChartToText as chart2txt } from './formatters/text/textFormatter';
|
|
8
|
+
export * from './types';
|
|
9
|
+
export { DEFAULT_SETTINGS, DEFAULT_ASPECTS, DEFAULT_ASPECT_CATEGORIES, ZODIAC_SIGNS, } from './constants';
|
|
10
|
+
export { ChartSettings } from './config/ChartSettings';
|
|
11
|
+
import { formatChartToText } from './formatters/text/textFormatter';
|
|
12
|
+
export default formatChartToText;
|
package/dist/index.js
CHANGED
|
@@ -1,163 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* chart2txt
|
|
4
|
-
* A library to convert astrological chart data to human-readable text
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function
|
|
13
|
-
const signIndex = Math.floor(degree / 30) % 12;
|
|
14
|
-
return constants_1.ZODIAC_SIGNS[signIndex];
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Calculates the house for a given degree, based on the ascendant
|
|
18
|
-
*/
|
|
19
|
-
function getHousePosition(houseSystem, pointDegree, ascendant) {
|
|
20
|
-
switch (houseSystem) {
|
|
21
|
-
case 'equal': {
|
|
22
|
-
// House 1 starts at the ascendant
|
|
23
|
-
const housePosition = (pointDegree - ascendant + 360) % 360;
|
|
24
|
-
const house = Math.floor(housePosition / 30) + 1;
|
|
25
|
-
const degree = housePosition % 30;
|
|
26
|
-
return { house, degree };
|
|
27
|
-
}
|
|
28
|
-
case 'whole_sign': {
|
|
29
|
-
// House 1 starts at beginning of ascendant sign
|
|
30
|
-
const house1SignCusp = (Math.floor(ascendant / 30) % 12) * 30;
|
|
31
|
-
// Computation proceeds same as equal, using sign cusp
|
|
32
|
-
const housePosition = (pointDegree - house1SignCusp + 360) % 360;
|
|
33
|
-
const house = Math.floor(housePosition / 30) + 1;
|
|
34
|
-
const degree = housePosition % 30;
|
|
35
|
-
return { house, degree };
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Identifies aspects between planets
|
|
41
|
-
*/
|
|
42
|
-
function calculateAspects(aspectDefinitions, planets) {
|
|
43
|
-
const aspects = [];
|
|
44
|
-
// Compare each planet with every other planet
|
|
45
|
-
for (let i = 0; i < planets.length; i++) {
|
|
46
|
-
for (let j = i + 1; j < planets.length; j++) {
|
|
47
|
-
const planetA = planets[i];
|
|
48
|
-
const planetB = planets[j];
|
|
49
|
-
// Calculate the angular difference
|
|
50
|
-
let diff = Math.abs(planetA.degree - planetB.degree);
|
|
51
|
-
if (diff > 180)
|
|
52
|
-
diff = 360 - diff;
|
|
53
|
-
// Check against each aspect type
|
|
54
|
-
for (const aspectType of aspectDefinitions) {
|
|
55
|
-
const orb = Math.abs(diff - aspectType.angle);
|
|
56
|
-
if (orb <= aspectType.orb) {
|
|
57
|
-
aspects.push({
|
|
58
|
-
planetA: planetA.name,
|
|
59
|
-
planetB: planetB.name,
|
|
60
|
-
aspectType: aspectType.name,
|
|
61
|
-
orb,
|
|
62
|
-
});
|
|
63
|
-
break; // Only record the strongest aspect between two planets
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return aspects;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Formats planet sign positions as text
|
|
72
|
-
*/
|
|
73
|
-
function formatPlanetSigns(planets, ascendant, points = [], includeDegree = constants_1.DEFAULT_SETTINGS.includeSignDegree) {
|
|
74
|
-
const ascPoint = ascendant
|
|
75
|
-
? [{ name: 'Ascendant', degree: ascendant }]
|
|
76
|
-
: [];
|
|
77
|
-
const output = [...ascPoint, ...planets, ...points]
|
|
78
|
-
.map((planet) => {
|
|
79
|
-
const sign = getDegreeSign(planet.degree);
|
|
80
|
-
if (includeDegree) {
|
|
81
|
-
const degree = Math.floor(planet.degree % 30);
|
|
82
|
-
return `${planet.name} is at ${degree}° ${sign}`;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
return `${planet.name} is in ${sign}`;
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
.join('. ');
|
|
89
|
-
return output ? `${output}.` : '';
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Formats planet house positions as text
|
|
93
|
-
*/
|
|
94
|
-
function formatPlanetHouses(houseSystem, ascendant, planets, points = [], includeDegree = constants_1.DEFAULT_SETTINGS.includeHouseDegree) {
|
|
95
|
-
// TODO: house systems
|
|
96
|
-
const output = [...planets, ...points]
|
|
97
|
-
.map((planet) => {
|
|
98
|
-
const houseData = getHousePosition(houseSystem, planet.degree, ascendant);
|
|
99
|
-
if (includeDegree) {
|
|
100
|
-
return `${planet.name} is at ${houseData.degree}° in house ${houseData.house}`;
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
return `${planet.name} is in house ${houseData.house}`;
|
|
104
|
-
}
|
|
105
|
-
})
|
|
106
|
-
.join('. ');
|
|
107
|
-
return output ? `${output}.` : '';
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Formats aspects between planets as text
|
|
111
|
-
*/
|
|
112
|
-
function formatAspects(aspects) {
|
|
113
|
-
const output = aspects
|
|
114
|
-
.map((aspect) => {
|
|
115
|
-
return `${aspect.planetA} is in ${aspect.aspectType} with ${aspect.planetB} (orb: ${aspect.orb.toFixed(1)}°)`;
|
|
116
|
-
})
|
|
117
|
-
.join('. ');
|
|
118
|
-
return output ? `${output}.` : '';
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Formats provided location and time, if present, as text
|
|
122
|
-
*/
|
|
123
|
-
function formatLocationAndDate(location, timestamp) {
|
|
124
|
-
const locationString = location ? `location: ${location}` : '';
|
|
125
|
-
const timestampString = timestamp ? `at: ${timestamp.toLocaleString()}` : '';
|
|
126
|
-
return [locationString, timestampString].filter((s) => s !== '').join(', ');
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Main function to convert chart data to text
|
|
130
|
-
*/
|
|
131
|
-
function chart2txt(data, settings = {}) {
|
|
132
|
-
// override default settings with any provided settings data
|
|
133
|
-
const fullSettings = Object.assign({}, constants_1.DEFAULT_SETTINGS, settings);
|
|
134
|
-
// format header
|
|
135
|
-
let result = 'Astrology Chart';
|
|
136
|
-
const locationAndDate = formatLocationAndDate(data.location, data.timestamp);
|
|
137
|
-
if (locationAndDate) {
|
|
138
|
-
result += ` (${locationAndDate})`;
|
|
139
|
-
}
|
|
140
|
-
result += ':\n\n';
|
|
141
|
-
// format planets
|
|
142
|
-
if (!fullSettings.omitSigns) {
|
|
143
|
-
result += formatPlanetSigns(data.planets, fullSettings.includeAscendant && data.ascendant
|
|
144
|
-
? data.ascendant
|
|
145
|
-
: undefined, fullSettings.omitPoints ? [] : data.points, fullSettings.includeSignDegree);
|
|
4
|
+
* A library to convert astrological chart data to human-readable text.
|
|
5
|
+
*
|
|
6
|
+
* This is the main entry point for the library.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
146
13
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
//
|
|
163
|
-
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.ChartSettings = exports.ZODIAC_SIGNS = exports.DEFAULT_ASPECT_CATEGORIES = exports.DEFAULT_ASPECTS = exports.DEFAULT_SETTINGS = exports.chart2txt = void 0;
|
|
24
|
+
// Core formatter function
|
|
25
|
+
var textFormatter_1 = require("./formatters/text/textFormatter");
|
|
26
|
+
Object.defineProperty(exports, "chart2txt", { enumerable: true, get: function () { return textFormatter_1.formatChartToText; } });
|
|
27
|
+
// Export all types for library users
|
|
28
|
+
__exportStar(require("./types"), exports);
|
|
29
|
+
// Export constants that might be useful for users (e.g., for custom settings)
|
|
30
|
+
var constants_1 = require("./constants");
|
|
31
|
+
Object.defineProperty(exports, "DEFAULT_SETTINGS", { enumerable: true, get: function () { return constants_1.DEFAULT_SETTINGS; } });
|
|
32
|
+
Object.defineProperty(exports, "DEFAULT_ASPECTS", { enumerable: true, get: function () { return constants_1.DEFAULT_ASPECTS; } });
|
|
33
|
+
Object.defineProperty(exports, "DEFAULT_ASPECT_CATEGORIES", { enumerable: true, get: function () { return constants_1.DEFAULT_ASPECT_CATEGORIES; } });
|
|
34
|
+
Object.defineProperty(exports, "ZODIAC_SIGNS", { enumerable: true, get: function () { return constants_1.ZODIAC_SIGNS; } });
|
|
35
|
+
// Export ChartSettings class for advanced configuration
|
|
36
|
+
var ChartSettings_1 = require("./config/ChartSettings");
|
|
37
|
+
Object.defineProperty(exports, "ChartSettings", { enumerable: true, get: function () { return ChartSettings_1.ChartSettings; } });
|
|
38
|
+
// Default export for convenience (e.g. UMD builds or simple script tags)
|
|
39
|
+
const textFormatter_2 = require("./formatters/text/textFormatter");
|
|
40
|
+
exports.default = textFormatter_2.formatChartToText;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
export interface Point {
|
|
2
2
|
name: string;
|
|
3
3
|
degree: number;
|
|
4
|
+
speed?: number;
|
|
4
5
|
}
|
|
5
6
|
export interface ChartData {
|
|
7
|
+
name?: string;
|
|
6
8
|
planets: Point[];
|
|
7
9
|
ascendant?: number;
|
|
10
|
+
midheaven?: number;
|
|
8
11
|
points?: Point[];
|
|
12
|
+
houseCusps?: number[];
|
|
13
|
+
houseSystemName?: string;
|
|
9
14
|
timestamp?: Date;
|
|
10
15
|
location?: string;
|
|
11
16
|
}
|
|
17
|
+
export interface MultiChartData {
|
|
18
|
+
chart1: ChartData;
|
|
19
|
+
chart2?: ChartData;
|
|
20
|
+
transit?: ChartData;
|
|
21
|
+
}
|
|
22
|
+
export declare function isMultiChartData(obj: ChartData | MultiChartData): obj is MultiChartData;
|
|
12
23
|
export interface Aspect {
|
|
13
24
|
name: string;
|
|
14
25
|
angle: number;
|
|
@@ -20,15 +31,17 @@ export interface AspectData {
|
|
|
20
31
|
aspectType: string;
|
|
21
32
|
orb: number;
|
|
22
33
|
}
|
|
23
|
-
export
|
|
34
|
+
export interface AspectCategory {
|
|
35
|
+
name: string;
|
|
36
|
+
minOrb?: number;
|
|
37
|
+
maxOrb: number;
|
|
38
|
+
}
|
|
24
39
|
export interface Settings {
|
|
25
40
|
includeSignDegree: boolean;
|
|
26
|
-
omitSigns: boolean;
|
|
27
41
|
includeAscendant: boolean;
|
|
28
|
-
omitPoints: boolean;
|
|
29
42
|
includeHouseDegree: boolean;
|
|
30
|
-
houseSystem: HouseSystem;
|
|
31
|
-
omitHouses: boolean;
|
|
32
43
|
aspectDefinitions: Aspect[];
|
|
33
|
-
|
|
44
|
+
aspectCategories: AspectCategory[];
|
|
45
|
+
dateFormat: string;
|
|
34
46
|
}
|
|
47
|
+
export type PartialSettings = Partial<Settings>;
|
package/dist/types.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a Date object into a string based on the specified format.
|
|
3
|
+
* @param date The Date object to format.
|
|
4
|
+
* @param format The target format string (e.g., "MM/DD/YYYY").
|
|
5
|
+
* @returns The formatted date string.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatDateCustom(date: Date, format: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Formats the time part of a Date object.
|
|
10
|
+
* @param date The Date object.
|
|
11
|
+
* @returns The formatted time string (e.g., "09:28:00 AM").
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatTime(date: Date): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDateCustom = formatDateCustom;
|
|
4
|
+
exports.formatTime = formatTime;
|
|
5
|
+
/**
|
|
6
|
+
* Formats a Date object into a string based on the specified format.
|
|
7
|
+
* @param date The Date object to format.
|
|
8
|
+
* @param format The target format string (e.g., "MM/DD/YYYY").
|
|
9
|
+
* @returns The formatted date string.
|
|
10
|
+
*/
|
|
11
|
+
function formatDateCustom(date, format) {
|
|
12
|
+
const m = date.getMonth() + 1;
|
|
13
|
+
const d = date.getDate();
|
|
14
|
+
const y = date.getFullYear();
|
|
15
|
+
switch (format.toUpperCase()) {
|
|
16
|
+
case 'MM/DD/YYYY':
|
|
17
|
+
return `${m.toString().padStart(2, '0')}/${d
|
|
18
|
+
.toString()
|
|
19
|
+
.padStart(2, '0')}/${y}`;
|
|
20
|
+
case 'DD/MM/YYYY':
|
|
21
|
+
return `${d.toString().padStart(2, '0')}/${m
|
|
22
|
+
.toString()
|
|
23
|
+
.padStart(2, '0')}/${y}`;
|
|
24
|
+
case 'YYYY-MM-DD':
|
|
25
|
+
return `${y}-${m.toString().padStart(2, '0')}-${d
|
|
26
|
+
.toString()
|
|
27
|
+
.padStart(2, '0')}`;
|
|
28
|
+
default:
|
|
29
|
+
// Fallback to a common locale string if format is unrecognized
|
|
30
|
+
console.warn(`Unrecognized date format: ${format}. Falling back to toLocaleDateString().`);
|
|
31
|
+
return date.toLocaleDateString();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Formats the time part of a Date object.
|
|
36
|
+
* @param date The Date object.
|
|
37
|
+
* @returns The formatted time string (e.g., "09:28:00 AM").
|
|
38
|
+
*/
|
|
39
|
+
function formatTime(date) {
|
|
40
|
+
return date.toLocaleTimeString('en-US', {
|
|
41
|
+
hour: '2-digit',
|
|
42
|
+
minute: '2-digit',
|
|
43
|
+
second: '2-digit',
|
|
44
|
+
hour12: true,
|
|
45
|
+
});
|
|
46
|
+
}
|