pystylometry 0.1.0__py3-none-any.whl → 1.1.0__py3-none-any.whl

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 (61) hide show
  1. pystylometry/__init__.py +30 -5
  2. pystylometry/_normalize.py +277 -0
  3. pystylometry/_types.py +1954 -28
  4. pystylometry/_utils.py +4 -0
  5. pystylometry/authorship/__init__.py +26 -1
  6. pystylometry/authorship/additional_methods.py +75 -0
  7. pystylometry/authorship/kilgarriff.py +347 -0
  8. pystylometry/character/__init__.py +15 -0
  9. pystylometry/character/character_metrics.py +389 -0
  10. pystylometry/cli.py +427 -0
  11. pystylometry/consistency/__init__.py +57 -0
  12. pystylometry/consistency/_thresholds.py +162 -0
  13. pystylometry/consistency/drift.py +549 -0
  14. pystylometry/dialect/__init__.py +65 -0
  15. pystylometry/dialect/_data/dialect_markers.json +1134 -0
  16. pystylometry/dialect/_loader.py +360 -0
  17. pystylometry/dialect/detector.py +533 -0
  18. pystylometry/lexical/__init__.py +13 -6
  19. pystylometry/lexical/advanced_diversity.py +680 -0
  20. pystylometry/lexical/function_words.py +590 -0
  21. pystylometry/lexical/hapax.py +310 -33
  22. pystylometry/lexical/mtld.py +180 -22
  23. pystylometry/lexical/ttr.py +149 -0
  24. pystylometry/lexical/word_frequency_sophistication.py +1805 -0
  25. pystylometry/lexical/yule.py +142 -29
  26. pystylometry/ngrams/__init__.py +2 -0
  27. pystylometry/ngrams/entropy.py +150 -49
  28. pystylometry/ngrams/extended_ngrams.py +235 -0
  29. pystylometry/prosody/__init__.py +12 -0
  30. pystylometry/prosody/rhythm_prosody.py +53 -0
  31. pystylometry/readability/__init__.py +12 -0
  32. pystylometry/readability/additional_formulas.py +2110 -0
  33. pystylometry/readability/ari.py +173 -35
  34. pystylometry/readability/coleman_liau.py +150 -30
  35. pystylometry/readability/complex_words.py +531 -0
  36. pystylometry/readability/flesch.py +181 -32
  37. pystylometry/readability/gunning_fog.py +208 -35
  38. pystylometry/readability/smog.py +126 -28
  39. pystylometry/readability/syllables.py +137 -30
  40. pystylometry/stylistic/__init__.py +20 -0
  41. pystylometry/stylistic/cohesion_coherence.py +45 -0
  42. pystylometry/stylistic/genre_register.py +45 -0
  43. pystylometry/stylistic/markers.py +131 -0
  44. pystylometry/stylistic/vocabulary_overlap.py +47 -0
  45. pystylometry/syntactic/__init__.py +4 -0
  46. pystylometry/syntactic/advanced_syntactic.py +494 -0
  47. pystylometry/syntactic/pos_ratios.py +172 -17
  48. pystylometry/syntactic/sentence_stats.py +105 -18
  49. pystylometry/syntactic/sentence_types.py +526 -0
  50. pystylometry/viz/__init__.py +71 -0
  51. pystylometry/viz/drift.py +589 -0
  52. pystylometry/viz/jsx/__init__.py +31 -0
  53. pystylometry/viz/jsx/_base.py +144 -0
  54. pystylometry/viz/jsx/report.py +677 -0
  55. pystylometry/viz/jsx/timeline.py +716 -0
  56. pystylometry/viz/jsx/viewer.py +1032 -0
  57. {pystylometry-0.1.0.dist-info → pystylometry-1.1.0.dist-info}/METADATA +49 -9
  58. pystylometry-1.1.0.dist-info/RECORD +63 -0
  59. pystylometry-1.1.0.dist-info/entry_points.txt +4 -0
  60. pystylometry-0.1.0.dist-info/RECORD +0 -26
  61. {pystylometry-0.1.0.dist-info → pystylometry-1.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,144 @@
1
+ """Shared utilities for JSX/HTML visualization exports.
2
+
3
+ This module provides the HTML wrapper template and common utilities
4
+ used by all JSX-based visualizations.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+
14
+ def generate_html_document(
15
+ title: str,
16
+ config: dict[str, Any],
17
+ react_component: str,
18
+ component_name: str,
19
+ extra_styles: str = "",
20
+ ) -> str:
21
+ """
22
+ Generate a self-contained HTML document with React via CDN.
23
+
24
+ Args:
25
+ title: Page title
26
+ config: Configuration object to embed as JSON
27
+ react_component: The React component code (JSX)
28
+ component_name: Name of the root component to render
29
+ extra_styles: Additional CSS styles to include
30
+
31
+ Returns:
32
+ Complete HTML document as string
33
+ """
34
+ config_json = json.dumps(config, indent=2)
35
+
36
+ return f"""<!DOCTYPE html>
37
+ <html lang="en">
38
+ <head>
39
+ <meta charset="UTF-8">
40
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
41
+ <title>{title}</title>
42
+ <script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
43
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
44
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
45
+ <style>
46
+ * {{
47
+ box-sizing: border-box;
48
+ }}
49
+ body {{
50
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
51
+ margin: 0;
52
+ padding: 20px;
53
+ background: #f8fafc;
54
+ color: #1f2937;
55
+ }}
56
+ #root {{
57
+ max-width: 1100px;
58
+ margin: 0 auto;
59
+ }}
60
+ {extra_styles}
61
+ </style>
62
+ </head>
63
+ <body>
64
+ <div id="root"></div>
65
+ <script type="text/babel">
66
+ const CONFIG = {config_json};
67
+
68
+ {react_component}
69
+
70
+ ReactDOM.createRoot(document.getElementById('root')).render(<{component_name} />);
71
+ </script>
72
+ </body>
73
+ </html>"""
74
+
75
+
76
+ def write_html_file(path: str | Path, content: str) -> Path:
77
+ """Write HTML content to file, creating parent directories as needed."""
78
+ output_path = Path(path)
79
+ output_path.parent.mkdir(parents=True, exist_ok=True)
80
+ output_path.write_text(content)
81
+ return output_path
82
+
83
+
84
+ # Shared color interpolation function as a JavaScript string
85
+ COLOR_INTERPOLATION_JS = """
86
+ // Color interpolation: blue -> amber -> red based on distance
87
+ function getPointColor(distance) {
88
+ const colors = [
89
+ { r: 147, g: 197, b: 253 }, // #93c5fd (blue)
90
+ { r: 251, g: 191, b: 36 }, // #fbbf24 (amber)
91
+ { r: 239, g: 68, b: 68 }, // #ef4444 (red)
92
+ ];
93
+
94
+ const t = Math.min(1, Math.max(0, distance));
95
+ let c1, c2, localT;
96
+
97
+ if (t < 0.5) {
98
+ c1 = colors[0];
99
+ c2 = colors[1];
100
+ localT = t * 2;
101
+ } else {
102
+ c1 = colors[1];
103
+ c2 = colors[2];
104
+ localT = (t - 0.5) * 2;
105
+ }
106
+
107
+ const r = Math.round(c1.r + (c2.r - c1.r) * localT);
108
+ const g = Math.round(c1.g + (c2.g - c1.g) * localT);
109
+ const b = Math.round(c1.b + (c2.b - c1.b) * localT);
110
+
111
+ return `rgb(${r}, ${g}, ${b})`;
112
+ }
113
+ """
114
+
115
+
116
+ # Common CSS for cards and panels
117
+ CARD_STYLES = """
118
+ .card {
119
+ background: white;
120
+ border-radius: 8px;
121
+ border: 1px solid #e2e8f0;
122
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
123
+ padding: 16px;
124
+ }
125
+ .card-title {
126
+ margin: 0 0 12px;
127
+ font-size: 14px;
128
+ font-weight: 600;
129
+ color: #1f2937;
130
+ }
131
+ .stat-row {
132
+ display: flex;
133
+ justify-content: space-between;
134
+ padding: 4px 0;
135
+ font-size: 13px;
136
+ color: #4b5563;
137
+ }
138
+ .stat-label {
139
+ font-weight: 500;
140
+ }
141
+ .stat-value {
142
+ font-family: ui-monospace, monospace;
143
+ }
144
+ """