@budiauktioner/buildi-primitives 0.1.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/CHANGELOG.md +51 -0
- package/LICENSE +21 -0
- package/README.md +253 -0
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/banking/index.cjs +6491 -0
- package/dist/banking/index.cjs.map +1 -0
- package/dist/banking/index.d.cts +58 -0
- package/dist/banking/index.d.ts +58 -0
- package/dist/banking/index.js +6464 -0
- package/dist/banking/index.js.map +1 -0
- package/dist/contact/index.cjs +6678 -0
- package/dist/contact/index.cjs.map +1 -0
- package/dist/contact/index.d.cts +709 -0
- package/dist/contact/index.d.ts +709 -0
- package/dist/contact/index.js +6586 -0
- package/dist/contact/index.js.map +1 -0
- package/dist/country-BhD51LDL.d.cts +433 -0
- package/dist/country-p0n0EVQ9.d.ts +433 -0
- package/dist/finance/index.cjs +3592 -0
- package/dist/finance/index.cjs.map +1 -0
- package/dist/finance/index.d.cts +83 -0
- package/dist/finance/index.d.ts +83 -0
- package/dist/finance/index.js +3584 -0
- package/dist/finance/index.js.map +1 -0
- package/dist/geography/index.cjs +4227 -0
- package/dist/geography/index.cjs.map +1 -0
- package/dist/geography/index.d.cts +34 -0
- package/dist/geography/index.d.ts +34 -0
- package/dist/geography/index.js +4202 -0
- package/dist/geography/index.js.map +1 -0
- package/dist/index.cjs +14087 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +75 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +13868 -0
- package/dist/index.js.map +1 -0
- package/dist/isin-EeVPpNWu.d.ts +39 -0
- package/dist/isin-ZlQLBVm8.d.cts +39 -0
- package/dist/organization/index.cjs +2376 -0
- package/dist/organization/index.cjs.map +1 -0
- package/dist/organization/index.d.cts +117 -0
- package/dist/organization/index.d.ts +117 -0
- package/dist/organization/index.js +2346 -0
- package/dist/organization/index.js.map +1 -0
- package/dist/person/index.cjs +1144 -0
- package/dist/person/index.cjs.map +1 -0
- package/dist/person/index.d.cts +60 -0
- package/dist/person/index.d.ts +60 -0
- package/dist/person/index.js +1125 -0
- package/dist/person/index.js.map +1 -0
- package/dist/person-full-name-Cmc9Ynuc.d.cts +82 -0
- package/dist/person-full-name-D6Hbsab6.d.ts +82 -0
- package/dist/phone-number-C24--ggy.d.ts +139 -0
- package/dist/phone-number-DZ-YxCQQ.d.cts +139 -0
- package/dist/property/index.cjs +487 -0
- package/dist/property/index.cjs.map +1 -0
- package/dist/property/index.d.cts +56 -0
- package/dist/property/index.d.ts +56 -0
- package/dist/property/index.js +480 -0
- package/dist/property/index.js.map +1 -0
- package/dist/sample-data/index.cjs +12310 -0
- package/dist/sample-data/index.cjs.map +1 -0
- package/dist/sample-data/index.d.cts +260 -0
- package/dist/sample-data/index.d.ts +260 -0
- package/dist/sample-data/index.js +12302 -0
- package/dist/sample-data/index.js.map +1 -0
- package/dist/swedish-address-DNC3ftRF.d.cts +297 -0
- package/dist/swedish-address-GMzjqgxb.d.ts +297 -0
- package/dist/swedish-bank-account-holder-name-BFJ8h1aO.d.cts +45 -0
- package/dist/swedish-bank-account-holder-name-CAAru07F.d.ts +45 -0
- package/dist/swedish-municipality-DlUS7g7h.d.cts +87 -0
- package/dist/swedish-municipality-nDRHYRAd.d.ts +87 -0
- package/dist/swedish-organization-name-D7NvERxA.d.cts +33 -0
- package/dist/swedish-organization-name-rR0Q836C.d.ts +33 -0
- package/dist/swedish-organization-number-Bcj7V_lh.d.cts +130 -0
- package/dist/swedish-organization-number-DM8dpXwR.d.ts +130 -0
- package/dist/swedish-organization-type-CZOdETwG.d.cts +29 -0
- package/dist/swedish-organization-type-CZOdETwG.d.ts +29 -0
- package/dist/swedish-personal-identity-number-BiIg4io3.d.ts +149 -0
- package/dist/swedish-personal-identity-number-Cp9Coz55.d.cts +149 -0
- package/dist/swedish-property-designation-BM-gdd9x.d.ts +46 -0
- package/dist/swedish-property-designation-BaHXufqV.d.cts +46 -0
- package/dist/swedish-sni-code-Ccsswpni.d.ts +53 -0
- package/dist/swedish-sni-code-CuJFyM6l.d.cts +53 -0
- package/dist/swedish-swish-number-CL6Gx_h3.d.cts +397 -0
- package/dist/swedish-swish-number-DDG3mNDg.d.ts +397 -0
- package/dist/text-candidate-qg2bD9PY.d.cts +110 -0
- package/dist/text-candidate-qg2bD9PY.d.ts +110 -0
- package/dist/text-scanning/index.cjs +10414 -0
- package/dist/text-scanning/index.cjs.map +1 -0
- package/dist/text-scanning/index.d.cts +153 -0
- package/dist/text-scanning/index.d.ts +153 -0
- package/dist/text-scanning/index.js +10406 -0
- package/dist/text-scanning/index.js.map +1 -0
- package/dist/validation/index.cjs +83 -0
- package/dist/validation/index.cjs.map +1 -0
- package/dist/validation/index.d.cts +63 -0
- package/dist/validation/index.d.ts +63 -0
- package/dist/validation/index.js +79 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/web/index.cjs +3994 -0
- package/dist/web/index.cjs.map +1 -0
- package/dist/web/index.d.cts +203 -0
- package/dist/web/index.d.ts +203 -0
- package/dist/web/index.js +3987 -0
- package/dist/web/index.js.map +1 -0
- package/package.json +211 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
// src/primitives-defaults.ts
|
|
2
|
+
var DEFAULT_CULTURE = "sv-SE";
|
|
3
|
+
var DEFAULT_UI_CULTURE = "sv-SE";
|
|
4
|
+
var state = {
|
|
5
|
+
culture: DEFAULT_CULTURE,
|
|
6
|
+
uiCulture: DEFAULT_UI_CULTURE};
|
|
7
|
+
var PrimitivesDefaults = {
|
|
8
|
+
/**
|
|
9
|
+
* BCP-47 locale tag used for casing and number formatting.
|
|
10
|
+
* Defaults to `'sv-SE'`.
|
|
11
|
+
*/
|
|
12
|
+
get culture() {
|
|
13
|
+
return state.culture;
|
|
14
|
+
},
|
|
15
|
+
set culture(value) {
|
|
16
|
+
state.culture = value;
|
|
17
|
+
},
|
|
18
|
+
/**
|
|
19
|
+
* `true` when {@link uiCulture} is Swedish (`sv` or `sv-*`).
|
|
20
|
+
* Types use this to select between localized and English display names.
|
|
21
|
+
*/
|
|
22
|
+
get useLocalizedDisplayNames() {
|
|
23
|
+
const lang = state.uiCulture.toLowerCase().split("-")[0];
|
|
24
|
+
return lang === "sv";
|
|
25
|
+
}};
|
|
26
|
+
|
|
27
|
+
// src/internal/input-sanitization.ts
|
|
28
|
+
var FORMAT_OR_NOT_ASSIGNED = /[\p{Cf}\p{Cn}]/u;
|
|
29
|
+
var SPACE_SEPARATOR = /[\p{Zs}\p{Zl}\p{Zp}]/u;
|
|
30
|
+
var CONTROL = /\p{Cc}/u;
|
|
31
|
+
function sanitizeInput(input) {
|
|
32
|
+
let out = "";
|
|
33
|
+
for (const c of input) {
|
|
34
|
+
if (c === "\u2018" || c === "\u2019" || c === "\u201A" || c === "\u201B") {
|
|
35
|
+
out += "'";
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (c === "\u201C" || c === "\u201D" || c === "\u201E" || c === "\u201F" || c === "\xAB" || c === "\xBB") {
|
|
39
|
+
out += '"';
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (FORMAT_OR_NOT_ASSIGNED.test(c)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (CONTROL.test(c)) {
|
|
46
|
+
if (c === " " || c === "\n" || c === "\r") out += " ";
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (SPACE_SEPARATOR.test(c)) {
|
|
50
|
+
out += " ";
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
out += c;
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
var WHITESPACE_RUN = /\s+/g;
|
|
58
|
+
function collapseWhitespace(input) {
|
|
59
|
+
if (input == null) return "";
|
|
60
|
+
return sanitizeInput(input).trim().replace(WHITESPACE_RUN, " ");
|
|
61
|
+
}
|
|
62
|
+
function keepDigits(input) {
|
|
63
|
+
let out = "";
|
|
64
|
+
for (let i = 0; i < input.length; i++) {
|
|
65
|
+
const c = input.charCodeAt(i);
|
|
66
|
+
if (c >= 48 && c <= 57) out += input[i];
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/text-scanning/text-candidate-category.ts
|
|
72
|
+
var TextCandidateCategory = {
|
|
73
|
+
Property: "Property"};
|
|
74
|
+
|
|
75
|
+
// src/text-scanning/text-candidate.ts
|
|
76
|
+
var TextCandidate = class {
|
|
77
|
+
/** Zero-based start position in the scanned text. */
|
|
78
|
+
startIndex;
|
|
79
|
+
/** Number of characters in the original matched span. */
|
|
80
|
+
length;
|
|
81
|
+
/** The raw substring from the input text that was matched. */
|
|
82
|
+
originalText;
|
|
83
|
+
/**
|
|
84
|
+
* Short type name, e.g. `EmailAddress` or `SwedishPersonalIdentityNumber`.
|
|
85
|
+
*/
|
|
86
|
+
typeName;
|
|
87
|
+
/** Broad category of the matched type. */
|
|
88
|
+
category;
|
|
89
|
+
/** Machine-comparable canonical form of the matched value. */
|
|
90
|
+
normalizedForm;
|
|
91
|
+
/** Human-readable display form of the matched value. */
|
|
92
|
+
formattedForm;
|
|
93
|
+
/**
|
|
94
|
+
* Display form with sensitive content masked (e.g. `990807-****`).
|
|
95
|
+
* Produced by the type's `toMaskedString()` helper.
|
|
96
|
+
*/
|
|
97
|
+
maskedForm;
|
|
98
|
+
/** Heuristic confidence level. */
|
|
99
|
+
confidence;
|
|
100
|
+
/** The successfully parsed instance of the matched type. */
|
|
101
|
+
value;
|
|
102
|
+
constructor(opts) {
|
|
103
|
+
this.startIndex = opts.startIndex;
|
|
104
|
+
this.length = opts.length;
|
|
105
|
+
this.originalText = opts.originalText;
|
|
106
|
+
this.typeName = opts.typeName;
|
|
107
|
+
this.category = opts.category;
|
|
108
|
+
this.normalizedForm = opts.normalizedForm;
|
|
109
|
+
this.formattedForm = opts.formattedForm;
|
|
110
|
+
this.maskedForm = opts.maskedForm;
|
|
111
|
+
this.confidence = opts.confidence;
|
|
112
|
+
this.value = opts.value;
|
|
113
|
+
}
|
|
114
|
+
/** Exclusive end position (`startIndex + length`). */
|
|
115
|
+
get endIndex() {
|
|
116
|
+
return this.startIndex + this.length;
|
|
117
|
+
}
|
|
118
|
+
/** Returns `true` if this candidate's span overlaps with `other`. */
|
|
119
|
+
overlaps(other) {
|
|
120
|
+
return this.startIndex < other.endIndex && other.startIndex < this.endIndex;
|
|
121
|
+
}
|
|
122
|
+
/** Returns `true` if this candidate's span fully contains `other`. */
|
|
123
|
+
contains(other) {
|
|
124
|
+
return this.startIndex <= other.startIndex && this.endIndex >= other.endIndex;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// src/text-scanning/text-match-confidence.ts
|
|
129
|
+
var TextMatchConfidence = {
|
|
130
|
+
/**
|
|
131
|
+
* Structural match with partial validation — the format is correct but no
|
|
132
|
+
* checksum or strong distinguishing feature confirms the match.
|
|
133
|
+
*/
|
|
134
|
+
Medium: 1};
|
|
135
|
+
|
|
136
|
+
// src/property/swedish-property-designation.ts
|
|
137
|
+
var MAX_INPUT_LENGTH = 200;
|
|
138
|
+
var PARSE_PATTERN = /^(?<name>[\p{L}\p{M}\d][\p{L}\p{M}\d\s'-]*?)\s+(?<block>\d{1,6}):(?<unit>\d{1,6})$/u;
|
|
139
|
+
var SCAN_PATTERN = /(?<![\p{L}\p{M}\d])(?<name>\p{Lu}[\p{L}\p{M}'-]*(?:\s\p{Lu}[\p{L}\p{M}'-]*)?)\s+(?<block>\d{1,6}):(?<unit>\d{1,6})(?!\d)/gu;
|
|
140
|
+
var SwedishPropertyDesignation = class _SwedishPropertyDesignation {
|
|
141
|
+
static typeInfo = Object.freeze({
|
|
142
|
+
englishName: "Property Designation",
|
|
143
|
+
localizedName: "Fastighetsbeteckning",
|
|
144
|
+
emoji: "\u{1F3E0}",
|
|
145
|
+
sources: Object.freeze([
|
|
146
|
+
"https://www.lantmateriet.se/sv/kartor/vara-karttjanster/min-karta/hitta-fastighetsbeteckning-i-min-karta/",
|
|
147
|
+
"https://www2.lantmateriet.se/sv/fastighet-och-mark/information-om-fastigheter/Fastighetsregistret/registrets-innehall/",
|
|
148
|
+
"https://sv.wikipedia.org/wiki/Fastighetsbeteckning"
|
|
149
|
+
])
|
|
150
|
+
});
|
|
151
|
+
/** The full designation, e.g. `Stockholm Söder 75:2`. */
|
|
152
|
+
value;
|
|
153
|
+
/** The capitalized designation name, e.g. `Stockholm Söder`. */
|
|
154
|
+
designationName;
|
|
155
|
+
/** The register number `BLOCK:UNIT`, e.g. `75:2`. */
|
|
156
|
+
registerNumber;
|
|
157
|
+
/** Block portion of the register number. */
|
|
158
|
+
blockNumber;
|
|
159
|
+
/** Unit portion of the register number. */
|
|
160
|
+
unitNumber;
|
|
161
|
+
constructor(value, designationName, registerNumber, blockNumber, unitNumber) {
|
|
162
|
+
this.value = value;
|
|
163
|
+
this.designationName = designationName;
|
|
164
|
+
this.registerNumber = registerNumber;
|
|
165
|
+
this.blockNumber = blockNumber;
|
|
166
|
+
this.unitNumber = unitNumber;
|
|
167
|
+
}
|
|
168
|
+
static tryParse(input) {
|
|
169
|
+
if (input == null || input.trim() === "") return null;
|
|
170
|
+
const normalized = normalizeInput(input);
|
|
171
|
+
if (normalized.length > MAX_INPUT_LENGTH) return null;
|
|
172
|
+
const match = PARSE_PATTERN.exec(normalized);
|
|
173
|
+
if (!match || !match.groups) return null;
|
|
174
|
+
const name = normalizeName(match.groups.name);
|
|
175
|
+
if (name === "") return null;
|
|
176
|
+
const block = Number(match.groups.block);
|
|
177
|
+
const unit = Number(match.groups.unit);
|
|
178
|
+
if (!Number.isFinite(block) || block <= 0) return null;
|
|
179
|
+
if (!Number.isFinite(unit) || unit <= 0) return null;
|
|
180
|
+
const register = `${block}:${unit}`;
|
|
181
|
+
const value = `${name} ${register}`;
|
|
182
|
+
return new _SwedishPropertyDesignation(value, name, register, block, unit);
|
|
183
|
+
}
|
|
184
|
+
static parse(input) {
|
|
185
|
+
const r = _SwedishPropertyDesignation.tryParse(input);
|
|
186
|
+
if (r === null) throw new Error("Invalid Swedish property designation.");
|
|
187
|
+
return r;
|
|
188
|
+
}
|
|
189
|
+
static isValid(input) {
|
|
190
|
+
return _SwedishPropertyDesignation.tryParse(input) !== null;
|
|
191
|
+
}
|
|
192
|
+
static format(input, options) {
|
|
193
|
+
const r = _SwedishPropertyDesignation.tryParse(input);
|
|
194
|
+
if (r) return r.value;
|
|
195
|
+
if (options?.fallbackToTrimmedInputWhenInvalid && input != null && input.trim() !== "") {
|
|
196
|
+
return input.trim();
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
static normalize(input, options) {
|
|
201
|
+
return _SwedishPropertyDesignation.format(input, options);
|
|
202
|
+
}
|
|
203
|
+
static isNormalized(input) {
|
|
204
|
+
return input != null && _SwedishPropertyDesignation.normalize(input) === input;
|
|
205
|
+
}
|
|
206
|
+
toNormalizedString() {
|
|
207
|
+
return this.value;
|
|
208
|
+
}
|
|
209
|
+
toString() {
|
|
210
|
+
return this.value;
|
|
211
|
+
}
|
|
212
|
+
static findCandidatesInText(text) {
|
|
213
|
+
if (!text) return [];
|
|
214
|
+
const out = [];
|
|
215
|
+
const re = new RegExp(SCAN_PATTERN.source, SCAN_PATTERN.flags);
|
|
216
|
+
let m;
|
|
217
|
+
while ((m = re.exec(text)) !== null) {
|
|
218
|
+
const r = _SwedishPropertyDesignation.tryParse(m[0]);
|
|
219
|
+
if (!r) continue;
|
|
220
|
+
out.push(
|
|
221
|
+
new TextCandidate({
|
|
222
|
+
startIndex: m.index,
|
|
223
|
+
length: m[0].length,
|
|
224
|
+
originalText: m[0],
|
|
225
|
+
typeName: "SwedishPropertyDesignation",
|
|
226
|
+
category: TextCandidateCategory.Property,
|
|
227
|
+
normalizedForm: r.toNormalizedString(),
|
|
228
|
+
formattedForm: r.toString(),
|
|
229
|
+
maskedForm: maskSwedishPropertyDesignation(r),
|
|
230
|
+
confidence: TextMatchConfidence.Medium,
|
|
231
|
+
value: r
|
|
232
|
+
})
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return out;
|
|
236
|
+
}
|
|
237
|
+
equals(other) {
|
|
238
|
+
return other != null && this.value === other.value;
|
|
239
|
+
}
|
|
240
|
+
compareTo(other) {
|
|
241
|
+
if (other == null) return 1;
|
|
242
|
+
return this.value < other.value ? -1 : this.value > other.value ? 1 : 0;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
function normalizeInput(input) {
|
|
246
|
+
let s = collapseWhitespace(input);
|
|
247
|
+
s = s.replace(/\s*:\s*/g, ":");
|
|
248
|
+
return s;
|
|
249
|
+
}
|
|
250
|
+
function normalizeName(input) {
|
|
251
|
+
const words = collapseWhitespace(input).split(" ").filter((w) => w.length > 0);
|
|
252
|
+
return words.map(capitalizeHyphenatedWord).join(" ");
|
|
253
|
+
}
|
|
254
|
+
function capitalizeHyphenatedWord(word) {
|
|
255
|
+
if (!word) return word;
|
|
256
|
+
return word.split("-").map(capitalizeWord).join("-");
|
|
257
|
+
}
|
|
258
|
+
function capitalizeWord(word) {
|
|
259
|
+
if (!word) return word;
|
|
260
|
+
const locale = PrimitivesDefaults.culture;
|
|
261
|
+
const lowered = word.toLocaleLowerCase(locale);
|
|
262
|
+
for (let i = 0; i < lowered.length; i++) {
|
|
263
|
+
const ch = lowered[i];
|
|
264
|
+
if (isLetter(ch)) {
|
|
265
|
+
return lowered.slice(0, i) + ch.toLocaleUpperCase(locale) + lowered.slice(i + 1);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return lowered;
|
|
269
|
+
}
|
|
270
|
+
function isLetter(ch) {
|
|
271
|
+
return /\p{L}/u.test(ch);
|
|
272
|
+
}
|
|
273
|
+
function maskSwedishPropertyDesignation(d) {
|
|
274
|
+
const block = "*".repeat(d.blockNumber.toString().length);
|
|
275
|
+
const unit = "*".repeat(d.unitNumber.toString().length);
|
|
276
|
+
return `${d.designationName} ${block}:${unit}`;
|
|
277
|
+
}
|
|
278
|
+
function getLantmaterietUrl(d) {
|
|
279
|
+
return `https://minkarta.lantmateriet.se/?search=${encodeURIComponent(d.value)}`;
|
|
280
|
+
}
|
|
281
|
+
function getPropertyHittaUrl(d) {
|
|
282
|
+
return `https://www.hitta.se/kartan?s=${encodeURIComponent(d.value)}`;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// src/property/swedish-property-taxation-code.ts
|
|
286
|
+
var MAX_INPUT_LENGTH2 = 20;
|
|
287
|
+
var SwedishPropertyTaxationCategory = {
|
|
288
|
+
Unknown: "Unknown",
|
|
289
|
+
Lantbruksenhet: "Lantbruksenhet",
|
|
290
|
+
Smahusenhet: "Smahusenhet",
|
|
291
|
+
Hyreshusenhet: "Hyreshusenhet",
|
|
292
|
+
Industrienhet: "Industrienhet",
|
|
293
|
+
Taktmark: "Taktmark",
|
|
294
|
+
Elproduktionsenhet: "Elproduktionsenhet",
|
|
295
|
+
Specialenhet: "Specialenhet",
|
|
296
|
+
OvrigMark: "OvrigMark"
|
|
297
|
+
};
|
|
298
|
+
var CATEGORY_BY_FIRST_DIGIT = {
|
|
299
|
+
1: SwedishPropertyTaxationCategory.Lantbruksenhet,
|
|
300
|
+
2: SwedishPropertyTaxationCategory.Smahusenhet,
|
|
301
|
+
3: SwedishPropertyTaxationCategory.Hyreshusenhet,
|
|
302
|
+
4: SwedishPropertyTaxationCategory.Industrienhet,
|
|
303
|
+
5: SwedishPropertyTaxationCategory.Taktmark,
|
|
304
|
+
6: SwedishPropertyTaxationCategory.Elproduktionsenhet,
|
|
305
|
+
7: SwedishPropertyTaxationCategory.Specialenhet,
|
|
306
|
+
8: SwedishPropertyTaxationCategory.OvrigMark
|
|
307
|
+
};
|
|
308
|
+
var KNOWN_CODES = {
|
|
309
|
+
110: { english: "Agricultural unit, undeveloped", swedish: "Lantbruksenhet, obebyggd" },
|
|
310
|
+
113: {
|
|
311
|
+
english: "Agricultural unit, with farm building only",
|
|
312
|
+
swedish: "Lantbruksenhet, obebyggd, enbart med ekonomibyggnad"
|
|
313
|
+
},
|
|
314
|
+
120: { english: "Agricultural unit, developed", swedish: "Lantbruksenhet, bebyggd" },
|
|
315
|
+
210: { english: "Small house unit, land only", swedish: "Sm\xE5husenhet, tomtmark" },
|
|
316
|
+
213: {
|
|
317
|
+
english: "Small house unit, land with building value under 50 000 SEK",
|
|
318
|
+
swedish: "Sm\xE5husenhet, tomtmark med byggnadsv\xE4rde under 50 000 kr"
|
|
319
|
+
},
|
|
320
|
+
220: { english: "Small house unit, developed", swedish: "Sm\xE5husenhet, bebyggd" },
|
|
321
|
+
221: {
|
|
322
|
+
english: "Small house unit, developed with two houses",
|
|
323
|
+
swedish: "Sm\xE5husenhet, bebyggd med tv\xE5 sm\xE5hus"
|
|
324
|
+
},
|
|
325
|
+
225: {
|
|
326
|
+
english: "Small house unit, on leasehold",
|
|
327
|
+
swedish: "Sm\xE5husenhet, bebyggd p\xE5 ofri grund"
|
|
328
|
+
},
|
|
329
|
+
230: {
|
|
330
|
+
english: "Small house unit, developed, cluster housing",
|
|
331
|
+
swedish: "Sm\xE5husenhet, bebyggd, grupphusomr\xE5de"
|
|
332
|
+
},
|
|
333
|
+
310: { english: "Rental property unit, land only", swedish: "Hyreshusenhet, tomtmark" },
|
|
334
|
+
313: {
|
|
335
|
+
english: "Rental property unit, land with building value under 50 000 SEK",
|
|
336
|
+
swedish: "Hyreshusenhet, tomtmark med byggnadsv\xE4rde under 50 000 kr"
|
|
337
|
+
},
|
|
338
|
+
320: {
|
|
339
|
+
english: "Rental property unit, developed, residential",
|
|
340
|
+
swedish: "Hyreshusenhet, bebyggd, bost\xE4der"
|
|
341
|
+
},
|
|
342
|
+
321: {
|
|
343
|
+
english: "Rental property unit, developed, residential and commercial",
|
|
344
|
+
swedish: "Hyreshusenhet, bebyggd, bost\xE4der och lokaler"
|
|
345
|
+
},
|
|
346
|
+
325: {
|
|
347
|
+
english: "Rental property unit, developed, commercial",
|
|
348
|
+
swedish: "Hyreshusenhet, bebyggd, lokaler"
|
|
349
|
+
},
|
|
350
|
+
381: {
|
|
351
|
+
english: "Rental property unit, developed, residential (special)",
|
|
352
|
+
swedish: "Hyreshusenhet, bebyggd, bost\xE4der (specialenhet)"
|
|
353
|
+
},
|
|
354
|
+
410: { english: "Industrial unit, land only", swedish: "Industrienhet, tomtmark" },
|
|
355
|
+
420: { english: "Industrial unit, developed", swedish: "Industrienhet, bebyggd" },
|
|
356
|
+
421: {
|
|
357
|
+
english: "Industrial unit, developed with rental property area",
|
|
358
|
+
swedish: "Industrienhet, bebyggd med hyreshusareal"
|
|
359
|
+
},
|
|
360
|
+
498: { english: "Industrial unit, petrol station", swedish: "Industrienhet, bensinstation" },
|
|
361
|
+
510: { english: "Quarry land, undeveloped", swedish: "T\xE4ktmark, obebyggd" },
|
|
362
|
+
520: { english: "Quarry land, developed", swedish: "T\xE4ktmark, bebyggd" },
|
|
363
|
+
610: {
|
|
364
|
+
english: "Power production unit, hydropower",
|
|
365
|
+
swedish: "Elproduktionsenhet, vattenkraftverk"
|
|
366
|
+
},
|
|
367
|
+
620: {
|
|
368
|
+
english: "Power production unit, thermal power",
|
|
369
|
+
swedish: "Elproduktionsenhet, v\xE4rmekraftverk"
|
|
370
|
+
},
|
|
371
|
+
630: {
|
|
372
|
+
english: "Power production unit, wind power",
|
|
373
|
+
swedish: "Elproduktionsenhet, vindkraftverk"
|
|
374
|
+
},
|
|
375
|
+
710: { english: "Communication building", swedish: "Kommunikationsbyggnad" },
|
|
376
|
+
720: { english: "Distribution building", swedish: "Distributionsbyggnad" },
|
|
377
|
+
730: { english: "Cultural building", swedish: "Kulturbyggnad" },
|
|
378
|
+
810: { english: "Special unit, undeveloped land", swedish: "Specialenhet, obebyggd mark" },
|
|
379
|
+
890: { english: "Other land", swedish: "\xD6vrig mark" }
|
|
380
|
+
};
|
|
381
|
+
var SwedishPropertyTaxationCode = class _SwedishPropertyTaxationCode {
|
|
382
|
+
static typeInfo = Object.freeze({
|
|
383
|
+
englishName: "Property Taxation Code",
|
|
384
|
+
localizedName: "Typkod",
|
|
385
|
+
emoji: "\u{1F3D7}\uFE0F",
|
|
386
|
+
sources: Object.freeze([
|
|
387
|
+
"https://www.skatteverket.se/privat/fastigheterochbostad/fastighetstaxering.4.69ef368911e1304a625800013531.html",
|
|
388
|
+
"https://sv.wikipedia.org/wiki/Typkod_(fastighet)"
|
|
389
|
+
])
|
|
390
|
+
});
|
|
391
|
+
/** The 3-digit taxation code, e.g. `220`. */
|
|
392
|
+
code;
|
|
393
|
+
/** The numeric form of the code, e.g. `220`. */
|
|
394
|
+
numericCode;
|
|
395
|
+
/** The main property category (derived from the first digit). */
|
|
396
|
+
category;
|
|
397
|
+
/** English description, or `null` when the code is not in the known list. */
|
|
398
|
+
englishDescription;
|
|
399
|
+
/** Localized (Swedish) description, or `null` when not in the known list. */
|
|
400
|
+
localizedDescription;
|
|
401
|
+
/** `true` when this code has a known description. */
|
|
402
|
+
get isKnown() {
|
|
403
|
+
return this.englishDescription !== null;
|
|
404
|
+
}
|
|
405
|
+
/** Display description in the current display language; falls back to the code. */
|
|
406
|
+
get displayDescription() {
|
|
407
|
+
const desc = PrimitivesDefaults.useLocalizedDisplayNames ? this.localizedDescription : this.englishDescription;
|
|
408
|
+
return desc ?? this.code;
|
|
409
|
+
}
|
|
410
|
+
constructor(code, numericCode, category, englishDescription, localizedDescription) {
|
|
411
|
+
this.code = code;
|
|
412
|
+
this.numericCode = numericCode;
|
|
413
|
+
this.category = category;
|
|
414
|
+
this.englishDescription = englishDescription;
|
|
415
|
+
this.localizedDescription = localizedDescription;
|
|
416
|
+
}
|
|
417
|
+
static tryParse(input) {
|
|
418
|
+
if (input == null || input.trim() === "") return null;
|
|
419
|
+
const digits = keepDigits(input);
|
|
420
|
+
if (digits.length > MAX_INPUT_LENGTH2) return null;
|
|
421
|
+
if (digits.length !== 3) return null;
|
|
422
|
+
const numeric = Number(digits);
|
|
423
|
+
if (!Number.isFinite(numeric) || numeric < 100 || numeric > 999) return null;
|
|
424
|
+
const firstDigit = Math.floor(numeric / 100);
|
|
425
|
+
const category = CATEGORY_BY_FIRST_DIGIT[firstDigit];
|
|
426
|
+
if (!category || category === SwedishPropertyTaxationCategory.Unknown) return null;
|
|
427
|
+
const known = KNOWN_CODES[numeric];
|
|
428
|
+
return new _SwedishPropertyTaxationCode(
|
|
429
|
+
digits,
|
|
430
|
+
numeric,
|
|
431
|
+
category,
|
|
432
|
+
known?.english ?? null,
|
|
433
|
+
known?.swedish ?? null
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
static parse(input) {
|
|
437
|
+
const r = _SwedishPropertyTaxationCode.tryParse(input);
|
|
438
|
+
if (r === null) throw new Error("Invalid Swedish property taxation code.");
|
|
439
|
+
return r;
|
|
440
|
+
}
|
|
441
|
+
static isValid(input) {
|
|
442
|
+
return _SwedishPropertyTaxationCode.tryParse(input) !== null;
|
|
443
|
+
}
|
|
444
|
+
static format(input, options) {
|
|
445
|
+
const r = _SwedishPropertyTaxationCode.tryParse(input);
|
|
446
|
+
if (r) return r.displayDescription;
|
|
447
|
+
if (options?.fallbackToTrimmedInputWhenInvalid && input != null && input.trim() !== "") {
|
|
448
|
+
return input.trim();
|
|
449
|
+
}
|
|
450
|
+
return null;
|
|
451
|
+
}
|
|
452
|
+
static normalize(input, options) {
|
|
453
|
+
const r = _SwedishPropertyTaxationCode.tryParse(input);
|
|
454
|
+
if (r) return r.code;
|
|
455
|
+
if (options?.fallbackToTrimmedInputWhenInvalid && input != null && input.trim() !== "") {
|
|
456
|
+
return input.trim();
|
|
457
|
+
}
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
static isNormalized(input) {
|
|
461
|
+
return input != null && _SwedishPropertyTaxationCode.normalize(input) === input;
|
|
462
|
+
}
|
|
463
|
+
toNormalizedString() {
|
|
464
|
+
return this.code;
|
|
465
|
+
}
|
|
466
|
+
toString() {
|
|
467
|
+
return this.displayDescription;
|
|
468
|
+
}
|
|
469
|
+
equals(other) {
|
|
470
|
+
return other != null && this.code === other.code;
|
|
471
|
+
}
|
|
472
|
+
compareTo(other) {
|
|
473
|
+
if (other == null) return 1;
|
|
474
|
+
return this.code < other.code ? -1 : this.code > other.code ? 1 : 0;
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
export { SwedishPropertyDesignation, SwedishPropertyTaxationCategory, SwedishPropertyTaxationCode, getLantmaterietUrl, getPropertyHittaUrl, maskSwedishPropertyDesignation };
|
|
479
|
+
//# sourceMappingURL=index.js.map
|
|
480
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/primitives-defaults.ts","../../src/internal/input-sanitization.ts","../../src/text-scanning/text-candidate-category.ts","../../src/text-scanning/text-candidate.ts","../../src/text-scanning/text-match-confidence.ts","../../src/property/swedish-property-designation.ts","../../src/property/swedish-property-taxation-code.ts"],"names":["MAX_INPUT_LENGTH"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Configurable defaults that control locale-sensitive behaviour across all\n * primitive types. When not explicitly set, values fall back to safe Swedish\n * defaults (the .NET version derives them from `CultureInfo.CurrentCulture`,\n * which has no direct equivalent in standard JavaScript).\n *\n * Set properties at application startup or override per-request as needed.\n */\n\nconst DEFAULT_CULTURE = \"sv-SE\";\nconst DEFAULT_UI_CULTURE = \"sv-SE\";\nconst DEFAULT_COUNTRY = \"SE\";\nconst DEFAULT_CALLING_CODE = \"46\";\n\ninterface PrimitivesDefaultsState {\n culture: string;\n uiCulture: string;\n countryAlpha2Code: string;\n defaultCallingCode: string;\n}\n\nconst state: PrimitivesDefaultsState = {\n culture: DEFAULT_CULTURE,\n uiCulture: DEFAULT_UI_CULTURE,\n countryAlpha2Code: DEFAULT_COUNTRY,\n defaultCallingCode: DEFAULT_CALLING_CODE,\n};\n\n/**\n * Configurable global defaults for locale, UI language, and default country.\n *\n * These mirror the .NET `PrimitivesDefaults` static class. `culture` controls\n * formatting and casing (Swedish-aware character handling for `Å`/`Ä`/`Ö`),\n * `uiCulture` controls display-name language selection (Swedish vs English),\n * and `countryAlpha2Code` is used as the default ISO 3166-1 alpha-2 country\n * when no explicit country is supplied.\n */\nexport const PrimitivesDefaults = {\n /**\n * BCP-47 locale tag used for casing and number formatting.\n * Defaults to `'sv-SE'`.\n */\n get culture(): string {\n return state.culture;\n },\n set culture(value: string) {\n state.culture = value;\n },\n\n /**\n * BCP-47 locale tag used for display-name language selection.\n * Defaults to `'sv-SE'`.\n */\n get uiCulture(): string {\n return state.uiCulture;\n },\n set uiCulture(value: string) {\n state.uiCulture = value;\n },\n\n /**\n * Default ISO 3166-1 alpha-2 country code. Used by types like\n * `PhoneNumber` and `SwedishOrganizationIdentifierParser` when no explicit\n * country is supplied. Defaults to `'SE'`.\n */\n get countryAlpha2Code(): string {\n return state.countryAlpha2Code;\n },\n set countryAlpha2Code(value: string) {\n state.countryAlpha2Code = value;\n },\n\n /**\n * Default phone calling code (digits only, no `+`). Used by {@link PhoneNumber}\n * for inputs without an explicit country prefix. Defaults to `'46'` (Sweden).\n */\n get defaultCallingCode(): string {\n return state.defaultCallingCode;\n },\n set defaultCallingCode(value: string) {\n state.defaultCallingCode = value;\n },\n\n /**\n * `true` when {@link uiCulture} is Swedish (`sv` or `sv-*`).\n * Types use this to select between localized and English display names.\n */\n get useLocalizedDisplayNames(): boolean {\n const lang = state.uiCulture.toLowerCase().split(\"-\")[0];\n return lang === \"sv\";\n },\n\n /** Resets all overrides to the package defaults. */\n reset(): void {\n state.culture = DEFAULT_CULTURE;\n state.uiCulture = DEFAULT_UI_CULTURE;\n state.countryAlpha2Code = DEFAULT_COUNTRY;\n state.defaultCallingCode = DEFAULT_CALLING_CODE;\n },\n};\n","/**\n * Shared input sanitization for text inputs across domain types.\n * Provides invisible-character stripping, whitespace normalization, and common\n * character-filtering helpers (digits-only, alphanumeric-only, collapse whitespace).\n *\n * Real-world inputs (e.g. from CRM/banking systems) commonly contain invisible\n * Unicode characters that break validation while being completely invisible in UIs\n * and logs. The most frequent offender is `U+202A` LEFT-TO-RIGHT EMBEDDING,\n * especially on values originating from RTL-language contexts (Arabic, Hebrew).\n * Other common contaminants include non-breaking spaces from web/PDF copy-paste,\n * null bytes from binary data, stray newlines from multi-line form fields,\n * and typographic (smart/curly) quotes from mobile keyboards and word processors.\n *\n * Equivalent of `Buildi.Primitives.InputSanitization` (internal in .NET).\n * Exposed via `internal/` and not re-exported from the public package entry.\n */\n\nconst FORMAT_OR_NOT_ASSIGNED = /[\\p{Cf}\\p{Cn}]/u;\nconst SPACE_SEPARATOR = /[\\p{Zs}\\p{Zl}\\p{Zp}]/u;\nconst CONTROL = /\\p{Cc}/u;\n\n/**\n * Strips invisible/non-printable characters, normalizes all whitespace variants\n * to ASCII space (`U+0020`), normalizes typographic single quotes to ASCII\n * apostrophe (`'`), and normalizes typographic and guillemet double quotes to\n * ASCII quotation mark (`\"`).\n */\nexport function sanitizeInput(input: string): string {\n let out = \"\";\n for (const c of input) {\n // Smart single quotes -> ASCII apostrophe.\n if (c === \"\\u2018\" || c === \"\\u2019\" || c === \"\\u201A\" || c === \"\\u201B\") {\n out += \"'\";\n continue;\n }\n // Smart and guillemet double quotes -> ASCII quotation mark.\n if (\n c === \"\\u201C\" ||\n c === \"\\u201D\" ||\n c === \"\\u201E\" ||\n c === \"\\u201F\" ||\n c === \"\\u00AB\" ||\n c === \"\\u00BB\"\n ) {\n out += '\"';\n continue;\n }\n\n if (FORMAT_OR_NOT_ASSIGNED.test(c)) {\n // Drop format characters (Cf) and unassigned code points (Cn).\n continue;\n }\n\n if (CONTROL.test(c)) {\n if (c === \"\\t\" || c === \"\\n\" || c === \"\\r\") out += \" \";\n continue;\n }\n\n if (SPACE_SEPARATOR.test(c)) {\n out += \" \";\n continue;\n }\n\n out += c;\n }\n return out;\n}\n\nconst WHITESPACE_RUN = /\\s+/g;\n\n/**\n * Sanitizes the input, trims, and collapses whitespace runs to a single space.\n * Returns an empty string when `input` is `null` or `undefined`.\n */\nexport function collapseWhitespace(input: string | null | undefined): string {\n if (input == null) return \"\";\n return sanitizeInput(input).trim().replace(WHITESPACE_RUN, \" \");\n}\n\n/** Keeps only ASCII digits (`0`-`9`), stripping everything else. */\nexport function keepDigits(input: string): string {\n let out = \"\";\n for (let i = 0; i < input.length; i++) {\n const c = input.charCodeAt(i);\n if (c >= 0x30 && c <= 0x39) out += input[i];\n }\n return out;\n}\n\n/**\n * Keeps only ASCII letters and digits, uppercasing letters.\n * Strips whitespace, hyphens, and all other non-alphanumeric characters.\n */\nexport function keepAsciiAlphanumericUppercase(input: string): string {\n let out = \"\";\n for (let i = 0; i < input.length; i++) {\n const c = input.charCodeAt(i);\n if (c >= 0x30 && c <= 0x39) out += input[i];\n else if (c >= 0x41 && c <= 0x5a) out += input[i];\n else if (c >= 0x61 && c <= 0x7a) out += String.fromCharCode(c - 32);\n }\n return out;\n}\n","/**\n * Broad classification of a {@link TextCandidate} for filtering and selective\n * masking.\n */\nexport const TextCandidateCategory = {\n PersonalIdentifier: \"PersonalIdentifier\",\n OrganizationIdentifier: \"OrganizationIdentifier\",\n Financial: \"Financial\",\n Contact: \"Contact\",\n Vehicle: \"Vehicle\",\n Property: \"Property\",\n Product: \"Product\",\n Geography: \"Geography\",\n Measurement: \"Measurement\",\n} as const;\n\nexport type TextCandidateCategory =\n (typeof TextCandidateCategory)[keyof typeof TextCandidateCategory];\n","import { TextCandidateCategory } from \"./text-candidate-category.js\";\nimport { TextMatchConfidence } from \"./text-match-confidence.js\";\n\n/**\n * A potential match of a structured type found in unstructured text.\n *\n * Text scanning is heuristic-based. Candidates may be false positives, and\n * valid occurrences may be missed. No guarantee is made that the matched text\n * actually represents the identified type in its original context.\n */\nexport class TextCandidate<T = unknown> {\n /** Zero-based start position in the scanned text. */\n readonly startIndex: number;\n /** Number of characters in the original matched span. */\n readonly length: number;\n /** The raw substring from the input text that was matched. */\n readonly originalText: string;\n /**\n * Short type name, e.g. `EmailAddress` or `SwedishPersonalIdentityNumber`.\n */\n readonly typeName: string;\n /** Broad category of the matched type. */\n readonly category: TextCandidateCategory;\n /** Machine-comparable canonical form of the matched value. */\n readonly normalizedForm: string;\n /** Human-readable display form of the matched value. */\n readonly formattedForm: string;\n /**\n * Display form with sensitive content masked (e.g. `990807-****`).\n * Produced by the type's `toMaskedString()` helper.\n */\n readonly maskedForm: string;\n /** Heuristic confidence level. */\n readonly confidence: TextMatchConfidence;\n /** The successfully parsed instance of the matched type. */\n readonly value: T;\n\n constructor(opts: {\n startIndex: number;\n length: number;\n originalText: string;\n typeName: string;\n category: TextCandidateCategory;\n normalizedForm: string;\n formattedForm: string;\n maskedForm: string;\n confidence: TextMatchConfidence;\n value: T;\n }) {\n this.startIndex = opts.startIndex;\n this.length = opts.length;\n this.originalText = opts.originalText;\n this.typeName = opts.typeName;\n this.category = opts.category;\n this.normalizedForm = opts.normalizedForm;\n this.formattedForm = opts.formattedForm;\n this.maskedForm = opts.maskedForm;\n this.confidence = opts.confidence;\n this.value = opts.value;\n }\n\n /** Exclusive end position (`startIndex + length`). */\n get endIndex(): number {\n return this.startIndex + this.length;\n }\n\n /** Returns `true` if this candidate's span overlaps with `other`. */\n overlaps(other: TextCandidate): boolean {\n return this.startIndex < other.endIndex && other.startIndex < this.endIndex;\n }\n\n /** Returns `true` if this candidate's span fully contains `other`. */\n contains(other: TextCandidate): boolean {\n return this.startIndex <= other.startIndex && this.endIndex >= other.endIndex;\n }\n}\n","/**\n * Indicates the confidence level of a candidate found by text scanning.\n * Higher confidence means stronger structural evidence, but no level guarantees\n * the absence of false positives.\n */\nexport const TextMatchConfidence = {\n /**\n * Pattern match only. High false-positive risk — the matched text merely\n * fits a syntactic pattern (e.g. a run of digits that happens to be the\n * right length).\n */\n Low: 0,\n /**\n * Structural match with partial validation — the format is correct but no\n * checksum or strong distinguishing feature confirms the match.\n */\n Medium: 1,\n /**\n * Strong match with checksum or format-specific validation (e.g. a personal\n * identity number with a valid Luhn check digit and plausible date, or an\n * IBAN with valid MOD-97).\n */\n High: 2,\n} as const;\n\nexport type TextMatchConfidence = (typeof TextMatchConfidence)[keyof typeof TextMatchConfidence];\n","import { PrimitiveTypeInfo } from \"../primitive-type-info.js\";\nimport { PrimitivesDefaults } from \"../primitives-defaults.js\";\nimport { collapseWhitespace } from \"../internal/input-sanitization.js\";\nimport { TextCandidateCategory } from \"../text-scanning/text-candidate-category.js\";\nimport { TextCandidate } from \"../text-scanning/text-candidate.js\";\nimport { TextMatchConfidence } from \"../text-scanning/text-match-confidence.js\";\n\nconst MAX_INPUT_LENGTH = 200;\n\nconst PARSE_PATTERN =\n /^(?<name>[\\p{L}\\p{M}\\d][\\p{L}\\p{M}\\d\\s'-]*?)\\s+(?<block>\\d{1,6}):(?<unit>\\d{1,6})$/u;\n\nconst SCAN_PATTERN =\n /(?<![\\p{L}\\p{M}\\d])(?<name>\\p{Lu}[\\p{L}\\p{M}'-]*(?:\\s\\p{Lu}[\\p{L}\\p{M}'-]*)?)\\s+(?<block>\\d{1,6}):(?<unit>\\d{1,6})(?!\\d)/gu;\n\n/**\n * A Swedish property designation (`fastighetsbeteckning`), e.g. `Stockholm Söder 75:2`.\n * Combines the municipality/tract name with a register number `BLOCK:UNIT`.\n */\nexport class SwedishPropertyDesignation {\n static readonly typeInfo: PrimitiveTypeInfo = Object.freeze({\n englishName: \"Property Designation\",\n localizedName: \"Fastighetsbeteckning\",\n emoji: \"\\u{1F3E0}\",\n sources: Object.freeze([\n \"https://www.lantmateriet.se/sv/kartor/vara-karttjanster/min-karta/hitta-fastighetsbeteckning-i-min-karta/\",\n \"https://www2.lantmateriet.se/sv/fastighet-och-mark/information-om-fastigheter/Fastighetsregistret/registrets-innehall/\",\n \"https://sv.wikipedia.org/wiki/Fastighetsbeteckning\",\n ]),\n });\n\n /** The full designation, e.g. `Stockholm Söder 75:2`. */\n readonly value: string;\n /** The capitalized designation name, e.g. `Stockholm Söder`. */\n readonly designationName: string;\n /** The register number `BLOCK:UNIT`, e.g. `75:2`. */\n readonly registerNumber: string;\n /** Block portion of the register number. */\n readonly blockNumber: number;\n /** Unit portion of the register number. */\n readonly unitNumber: number;\n\n private constructor(\n value: string,\n designationName: string,\n registerNumber: string,\n blockNumber: number,\n unitNumber: number,\n ) {\n this.value = value;\n this.designationName = designationName;\n this.registerNumber = registerNumber;\n this.blockNumber = blockNumber;\n this.unitNumber = unitNumber;\n }\n\n static tryParse(input: string | null | undefined): SwedishPropertyDesignation | null {\n if (input == null || input.trim() === \"\") return null;\n const normalized = normalizeInput(input);\n if (normalized.length > MAX_INPUT_LENGTH) return null;\n\n const match = PARSE_PATTERN.exec(normalized);\n if (!match || !match.groups) return null;\n\n const name = normalizeName(match.groups.name!);\n if (name === \"\") return null;\n\n const block = Number(match.groups.block);\n const unit = Number(match.groups.unit);\n if (!Number.isFinite(block) || block <= 0) return null;\n if (!Number.isFinite(unit) || unit <= 0) return null;\n\n const register = `${block}:${unit}`;\n const value = `${name} ${register}`;\n return new SwedishPropertyDesignation(value, name, register, block, unit);\n }\n\n static parse(input: string): SwedishPropertyDesignation {\n const r = SwedishPropertyDesignation.tryParse(input);\n if (r === null) throw new Error(\"Invalid Swedish property designation.\");\n return r;\n }\n\n static isValid(input: string | null | undefined): boolean {\n return SwedishPropertyDesignation.tryParse(input) !== null;\n }\n\n static format(\n input: string | null | undefined,\n options?: { fallbackToTrimmedInputWhenInvalid?: boolean },\n ): string | null {\n const r = SwedishPropertyDesignation.tryParse(input);\n if (r) return r.value;\n if (options?.fallbackToTrimmedInputWhenInvalid && input != null && input.trim() !== \"\") {\n return input.trim();\n }\n return null;\n }\n\n static normalize(\n input: string | null | undefined,\n options?: { fallbackToTrimmedInputWhenInvalid?: boolean },\n ): string | null {\n return SwedishPropertyDesignation.format(input, options);\n }\n\n static isNormalized(input: string | null | undefined): boolean {\n return input != null && SwedishPropertyDesignation.normalize(input) === input;\n }\n\n toNormalizedString(): string {\n return this.value;\n }\n toString(): string {\n return this.value;\n }\n\n static findCandidatesInText(text: string): readonly TextCandidate<SwedishPropertyDesignation>[] {\n if (!text) return [];\n const out: TextCandidate<SwedishPropertyDesignation>[] = [];\n const re = new RegExp(SCAN_PATTERN.source, SCAN_PATTERN.flags);\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const r = SwedishPropertyDesignation.tryParse(m[0]);\n if (!r) continue;\n out.push(\n new TextCandidate<SwedishPropertyDesignation>({\n startIndex: m.index,\n length: m[0].length,\n originalText: m[0],\n typeName: \"SwedishPropertyDesignation\",\n category: TextCandidateCategory.Property,\n normalizedForm: r.toNormalizedString(),\n formattedForm: r.toString(),\n maskedForm: maskSwedishPropertyDesignation(r),\n confidence: TextMatchConfidence.Medium,\n value: r,\n }),\n );\n }\n return out;\n }\n\n equals(other: SwedishPropertyDesignation | null | undefined): boolean {\n return other != null && this.value === other.value;\n }\n compareTo(other: SwedishPropertyDesignation | null | undefined): number {\n if (other == null) return 1;\n return this.value < other.value ? -1 : this.value > other.value ? 1 : 0;\n }\n}\n\nfunction normalizeInput(input: string): string {\n let s = collapseWhitespace(input);\n s = s.replace(/\\s*:\\s*/g, \":\");\n return s;\n}\n\nfunction normalizeName(input: string): string {\n const words = collapseWhitespace(input)\n .split(\" \")\n .filter((w) => w.length > 0);\n return words.map(capitalizeHyphenatedWord).join(\" \");\n}\n\nfunction capitalizeHyphenatedWord(word: string): string {\n if (!word) return word;\n return word.split(\"-\").map(capitalizeWord).join(\"-\");\n}\n\nfunction capitalizeWord(word: string): string {\n if (!word) return word;\n const locale = PrimitivesDefaults.culture;\n const lowered = word.toLocaleLowerCase(locale);\n for (let i = 0; i < lowered.length; i++) {\n const ch = lowered[i]!;\n if (isLetter(ch)) {\n return lowered.slice(0, i) + ch.toLocaleUpperCase(locale) + lowered.slice(i + 1);\n }\n }\n return lowered;\n}\n\nfunction isLetter(ch: string): boolean {\n return /\\p{L}/u.test(ch);\n}\n\n/**\n * Masks the property designation preserving the name, e.g.\n * `Stockholm Söder 75:2` → `Stockholm Söder **:*`.\n */\nexport function maskSwedishPropertyDesignation(d: SwedishPropertyDesignation): string {\n const block = \"*\".repeat(d.blockNumber.toString().length);\n const unit = \"*\".repeat(d.unitNumber.toString().length);\n return `${d.designationName} ${block}:${unit}`;\n}\n\n/** Returns a Lantmäteriet map search URL for the designation. */\nexport function getLantmaterietUrl(d: SwedishPropertyDesignation): string {\n return `https://minkarta.lantmateriet.se/?search=${encodeURIComponent(d.value)}`;\n}\n\n/** Returns a Hitta.se map search URL for the designation. */\nexport function getPropertyHittaUrl(d: SwedishPropertyDesignation): string {\n return `https://www.hitta.se/kartan?s=${encodeURIComponent(d.value)}`;\n}\n","import { PrimitiveTypeInfo } from \"../primitive-type-info.js\";\nimport { PrimitivesDefaults } from \"../primitives-defaults.js\";\nimport { keepDigits } from \"../internal/input-sanitization.js\";\n\nconst MAX_INPUT_LENGTH = 20;\n\n/**\n * Main category derived from the first digit of a Swedish property taxation code (`typkod`).\n */\nexport const SwedishPropertyTaxationCategory = {\n Unknown: \"Unknown\",\n Lantbruksenhet: \"Lantbruksenhet\",\n Smahusenhet: \"Smahusenhet\",\n Hyreshusenhet: \"Hyreshusenhet\",\n Industrienhet: \"Industrienhet\",\n Taktmark: \"Taktmark\",\n Elproduktionsenhet: \"Elproduktionsenhet\",\n Specialenhet: \"Specialenhet\",\n OvrigMark: \"OvrigMark\",\n} as const;\n\nexport type SwedishPropertyTaxationCategory =\n (typeof SwedishPropertyTaxationCategory)[keyof typeof SwedishPropertyTaxationCategory];\n\nconst CATEGORY_BY_FIRST_DIGIT: Record<number, SwedishPropertyTaxationCategory> = {\n 1: SwedishPropertyTaxationCategory.Lantbruksenhet,\n 2: SwedishPropertyTaxationCategory.Smahusenhet,\n 3: SwedishPropertyTaxationCategory.Hyreshusenhet,\n 4: SwedishPropertyTaxationCategory.Industrienhet,\n 5: SwedishPropertyTaxationCategory.Taktmark,\n 6: SwedishPropertyTaxationCategory.Elproduktionsenhet,\n 7: SwedishPropertyTaxationCategory.Specialenhet,\n 8: SwedishPropertyTaxationCategory.OvrigMark,\n};\n\ninterface KnownCode {\n readonly english: string;\n readonly swedish: string;\n}\n\nconst KNOWN_CODES: Readonly<Record<number, KnownCode>> = {\n 110: { english: \"Agricultural unit, undeveloped\", swedish: \"Lantbruksenhet, obebyggd\" },\n 113: {\n english: \"Agricultural unit, with farm building only\",\n swedish: \"Lantbruksenhet, obebyggd, enbart med ekonomibyggnad\",\n },\n 120: { english: \"Agricultural unit, developed\", swedish: \"Lantbruksenhet, bebyggd\" },\n\n 210: { english: \"Small house unit, land only\", swedish: \"Småhusenhet, tomtmark\" },\n 213: {\n english: \"Small house unit, land with building value under 50 000 SEK\",\n swedish: \"Småhusenhet, tomtmark med byggnadsvärde under 50 000 kr\",\n },\n 220: { english: \"Small house unit, developed\", swedish: \"Småhusenhet, bebyggd\" },\n 221: {\n english: \"Small house unit, developed with two houses\",\n swedish: \"Småhusenhet, bebyggd med två småhus\",\n },\n 225: {\n english: \"Small house unit, on leasehold\",\n swedish: \"Småhusenhet, bebyggd på ofri grund\",\n },\n 230: {\n english: \"Small house unit, developed, cluster housing\",\n swedish: \"Småhusenhet, bebyggd, grupphusområde\",\n },\n\n 310: { english: \"Rental property unit, land only\", swedish: \"Hyreshusenhet, tomtmark\" },\n 313: {\n english: \"Rental property unit, land with building value under 50 000 SEK\",\n swedish: \"Hyreshusenhet, tomtmark med byggnadsvärde under 50 000 kr\",\n },\n 320: {\n english: \"Rental property unit, developed, residential\",\n swedish: \"Hyreshusenhet, bebyggd, bostäder\",\n },\n 321: {\n english: \"Rental property unit, developed, residential and commercial\",\n swedish: \"Hyreshusenhet, bebyggd, bostäder och lokaler\",\n },\n 325: {\n english: \"Rental property unit, developed, commercial\",\n swedish: \"Hyreshusenhet, bebyggd, lokaler\",\n },\n 381: {\n english: \"Rental property unit, developed, residential (special)\",\n swedish: \"Hyreshusenhet, bebyggd, bostäder (specialenhet)\",\n },\n\n 410: { english: \"Industrial unit, land only\", swedish: \"Industrienhet, tomtmark\" },\n 420: { english: \"Industrial unit, developed\", swedish: \"Industrienhet, bebyggd\" },\n 421: {\n english: \"Industrial unit, developed with rental property area\",\n swedish: \"Industrienhet, bebyggd med hyreshusareal\",\n },\n 498: { english: \"Industrial unit, petrol station\", swedish: \"Industrienhet, bensinstation\" },\n\n 510: { english: \"Quarry land, undeveloped\", swedish: \"Täktmark, obebyggd\" },\n 520: { english: \"Quarry land, developed\", swedish: \"Täktmark, bebyggd\" },\n\n 610: {\n english: \"Power production unit, hydropower\",\n swedish: \"Elproduktionsenhet, vattenkraftverk\",\n },\n 620: {\n english: \"Power production unit, thermal power\",\n swedish: \"Elproduktionsenhet, värmekraftverk\",\n },\n 630: {\n english: \"Power production unit, wind power\",\n swedish: \"Elproduktionsenhet, vindkraftverk\",\n },\n\n 710: { english: \"Communication building\", swedish: \"Kommunikationsbyggnad\" },\n 720: { english: \"Distribution building\", swedish: \"Distributionsbyggnad\" },\n 730: { english: \"Cultural building\", swedish: \"Kulturbyggnad\" },\n\n 810: { english: \"Special unit, undeveloped land\", swedish: \"Specialenhet, obebyggd mark\" },\n 890: { english: \"Other land\", swedish: \"Övrig mark\" },\n};\n\n/**\n * A Swedish property taxation code (`typkod`), e.g. `220` (Småhusenhet, bebyggd).\n * 3-digit numeric code assigned by Skatteverket.\n */\nexport class SwedishPropertyTaxationCode {\n static readonly typeInfo: PrimitiveTypeInfo = Object.freeze({\n englishName: \"Property Taxation Code\",\n localizedName: \"Typkod\",\n emoji: \"\\u{1F3D7}\\uFE0F\",\n sources: Object.freeze([\n \"https://www.skatteverket.se/privat/fastigheterochbostad/fastighetstaxering.4.69ef368911e1304a625800013531.html\",\n \"https://sv.wikipedia.org/wiki/Typkod_(fastighet)\",\n ]),\n });\n\n /** The 3-digit taxation code, e.g. `220`. */\n readonly code: string;\n /** The numeric form of the code, e.g. `220`. */\n readonly numericCode: number;\n /** The main property category (derived from the first digit). */\n readonly category: SwedishPropertyTaxationCategory;\n /** English description, or `null` when the code is not in the known list. */\n readonly englishDescription: string | null;\n /** Localized (Swedish) description, or `null` when not in the known list. */\n readonly localizedDescription: string | null;\n\n /** `true` when this code has a known description. */\n get isKnown(): boolean {\n return this.englishDescription !== null;\n }\n\n /** Display description in the current display language; falls back to the code. */\n get displayDescription(): string {\n const desc = PrimitivesDefaults.useLocalizedDisplayNames\n ? this.localizedDescription\n : this.englishDescription;\n return desc ?? this.code;\n }\n\n private constructor(\n code: string,\n numericCode: number,\n category: SwedishPropertyTaxationCategory,\n englishDescription: string | null,\n localizedDescription: string | null,\n ) {\n this.code = code;\n this.numericCode = numericCode;\n this.category = category;\n this.englishDescription = englishDescription;\n this.localizedDescription = localizedDescription;\n }\n\n static tryParse(input: string | null | undefined): SwedishPropertyTaxationCode | null {\n if (input == null || input.trim() === \"\") return null;\n const digits = keepDigits(input);\n if (digits.length > MAX_INPUT_LENGTH) return null;\n if (digits.length !== 3) return null;\n const numeric = Number(digits);\n if (!Number.isFinite(numeric) || numeric < 100 || numeric > 999) return null;\n\n const firstDigit = Math.floor(numeric / 100);\n const category = CATEGORY_BY_FIRST_DIGIT[firstDigit];\n if (!category || category === SwedishPropertyTaxationCategory.Unknown) return null;\n\n const known = KNOWN_CODES[numeric];\n return new SwedishPropertyTaxationCode(\n digits,\n numeric,\n category,\n known?.english ?? null,\n known?.swedish ?? null,\n );\n }\n\n static parse(input: string): SwedishPropertyTaxationCode {\n const r = SwedishPropertyTaxationCode.tryParse(input);\n if (r === null) throw new Error(\"Invalid Swedish property taxation code.\");\n return r;\n }\n\n static isValid(input: string | null | undefined): boolean {\n return SwedishPropertyTaxationCode.tryParse(input) !== null;\n }\n\n static format(\n input: string | null | undefined,\n options?: { fallbackToTrimmedInputWhenInvalid?: boolean },\n ): string | null {\n const r = SwedishPropertyTaxationCode.tryParse(input);\n if (r) return r.displayDescription;\n if (options?.fallbackToTrimmedInputWhenInvalid && input != null && input.trim() !== \"\") {\n return input.trim();\n }\n return null;\n }\n\n static normalize(\n input: string | null | undefined,\n options?: { fallbackToTrimmedInputWhenInvalid?: boolean },\n ): string | null {\n const r = SwedishPropertyTaxationCode.tryParse(input);\n if (r) return r.code;\n if (options?.fallbackToTrimmedInputWhenInvalid && input != null && input.trim() !== \"\") {\n return input.trim();\n }\n return null;\n }\n\n static isNormalized(input: string | null | undefined): boolean {\n return input != null && SwedishPropertyTaxationCode.normalize(input) === input;\n }\n\n toNormalizedString(): string {\n return this.code;\n }\n toString(): string {\n return this.displayDescription;\n }\n\n equals(other: SwedishPropertyTaxationCode | null | undefined): boolean {\n return other != null && this.code === other.code;\n }\n compareTo(other: SwedishPropertyTaxationCode | null | undefined): number {\n if (other == null) return 1;\n return this.code < other.code ? -1 : this.code > other.code ? 1 : 0;\n }\n}\n"]}
|