`;
20 |
21 | const heading: Element | null = document.querySelector(tagListQuery);
22 | if (heading == null) return;
23 |
24 | heading.insertAdjacentHTML(
25 | "afterbegin",
26 | `
27 | -
28 | masterpiece
29 |
30 | -
31 | masterpiece
32 |
33 |
`
34 | );
35 |
36 | heading.insertAdjacentHTML(
37 | "afterbegin",
38 | `
Quality Tag
`
39 | );
40 |
41 | heading.insertAdjacentHTML(
42 | "afterbegin",
43 | `
`
53 | );
54 |
55 | heading.insertAdjacentHTML(
56 | "afterbegin",
57 | `
Danbooru To Prompt
`
58 | );
59 |
60 | const listItemQuery = "ul>li";
61 | const emphasisUpQuery = ".emphasis-up-icon";
62 | const emphasisDownQuery = ".emphasis-down-icon";
63 | const emphasisSpanQuery = "span.data-tag-emphasis";
64 | heading.querySelectorAll(listItemQuery).forEach((li) => {
65 | li.insertAdjacentHTML("afterbegin", InsertElement);
66 | });
67 | heading.querySelectorAll(emphasisUpQuery).forEach((icon) => {
68 | icon.addEventListener("click", (e) => {
69 | let emphasis = icon.parentElement?.querySelector(emphasisSpanQuery);
70 | if (emphasis === undefined) return;
71 | if (emphasis === null) return;
72 | let strength = parseFloat(emphasis.getAttribute("emphasis") ?? "1") + 0.1;
73 | if (strength >= 1.8) return;
74 | emphasis.setAttribute("emphasis", strength.toFixed(1));
75 | emphasis.innerHTML = strength.toFixed(1);
76 | });
77 | });
78 | heading.querySelectorAll(emphasisDownQuery).forEach((icon) => {
79 | icon.addEventListener("click", (e) => {
80 | let emphasis = icon.parentElement?.querySelector(emphasisSpanQuery);
81 | if (emphasis === undefined) return;
82 | if (emphasis === null) return;
83 | let strength = parseFloat(emphasis.getAttribute("emphasis") ?? "1") - 0.1;
84 | if (strength <= 0.01) return;
85 | emphasis.setAttribute("emphasis", strength.toFixed(1));
86 | emphasis.innerHTML = strength.toFixed(1);
87 | });
88 | });
89 |
90 | const getChecked = (): string[] => {
91 | return sort(
92 |
(
93 | [...heading.querySelectorAll(checkedQuery)]
94 | .map((input) => input?.parentElement?.parentElement)
95 | .filter((value) => value !== null)
96 | )
97 | ).map((value) =>
98 | emphasis(
99 | escape(value.getAttribute("data-tag-name")!),
100 | parseFloat(
101 | value.querySelector(emphasisSpanQuery)?.getAttribute("emphasis") ??
102 | "1.0"
103 | )
104 | )
105 | );
106 | };
107 |
108 | const toSimply = (word: Element[]): Element[] => {
109 | return word.filter((value) =>
110 | word
111 | .map((text) => {
112 | let textAttr = text.getAttribute("data-tag-name");
113 | let valueAttr = value.getAttribute("data-tag-name");
114 | if (textAttr == null) return false;
115 | if (valueAttr == null) return false;
116 | if (valueAttr == textAttr) return false;
117 | return ["", "ing", "ed", "s"]
118 | .map((end) => {
119 | if (!valueAttr!.endsWith(end)) return false;
120 | return textAttr!.includes(
121 | valueAttr!.replace(new RegExp(end + "$"), "")
122 | );
123 | })
124 | .some((v) => v === true);
125 | })
126 | .every((v) => v === false)
127 | );
128 | };
129 |
130 | const emphasis = (word: string, factor: number): string => {
131 | if (factor == 1) return word;
132 | if (factor == 1.1) return "(" + word + ")";
133 | return "(" + word + ":" + factor.toFixed(1) + ")";
134 | };
135 |
136 | const escape = (word: string): string => {
137 | return word
138 | .replace("(", "\\(")
139 | .replace(")", "\\)")
140 | .replace("[", "\\[")
141 | .replace("]", "\\]");
142 | };
143 |
144 | const sort = (value: Element[]): Element[] => {
145 | return value.sort((a: Element, b: Element) => {
146 | const titleA: Number = Number(
147 | a.querySelector("span[title]")?.getAttribute("title")
148 | );
149 | const titleB: Number = Number(
150 | b.querySelector("span[title]")?.getAttribute("title")
151 | );
152 | if (titleA > titleB) return -1;
153 | else if (titleA < titleB) return 1;
154 | else return 0;
155 | });
156 | };
157 |
158 | const clacTokenSize = (value: string): number => {
159 | const re = new RegExp("([0-90-9]{1,4}|[a-zA-Z]{1,4})", "g");
160 |
161 | return value.match(re)?.length ?? 0;
162 | };
163 | const getTokenSize = (): number => {
164 | return Math.floor(
165 | getChecked()
166 | .map((value) => Number(clacTokenSize(value)))
167 | .reduce((sum, element) => sum + element, 0) * 0.9
168 | );
169 | };
170 |
171 | const changeTokenSize = () => {
172 | const text: string | undefined = getTokenSize().toString();
173 | const tokenSize: Element | null = document.getElementById("d2p-token-size");
174 | if (text === undefined) text == "error";
175 | if (tokenSize === null) return;
176 | tokenSize.innerHTML = text;
177 | };
178 |
179 | heading.querySelectorAll(checkboxQuery).forEach((e) => {
180 | e.addEventListener("change", (_) => changeTokenSize());
181 | });
182 |
183 | document
184 | .getElementById("d2p-auto-select")
185 | ?.addEventListener("click", (button: MouseEvent) => {
186 | const tagList = [...heading.querySelectorAll(tagQuery)]
187 | .filter((tag) => tag.getAttribute("data-tag-name") !== null)
188 | .filter((tag) => tag.querySelector(checkboxQuery) !== null);
189 |
190 | tagList.forEach((value) => {
191 | (value.querySelector(checkboxQuery) as HTMLInputElement).checked =
192 | false;
193 | });
194 | let length = getTokenSize();
195 | sort(toSimply(tagList)).forEach((value: Element) => {
196 | const input = value.getAttribute("data-tag-name");
197 | if (input == null) return;
198 | if (length + clacTokenSize(input) > 75) return;
199 | (value.querySelector(checkboxQuery) as HTMLInputElement).checked = true;
200 | length += clacTokenSize(input);
201 | });
202 | changeTokenSize();
203 | });
204 |
205 | document
206 | .getElementById("d2p-all-select")
207 | ?.addEventListener("click", (button: MouseEvent) => {
208 | const tagList = [...heading.querySelectorAll(tagQuery)]
209 | .filter((tag) => tag.getAttribute("data-tag-name") !== null)
210 | .filter((tag) => tag.querySelector(checkboxQuery) !== null);
211 |
212 | tagList.forEach((value) => {
213 | (value.querySelector(checkboxQuery) as HTMLInputElement).checked = true;
214 | });
215 | changeTokenSize();
216 | });
217 |
218 | document
219 | .getElementById("d2p-copy")
220 | ?.addEventListener("click", (button: MouseEvent) => {
221 | const output = getChecked().join(" ");
222 | console.log(`${HEADER}\n${output}`);
223 | return navigator.clipboard
224 | .writeText(output)
225 | .then(
226 | () => {
227 | console.log(`${HEADER} success`);
228 | (button.target as Element).innerHTML = "success";
229 | },
230 | () => {
231 | console.log(`${HEADER} failed`);
232 | (button.target as Element).innerHTML = "failed";
233 | }
234 | )
235 | .then(() =>
236 | setTimeout(
237 | () => ((button.target as Element).innerHTML = "copy to clipboard"),
238 | 2000
239 | )
240 | );
241 | });
242 | });
243 |
--------------------------------------------------------------------------------