pystylometry 1.0.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.
- pystylometry/__init__.py +29 -3
- pystylometry/_types.py +963 -259
- pystylometry/authorship/__init__.py +23 -2
- pystylometry/authorship/additional_methods.py +4 -29
- pystylometry/authorship/kilgarriff.py +347 -0
- pystylometry/character/character_metrics.py +267 -179
- pystylometry/cli.py +427 -0
- pystylometry/consistency/__init__.py +57 -0
- pystylometry/consistency/_thresholds.py +162 -0
- pystylometry/consistency/drift.py +549 -0
- pystylometry/dialect/__init__.py +65 -0
- pystylometry/dialect/_data/dialect_markers.json +1134 -0
- pystylometry/dialect/_loader.py +360 -0
- pystylometry/dialect/detector.py +533 -0
- pystylometry/lexical/advanced_diversity.py +61 -22
- pystylometry/lexical/function_words.py +255 -56
- pystylometry/lexical/hapax.py +182 -52
- pystylometry/lexical/mtld.py +108 -26
- pystylometry/lexical/ttr.py +76 -10
- pystylometry/lexical/word_frequency_sophistication.py +1522 -298
- pystylometry/lexical/yule.py +136 -50
- pystylometry/ngrams/entropy.py +150 -49
- pystylometry/readability/additional_formulas.py +1887 -762
- pystylometry/readability/ari.py +144 -82
- pystylometry/readability/coleman_liau.py +136 -109
- pystylometry/readability/flesch.py +177 -73
- pystylometry/readability/gunning_fog.py +165 -161
- pystylometry/readability/smog.py +123 -42
- pystylometry/syntactic/advanced_syntactic.py +76 -14
- pystylometry/syntactic/pos_ratios.py +70 -6
- pystylometry/syntactic/sentence_stats.py +55 -12
- pystylometry/syntactic/sentence_types.py +71 -15
- pystylometry/viz/__init__.py +71 -0
- pystylometry/viz/drift.py +589 -0
- pystylometry/viz/jsx/__init__.py +31 -0
- pystylometry/viz/jsx/_base.py +144 -0
- pystylometry/viz/jsx/report.py +677 -0
- pystylometry/viz/jsx/timeline.py +716 -0
- pystylometry/viz/jsx/viewer.py +1032 -0
- {pystylometry-1.0.0.dist-info → pystylometry-1.1.0.dist-info}/METADATA +5 -2
- pystylometry-1.1.0.dist-info/RECORD +63 -0
- {pystylometry-1.0.0.dist-info → pystylometry-1.1.0.dist-info}/WHEEL +1 -1
- pystylometry-1.1.0.dist-info/entry_points.txt +4 -0
- pystylometry-1.0.0.dist-info/RECORD +0 -46
|
@@ -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
|
+
"""
|