chart2txt 0.3.0 → 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.
Files changed (32) hide show
  1. package/dist/chart2txt.min.js +1 -1
  2. package/dist/config/ChartSettings.d.ts +10 -0
  3. package/dist/config/ChartSettings.js +18 -0
  4. package/dist/constants.d.ts +2 -1
  5. package/dist/constants.js +11 -10
  6. package/dist/core/aspects.d.ts +17 -0
  7. package/dist/core/aspects.js +86 -0
  8. package/dist/core/astrology.d.ts +12 -0
  9. package/dist/core/astrology.js +27 -0
  10. package/dist/formatters/text/sections/angles.d.ts +7 -0
  11. package/dist/formatters/text/sections/angles.js +26 -0
  12. package/dist/formatters/text/sections/aspects.d.ts +14 -0
  13. package/dist/formatters/text/sections/aspects.js +64 -0
  14. package/dist/formatters/text/sections/birthdata.d.ts +10 -0
  15. package/dist/formatters/text/sections/birthdata.js +21 -0
  16. package/dist/formatters/text/sections/chartHeader.d.ts +7 -0
  17. package/dist/formatters/text/sections/chartHeader.js +12 -0
  18. package/dist/formatters/text/sections/houseOverlays.d.ts +10 -0
  19. package/dist/formatters/text/sections/houseOverlays.js +85 -0
  20. package/dist/formatters/text/sections/metadata.d.ts +9 -0
  21. package/dist/formatters/text/sections/metadata.js +18 -0
  22. package/dist/formatters/text/sections/planets.d.ts +10 -0
  23. package/dist/formatters/text/sections/planets.js +53 -0
  24. package/dist/formatters/text/textFormatter.d.ts +8 -0
  25. package/dist/formatters/text/textFormatter.js +98 -0
  26. package/dist/index.d.ts +9 -8
  27. package/dist/index.js +36 -159
  28. package/dist/types.d.ts +19 -6
  29. package/dist/types.js +5 -0
  30. package/dist/utils/datetime.d.ts +13 -0
  31. package/dist/utils/datetime.js +46 -0
  32. package/package.json +45 -45
@@ -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.toISOString()}`:""].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;
@@ -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
- houseSystem: 'equal',
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
- omitAspects: false,
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
- import type { Point, ChartData, Settings } from './types';
6
- /**
7
- * Main function to convert chart data to text
8
- */
9
- export declare function chart2txt(data: ChartData, settings?: Partial<Settings>): string;
10
- export { ChartData, Point, Settings };
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
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.chart2txt = chart2txt;
8
- const constants_1 = require("./constants");
9
- /**
10
- * Determines the zodiac sign for a given degree
11
- */
12
- function getDegreeSign(degree) {
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.toISOString()}` : '';
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
- // format houses
148
- if (!fullSettings.omitHouses && data.ascendant !== undefined) {
149
- result +=
150
- '\n\n' +
151
- formatPlanetHouses(fullSettings.houseSystem, data.ascendant, data.planets, fullSettings.omitPoints ? [] : data.points, fullSettings.includeHouseDegree);
152
- }
153
- // format aspects
154
- if (!fullSettings.omitAspects) {
155
- const aspects = calculateAspects(fullSettings.aspectDefinitions, data.planets);
156
- if (aspects.length > 0) {
157
- result += '\n\n' + formatAspects(aspects);
158
- }
159
- }
160
- return result;
161
- }
162
- // Default export for browser usage
163
- exports.default = chart2txt;
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 type HouseSystem = 'whole_sign' | 'equal';
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
- omitAspects: boolean;
44
+ aspectCategories: AspectCategory[];
45
+ dateFormat: string;
34
46
  }
47
+ export type PartialSettings = Partial<Settings>;
package/dist/types.js CHANGED
@@ -1,2 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isMultiChartData = isMultiChartData;
4
+ function isMultiChartData(obj) {
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ return obj.chart1 !== undefined;
7
+ }
@@ -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
+ }
package/package.json CHANGED
@@ -1,45 +1,45 @@
1
- {
2
- "name": "chart2txt",
3
- "version": "0.3.0",
4
- "description": "Convert astrological chart data to human-readable text",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "browser": "dist/chart2txt.min.js",
8
- "scripts": {
9
- "build": "tsc && webpack",
10
- "build:tsc": "tsc",
11
- "build:webpack": "webpack",
12
- "test": "jest",
13
- "lint": "eslint src/**/*.ts",
14
- "format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\""
15
- },
16
- "keywords": [
17
- "astrology",
18
- "chart",
19
- "text"
20
- ],
21
- "homepage": "https://github.com/simpolism/chart2txt",
22
- "author": "simpolism <simpolism@gmail.com>",
23
- "license": "MIT",
24
- "devDependencies": {
25
- "@types/jest": "^29.5.0",
26
- "@types/node": "^18.0.0",
27
- "@typescript-eslint/eslint-plugin": "^5.0.0",
28
- "@typescript-eslint/parser": "^5.0.0",
29
- "eslint": "^8.0.0",
30
- "eslint-config-prettier": "^8.0.0",
31
- "jest": "^29.0.0",
32
- "prettier": "^2.0.0",
33
- "ts-jest": "^29.1.0",
34
- "ts-loader": "^9.4.4",
35
- "typescript": "^5.0.0",
36
- "webpack": "^5.88.2",
37
- "webpack-cli": "^5.1.4",
38
- "terser-webpack-plugin": "^5.3.9"
39
- },
40
- "files": [
41
- "dist",
42
- "LICENSE",
43
- "README.md"
44
- ]
45
- }
1
+ {
2
+ "name": "chart2txt",
3
+ "version": "0.4.0",
4
+ "description": "Convert astrological chart data to human-readable text",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "browser": "dist/chart2txt.min.js",
8
+ "scripts": {
9
+ "build": "tsc && webpack",
10
+ "build:tsc": "tsc",
11
+ "build:webpack": "webpack",
12
+ "test": "jest",
13
+ "lint": "eslint src/**/*.ts",
14
+ "format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\""
15
+ },
16
+ "keywords": [
17
+ "astrology",
18
+ "chart",
19
+ "text"
20
+ ],
21
+ "homepage": "https://github.com/simpolism/chart2txt",
22
+ "author": "simpolism <simpolism@gmail.com>",
23
+ "license": "MIT",
24
+ "devDependencies": {
25
+ "@types/jest": "^29.5.0",
26
+ "@types/node": "^18.0.0",
27
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
28
+ "@typescript-eslint/parser": "^5.0.0",
29
+ "eslint": "^8.0.0",
30
+ "eslint-config-prettier": "^8.0.0",
31
+ "jest": "^29.0.0",
32
+ "prettier": "^2.0.0",
33
+ "ts-jest": "^29.1.0",
34
+ "ts-loader": "^9.4.4",
35
+ "typescript": "^5.0.0",
36
+ "webpack": "^5.88.2",
37
+ "webpack-cli": "^5.1.4",
38
+ "terser-webpack-plugin": "^5.3.9"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "LICENSE",
43
+ "README.md"
44
+ ]
45
+ }