@kangsicj/dcinsideenhancer 1.3.2 → 1.3.4

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/LICENSE CHANGED
@@ -1,21 +1,232 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 jinny
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+
6
+ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for software and other kinds of works.
11
+
12
+ The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
13
+
14
+ When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
15
+
16
+ To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
17
+
18
+ For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
19
+
20
+ Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
21
+
22
+ For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
23
+
24
+ Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
25
+
26
+ Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
27
+
28
+ The precise terms and conditions for copying, distribution and modification follow.
29
+
30
+ TERMS AND CONDITIONS
31
+
32
+ 0. Definitions.
33
+
34
+ “This License” refers to version 3 of the GNU General Public License.
35
+
36
+ “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
37
+
38
+ “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
39
+
40
+ To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
41
+
42
+ A “covered work” means either the unmodified Program or a work based on the Program.
43
+
44
+ To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
45
+
46
+ To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
47
+
48
+ An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
49
+
50
+ 1. Source Code.
51
+ The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
52
+
53
+ A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
54
+
55
+ The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
56
+
57
+ The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
58
+
59
+ The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
60
+
61
+ The Corresponding Source for a work in source code form is that same work.
62
+
63
+ 2. Basic Permissions.
64
+ All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
65
+
66
+ You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
67
+
68
+ Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
69
+
70
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
71
+ No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
72
+
73
+ When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
74
+
75
+ 4. Conveying Verbatim Copies.
76
+ You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
77
+
78
+ You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
79
+
80
+ 5. Conveying Modified Source Versions.
81
+ You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
82
+
83
+ a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
84
+
85
+ b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
86
+
87
+ c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
88
+
89
+ d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
90
+
91
+ A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
92
+
93
+ 6. Conveying Non-Source Forms.
94
+ You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
95
+
96
+ a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
97
+
98
+ b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
99
+
100
+ c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
101
+
102
+ d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
103
+
104
+ e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
105
+
106
+ A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
107
+
108
+ A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
109
+
110
+ “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
111
+
112
+ If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
113
+
114
+ The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
115
+
116
+ Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
117
+
118
+ 7. Additional Terms.
119
+ “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
120
+
121
+ When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
122
+
123
+ Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
124
+
125
+ a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
126
+
127
+ b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
128
+
129
+ c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
130
+
131
+ d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
132
+
133
+ e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
134
+
135
+ f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
136
+
137
+ All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
138
+
139
+ If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
140
+
141
+ Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
142
+
143
+ 8. Termination.
144
+ You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
145
+
146
+ However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
147
+
148
+ Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
149
+
150
+ Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
151
+
152
+ 9. Acceptance Not Required for Having Copies.
153
+ You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
154
+
155
+ 10. Automatic Licensing of Downstream Recipients.
156
+ Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
157
+
158
+ An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
159
+
160
+ You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
161
+
162
+ 11. Patents.
163
+ A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
164
+
165
+ A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
166
+
167
+ Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
168
+
169
+ In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
170
+
171
+ If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
172
+
173
+ If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
174
+
175
+ A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
176
+
177
+ Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
178
+
179
+ 12. No Surrender of Others' Freedom.
180
+ If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
181
+
182
+ 13. Use with the GNU Affero General Public License.
183
+ Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
184
+
185
+ 14. Revised Versions of this License.
186
+ The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
187
+
188
+ Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
189
+
190
+ If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
191
+
192
+ Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
193
+
194
+ 15. Disclaimer of Warranty.
195
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
196
+
197
+ 16. Limitation of Liability.
198
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
199
+
200
+ 17. Interpretation of Sections 15 and 16.
201
+ If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
202
+
203
+ END OF TERMS AND CONDITIONS
204
+
205
+ How to Apply These Terms to Your New Programs
206
+
207
+ If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
208
+
209
+ To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
210
+
211
+ <one line to give the program's name and a brief idea of what it does.>
212
+ Copyright (C) <year> <name of author>
213
+
214
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
215
+
216
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
217
+
218
+ You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
219
+
220
+ Also add information on how to contact you by electronic and paper mail.
221
+
222
+ If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
223
+
224
+ <program> Copyright (C) <year> <name of author>
225
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
226
+ This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
227
+
228
+ The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
229
+
230
+ You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
231
+
232
+ The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/philosophy/why-not-lgpl.html>.
package/README.en.md CHANGED
@@ -7,7 +7,8 @@
7
7
  <a href="https://cdn.jsdelivr.net/npm/@kangsicj/dcinsideenhancer@latest/dist/DCInsideEnhancer.user.js"><img src="https://img.shields.io/npm/v/%40kangsicj%2Fdcinsideenhancer?label=Install&color=3b4890&style=for-the-badge&logo=tampermonkey&logoColor=white&cacheSeconds=1800" alt="Install"></a>
8
8
  <img src="https://img.shields.io/badge/iPhone%20%C2%B7%20Android%20%C2%B7%20PC-supported-5865c7?style=for-the-badge" alt="iPhone · Android · PC">
9
9
  <img src="https://img.shields.io/badge/ads%20%26%20tracking-none-2e7d5b?style=for-the-badge" alt="No ads or tracking">
10
- <a href="https://fairy.hada.io/@jinny#support"><img src="https://img.shields.io/badge/Fairy-Support-ff6fb5?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Support on Fairy"></a>
10
+ <a href="https://fairy.hada.io/@kangsicj"><img src="https://img.shields.io/badge/Fairy-Support-ff6fb5?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Support on Fairy"></a>
11
+ <a href="https://buymeacoffee.com/kangsicj"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-Support-ffdd00?style=for-the-badge&logo=buymeacoffee&logoColor=black" alt="Buy Me a Coffee"></a>
11
12
 
12
13
  [한국어](README.md) · **English**
13
14
 
@@ -18,6 +19,15 @@ One userscript for DCInside on mobile and PC: smart blocking, endless lists, ima
18
19
 
19
20
  ---
20
21
 
22
+ ## 🎯 Why it exists
23
+
24
+ - **App-like, without the app.** The DCInside app experience in any browser — including app-only features and ones you won't find anywhere else.
25
+ - **Gentle on the site.** Only the requests it needs, spaced out. If DCInside throttles, it backs off and resumes on its own.
26
+ - **Your data stays on your device.** Block lists, settings and scraps are stored locally. No ads, analytics or tracking.
27
+ - **Sync only if you want it.** Off until you turn it on, and no account or sign-up. Everything is encrypted on your device before it leaves, so the server can read neither the content nor whose it is. Link phones, tablets and PCs with a short code and unlink everything at any time. Sync boxes nobody uses for a long time are deleted from the server automatically.
28
+
29
+ ---
30
+
21
31
  ## ✨ At a glance
22
32
 
23
33
  <table>
@@ -157,8 +167,10 @@ Meanwhile, **Show all** in the floating menu temporarily reveals everything.
157
167
  This is a personal project, built and polished in spare time. Every feature is free and will stay that way.
158
168
  If it helps you, a coffee keeps the updates coming.
159
169
 
160
- <a href="https://fairy.hada.io/@jinny#support"><img src="https://img.shields.io/badge/%E2%98%95%20Support%20on%20Fairy-ff6fb5?style=for-the-badge" alt="Support on Fairy"></a>
170
+ <a href="https://fairy.hada.io/@kangsicj"><img src="https://img.shields.io/badge/Fairy-Support-ff6fb5?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Support on Fairy"></a>
171
+ <a href="https://buymeacoffee.com/kangsicj"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-Support-ffdd00?style=for-the-badge&logo=buymeacoffee&logoColor=black" alt="Buy Me a Coffee"></a>
161
172
 
162
173
  ## 📄 License
163
174
 
164
- [MIT](LICENSE) · An independent project, not affiliated with DCInside.
175
+ [GNU GPL v3.0](LICENSE) · An independent project, not affiliated with DCInside.
176
+ If you modify or redistribute it, please share the source under the same GPL v3.0.
package/README.md CHANGED
@@ -7,7 +7,8 @@
7
7
  <a href="https://cdn.jsdelivr.net/npm/@kangsicj/dcinsideenhancer@latest/dist/DCInsideEnhancer.user.js"><img src="https://img.shields.io/npm/v/%40kangsicj%2Fdcinsideenhancer?label=%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0&color=3b4890&style=for-the-badge&logo=tampermonkey&logoColor=white&cacheSeconds=1800" alt="설치하기"></a>
8
8
  <img src="https://img.shields.io/badge/iPhone%20%C2%B7%20Android%20%C2%B7%20PC-%EC%A7%80%EC%9B%90-5865c7?style=for-the-badge" alt="iPhone · Android · PC 지원">
9
9
  <img src="https://img.shields.io/badge/%EA%B4%91%EA%B3%A0%C2%B7%EC%B6%94%EC%A0%81-%EC%97%86%EC%9D%8C-2e7d5b?style=for-the-badge" alt="광고·추적 없음">
10
- <a href="https://fairy.hada.io/@jinny#support"><img src="https://img.shields.io/badge/Fairy-%ED%9B%84%EC%9B%90%ED%95%98%EA%B8%B0-ff6fb5?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Fairy로 후원하기"></a>
10
+ <a href="https://fairy.hada.io/@kangsicj"><img src="https://img.shields.io/badge/Fairy-%ED%9B%84%EC%9B%90%ED%95%98%EA%B8%B0-ff6fb5?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Fairy로 후원하기"></a>
11
+ <a href="https://buymeacoffee.com/kangsicj"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-%ED%9B%84%EC%9B%90%ED%95%98%EA%B8%B0-ffdd00?style=for-the-badge&logo=buymeacoffee&logoColor=black" alt="Buy Me a Coffee로 후원하기"></a>
11
12
 
12
13
  **한국어** · [English](README.en.md)
13
14
 
@@ -18,6 +19,15 @@
18
19
 
19
20
  ---
20
21
 
22
+ ## 🎯 만든 이유
23
+
24
+ - **앱 없이도 앱처럼.** 웹 브라우저만으로 디시인사이드 앱에서 쓰던 경험을 그대로, 앱에만 있던 기능과 여기에만 있는 기능까지 함께.
25
+ - **사이트에 부담 주지 않기.** 필요한 요청만, 간격을 두고 보냅니다. 디시가 잠시 막으면 스스로 쉬었다가 다시 시작합니다.
26
+ - **내 데이터는 내 기기에.** 차단 목록·설정·스크랩은 기기 안에만 저장됩니다. 광고·분석·추적 코드가 없습니다.
27
+ - **동기화는 원하는 사람만.** 켜야만 동작하고, 계정이나 가입이 필요 없습니다. 내용은 기기에서 암호화된 뒤 보내므로 서버는 내용도, 누구의 것인지도 알 수 없습니다. 연결 코드만 있으면 휴대폰·태블릿·PC 어디든 연결되고, 언제든 모든 연결을 끊을 수 있습니다. 오래 쓰지 않은 동기화 보관함은 서버에서 저절로 지워집니다.
28
+
29
+ ---
30
+
21
31
  ## ✨ 한눈에 보기
22
32
 
23
33
  <table>
@@ -157,8 +167,10 @@
157
167
  틈틈이 만들고 다듬는 개인 프로젝트입니다. 모든 기능은 무료이며 앞으로도 그렇습니다.
158
168
  도움이 되셨다면 커피 한 잔으로 응원해 주세요. 더 빠른 업데이트의 원동력이 됩니다.
159
169
 
160
- <a href="https://fairy.hada.io/@jinny#support"><img src="https://img.shields.io/badge/%E2%98%95%20Fairy%EB%A1%9C%20%ED%9B%84%EC%9B%90%ED%95%98%EA%B8%B0-ff6fb5?style=for-the-badge" alt="Fairy로 후원하기"></a>
170
+ <a href="https://fairy.hada.io/@kangsicj"><img src="https://img.shields.io/badge/Fairy-%ED%9B%84%EC%9B%90%ED%95%98%EA%B8%B0-ff6fb5?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Fairy로 후원하기"></a>
171
+ <a href="https://buymeacoffee.com/kangsicj"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-%ED%9B%84%EC%9B%90%ED%95%98%EA%B8%B0-ffdd00?style=for-the-badge&logo=buymeacoffee&logoColor=black" alt="Buy Me a Coffee로 후원하기"></a>
161
172
 
162
173
  ## 📄 라이선스
163
174
 
164
- [MIT](LICENSE) · 디시인사이드와 관계없는 개인 프로젝트입니다.
175
+ [GNU GPL v3.0](LICENSE) · 디시인사이드와 관계없는 개인 프로젝트입니다.
176
+ 고쳐 쓰거나 다시 배포할 때는 같은 GPL v3.0 으로 소스를 함께 공개해 주세요.
@@ -2,15 +2,15 @@
2
2
  // @name DCInside Enhancer
3
3
  // @name:ko 디시 인핸서
4
4
  // @namespace https://github.com/kangsicj/DCInsideEnhancer
5
- // @version 1.3.2
6
- // @description DCInside filter & enhancer — mobile & PC. Block users/words/heads/notices/images & GIFs across posts, infinite list, zoom viewer, theme sync, encrypted multi-device sync.
7
- // @description:ko 디시인사이드 차단·편의 기능 (모바일·PC) - 유저·단어(제목/본문)·말머리·공지 차단, 같은/비슷한 이미지·움짤 모든 글 차단, 디시콘 제거, 차단 미디어 데이터 절약, 목록 자동 보충·무한 스크롤·뒤로 가기 위치 복원, 스크랩, 이미지 확대뷰 개선, 야간모드 자동 연동, 암호화 기기 간 동기화
5
+ // @version 1.3.4
6
+ // @description DCInside filter & enhancer — mobile & PC. Block users/words/heads/notices/images & GIFs across posts, infinite list, zoom viewer, theme sync, encrypted multi-device sync (no account, no tracking).
7
+ // @description:ko 디시인사이드 차단·편의 기능 (모바일·PC) - 유저·단어(제목/본문)·말머리·공지 차단, 같은/비슷한 이미지·움짤 모든 글 차단, 디시콘 제거, 차단 미디어 데이터 절약, 목록 자동 보충·무한 스크롤·뒤로 가기 위치 복원, 스크랩, 이미지 확대뷰 개선, 야간모드 자동 연동, 암호화 기기 간 동기화 (계정 없음·추적 없음)
8
8
  // @author kangsicj
9
- // @license MIT
9
+ // @license GPL-3.0-only
10
10
  // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJnIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjNTg2NWM3Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMmQzNzc4Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMTUiIGZpbGw9InVybCgjZykiLz48cGF0aCBkPSJNMzIgMTEgNDkgMTd2MTNjMCAxMS03LjMgMTkuNi0xNyAyMy05LjctMy40LTE3LTEyLTE3LTIzVjE3eiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Im0yNC41IDMyLjUgNS4yIDUuMiAxMC4zLTExIiBmaWxsPSJub25lIiBzdHJva2U9IiMzYjQ4OTAiIHN0cm9rZS13aWR0aD0iNC42IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4K
11
11
  // @homepageURL https://github.com/kangsicj/DCInsideEnhancer
12
12
  // @supportURL https://github.com/kangsicj/DCInsideEnhancer/issues
13
- // @contributionURL https://fairy.hada.io/@jinny
13
+ // @contributionURL https://buymeacoffee.com/kangsicj
14
14
  // @updateURL https://cdn.jsdelivr.net/npm/@kangsicj/dcinsideenhancer@latest/dist/DCInsideEnhancer.meta.js
15
15
  // @downloadURL https://cdn.jsdelivr.net/npm/@kangsicj/dcinsideenhancer@latest/dist/DCInsideEnhancer.user.js
16
16
  // @match *://m.dcinside.com/*
@@ -2,15 +2,15 @@
2
2
  // @name DCInside Enhancer
3
3
  // @name:ko 디시 인핸서
4
4
  // @namespace https://github.com/kangsicj/DCInsideEnhancer
5
- // @version 1.3.2
6
- // @description DCInside filter & enhancer — mobile & PC. Block users/words/heads/notices/images & GIFs across posts, infinite list, zoom viewer, theme sync, encrypted multi-device sync.
7
- // @description:ko 디시인사이드 차단·편의 기능 (모바일·PC) - 유저·단어(제목/본문)·말머리·공지 차단, 같은/비슷한 이미지·움짤 모든 글 차단, 디시콘 제거, 차단 미디어 데이터 절약, 목록 자동 보충·무한 스크롤·뒤로 가기 위치 복원, 스크랩, 이미지 확대뷰 개선, 야간모드 자동 연동, 암호화 기기 간 동기화
5
+ // @version 1.3.4
6
+ // @description DCInside filter & enhancer — mobile & PC. Block users/words/heads/notices/images & GIFs across posts, infinite list, zoom viewer, theme sync, encrypted multi-device sync (no account, no tracking).
7
+ // @description:ko 디시인사이드 차단·편의 기능 (모바일·PC) - 유저·단어(제목/본문)·말머리·공지 차단, 같은/비슷한 이미지·움짤 모든 글 차단, 디시콘 제거, 차단 미디어 데이터 절약, 목록 자동 보충·무한 스크롤·뒤로 가기 위치 복원, 스크랩, 이미지 확대뷰 개선, 야간모드 자동 연동, 암호화 기기 간 동기화 (계정 없음·추적 없음)
8
8
  // @author kangsicj
9
- // @license MIT
9
+ // @license GPL-3.0-only
10
10
  // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJnIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjNTg2NWM3Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMmQzNzc4Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMTUiIGZpbGw9InVybCgjZykiLz48cGF0aCBkPSJNMzIgMTEgNDkgMTd2MTNjMCAxMS03LjMgMTkuNi0xNyAyMy05LjctMy40LTE3LTEyLTE3LTIzVjE3eiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Im0yNC41IDMyLjUgNS4yIDUuMiAxMC4zLTExIiBmaWxsPSJub25lIiBzdHJva2U9IiMzYjQ4OTAiIHN0cm9rZS13aWR0aD0iNC42IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4K
11
11
  // @homepageURL https://github.com/kangsicj/DCInsideEnhancer
12
12
  // @supportURL https://github.com/kangsicj/DCInsideEnhancer/issues
13
- // @contributionURL https://fairy.hada.io/@jinny
13
+ // @contributionURL https://buymeacoffee.com/kangsicj
14
14
  // @updateURL https://cdn.jsdelivr.net/npm/@kangsicj/dcinsideenhancer@latest/dist/DCInsideEnhancer.meta.js
15
15
  // @downloadURL https://cdn.jsdelivr.net/npm/@kangsicj/dcinsideenhancer@latest/dist/DCInsideEnhancer.user.js
16
16
  // @match *://m.dcinside.com/*
@@ -23,40 +23,6 @@
23
23
  // @grant none
24
24
  // ==/UserScript==
25
25
 
26
- /*
27
- * 파일: DCInsideEnhancer.user.js (예전 이름 dcinside_enhancer.user.js · dc-refinery.user.js · dcinside_filter_enhancer.user.js — 같은 폴더에 남아 있으면 삭제)
28
- *
29
- * 구조 안내
30
- * ─────────────────────────────────────────────────────────────
31
- * 0 설정·상수 저장 키, 기본 설정, 판정 규칙, 모바일/PC 구분
32
- * 1 스타일 테마 토큰과 기능별 CSS
33
- * 2 저장소 localStorage 입출력, 목록 정렬, 과거 형식 정리
34
- * 2-1 요청 조절 모든 자동 요청의 간격·한도, 디시 일시 차단 감지
35
- * 3 테마 연동 기기 다크모드 ↔ 사이트 자체 야간모드 (모바일·PC)
36
- * 4 미디어 식별 미디어의 식별자 수집, 차단 판정
37
- * 5 네트워크 선차단 차단 미디어·디시콘이 요청되지 않게 함
38
- * 6 작성자·텍스트 닉네임/IP/식별코드, 제목·단어 매칭
39
- * 7 말머리 갤러리별 말머리·홈 출처 숨김
40
- * 8 미디어 UI 차단 버튼, 데이터 세이버, 디시콘, 확대뷰 슬라이드
41
- * 9 닉네임 팝오버 차단 기준 선택, 사이트 메뉴, 알림
42
- * 10 항목 처리 목록·본문·댓글·홈·통합검색 항목, 읽은 글 색
43
- * 11 차단 기록 가려진 글 기록 (현황 패널·재차단)
44
- * 11-1 본문 미리 검사 본문에만 차단 단어가 있는 글도 목록에서 숨김
45
- * 12 목록 스트림 자동 보충, 무한 스크롤, 페이지 표시, 뒤로 가기 복원
46
- * 13 모달 현황 / 유저 / 차단 목록 / 설정 / 백업
47
- * 14 플로팅 버튼 FAB, 맨 위로 버튼
48
- * 15 이미지 확대뷰 스크롤 잠금, 쓸어내려 닫기 (관리 창 시트 포함)
49
- * 16 초기화 DOM 감시, 실행 순서, 페이지 이동 대응
50
- *
51
- * 공통 원칙
52
- * - 모바일(m.)과 PC(gall./www.)는 화면 구조가 다르다. 선택자는 두 구조를 함께 적고,
53
- * 구조 자체가 다른 곳만 IS_MOBILE_SITE 로 나눈다. 글 주소는 "/board/갤ID/글번호" 키로 저장한다.
54
- * - 사이트 요소의 display·레이아웃은 직접 바꾸지 않는다. 숨길 때는 클래스만 쓰고,
55
- * 표시가 필요하면 스크립트 전용 요소(.dc-ui)를 끼운다.
56
- * - 스크립트가 DOM 을 쓰는 동안에는 withSelfMutation() 으로 감싼다.
57
- * - 사이트로 보내는 요청은 모두 siteFetchText() 를 거친다.
58
- */
59
-
60
26
  (function () {
61
27
  'use strict';
62
28
 
@@ -71,13 +37,10 @@
71
37
  window.__dcInsideEnhancer = true;
72
38
  window.__dcRefinery = true;
73
39
 
74
- // =========================================================
75
- // 0. 설정·상수
76
- // =========================================================
77
-
78
- const SCRIPT_VERSION = '1.3.2';
40
+ const SCRIPT_VERSION = '1.3.4';
79
41
  const PROJECT_URL = 'https://github.com/kangsicj/DCInsideEnhancer';
80
- const DONATE_URL = 'https://fairy.hada.io/@jinny#support';
42
+ const DONATE_URL = 'https://fairy.hada.io/@kangsicj';
43
+ const DONATE_URL_BMC = 'https://buymeacoffee.com/kangsicj';
81
44
 
82
45
  const STORAGE = {
83
46
  users: 'dc_block_list',
@@ -224,7 +187,6 @@
224
187
  hideCommentAds: true,
225
188
  hideCommentFab: true,
226
189
  mobileRecentBar: true,
227
- mobileRecentStrip: true,
228
190
  hideSilbeAlarm: true,
229
191
  alarmBubble: true,
230
192
  alarmKeepPolling: true,
@@ -261,10 +223,6 @@
261
223
  forceDarkFallback: false
262
224
  };
263
225
 
264
- // =========================================================
265
- // 1. 스타일
266
- // =========================================================
267
-
268
226
  const LIGHT_TOKENS = `
269
227
  --dc-surface: #ffffff;
270
228
  --dc-surface-2: #f5f6f8;
@@ -2073,17 +2031,16 @@
2073
2031
  #dc-recent-bar {
2074
2032
  display: flex;
2075
2033
  align-items: center;
2076
- gap: 0;
2077
- height: 34px;
2034
+ gap: var(--dc-rb-gap, 30px);
2035
+ height: 40px;
2078
2036
  margin: 0;
2079
- padding: 0 6px;
2037
+ padding: 0 var(--dc-rb-pad, 14px);
2080
2038
  overflow-x: auto;
2081
2039
  overflow-y: hidden;
2082
2040
  -webkit-overflow-scrolling: touch;
2083
2041
  scrollbar-width: none;
2084
2042
  overscroll-behavior-x: contain;
2085
2043
  background: var(--dc-rb-bg, #3b4890);
2086
- border-bottom: 1px solid rgba(255,255,255,.12);
2087
2044
  box-sizing: border-box;
2088
2045
  }
2089
2046
  #dc-recent-bar::-webkit-scrollbar { display: none; }
@@ -2091,74 +2048,23 @@
2091
2048
  flex: 0 0 auto;
2092
2049
  display: inline-flex;
2093
2050
  align-items: center;
2094
- gap: 2px;
2095
- max-width: 46vw;
2096
- height: 34px;
2097
- padding: 0 10px;
2051
+ gap: 3px;
2052
+ max-width: 60vw;
2053
+ height: 40px;
2054
+ padding: 0;
2098
2055
  overflow: hidden;
2099
- color: rgba(255,255,255,.82);
2100
- font-size: 13px;
2101
- font-weight: 500;
2102
- letter-spacing: -.3px;
2056
+ color: var(--dc-rb-color, #fff);
2057
+ font-family: var(--dc-rb-family, inherit);
2058
+ font-size: var(--dc-rb-size, 16px);
2059
+ font-weight: var(--dc-rb-weight, 700);
2060
+ letter-spacing: var(--dc-rb-spacing, normal);
2103
2061
  text-decoration: none;
2104
2062
  text-overflow: ellipsis;
2105
2063
  white-space: nowrap;
2064
+ opacity: .9;
2106
2065
  }
2107
- #dc-recent-bar .dc-rb-item + .dc-rb-item { border-left: 1px solid rgba(255,255,255,.18); }
2108
- #dc-recent-bar .dc-rb-item.on { color: var(--dc-rb-on, #ffe10a); font-weight: 700; }
2109
- #dc-recent-bar .dc-rb-kind { font-size: 11px; opacity: .8; }
2110
-
2111
- html.dc-recent-strip-on #lately_pop.dc-strip-lately #swiper-lately,
2112
- html.dc-recent-strip-on #lately_pop.dc-strip-lately #lately_paging1 { display: none !important; }
2113
- .dc-recent-strip {
2114
- display: flex;
2115
- gap: 8px;
2116
- padding: 12px 12px 14px;
2117
- overflow-x: auto;
2118
- overflow-y: hidden;
2119
- -webkit-overflow-scrolling: touch;
2120
- scroll-snap-type: x proximity;
2121
- scrollbar-width: none;
2122
- overscroll-behavior-x: contain;
2123
- }
2124
- .dc-recent-strip::-webkit-scrollbar { display: none; }
2125
- .dc-recent-strip[hidden] { display: none !important; }
2126
- .dc-recent-strip .dc-rs-chip {
2127
- flex: 0 0 auto;
2128
- display: inline-flex;
2129
- align-items: center;
2130
- gap: 4px;
2131
- max-width: 60vw;
2132
- height: 36px;
2133
- padding: 0 4px 0 14px;
2134
- border: 1px solid var(--dc-border);
2135
- border-radius: 999px;
2136
- background: var(--dc-surface-2);
2137
- color: var(--dc-text);
2138
- font-size: 14px;
2139
- font-weight: 600;
2140
- text-decoration: none;
2141
- white-space: nowrap;
2142
- scroll-snap-align: start;
2143
- }
2144
- .dc-recent-strip .dc-rs-chip.here { border-color: var(--dc-accent-ink); color: var(--dc-accent-ink); background: var(--dc-accent-soft); }
2145
- .dc-recent-strip .dc-rs-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
2146
- .dc-recent-strip .dc-rs-kind { color: var(--dc-text-dim); font-size: 13px; }
2147
- .dc-recent-strip .dc-rs-del {
2148
- flex: 0 0 auto;
2149
- width: 28px;
2150
- height: 28px;
2151
- margin: 0;
2152
- padding: 0;
2153
- border: none;
2154
- border-radius: 50%;
2155
- background: transparent;
2156
- color: var(--dc-text-dim);
2157
- font-size: 18px;
2158
- line-height: 28px;
2159
- }
2160
- .dc-recent-strip .dc-rs-pin,
2161
- .dc-recent-strip .dc-rs-empty { flex: 0 0 auto; align-self: center; padding: 0 6px; color: var(--dc-text-dim); font-size: 12px; white-space: nowrap; }
2066
+ #dc-recent-bar .dc-rb-item.on { color: var(--dc-rb-on, #ffe10a); opacity: 1; }
2067
+ #dc-recent-bar .dc-rb-kind { font-size: .75em; font-weight: 400; opacity: .85; }
2162
2068
 
2163
2069
  .dc-key-cursor { outline: 2px solid var(--dc-accent-ink) !important; outline-offset: -2px; background: var(--dc-accent-soft) !important; }
2164
2070
 
@@ -2196,6 +2102,9 @@
2196
2102
  }
2197
2103
 
2198
2104
  #dc-custom-modal .dc-about a.dc-btn { text-decoration: none; }
2105
+ #dc-custom-modal .dc-about .dc-btn-row { flex-wrap: wrap; }
2106
+ #dc-custom-modal .dc-about .dc-btn-row .dc-btn { flex: 1 1 40%; }
2107
+ #dc-custom-modal .dc-about .dc-btn-row .dc-btn.neutral { flex-basis: 100%; }
2199
2108
 
2200
2109
  #dc-custom-modal .dc-fold-body .dc-btn-row,
2201
2110
  #dc-custom-modal .dc-fold-body .dc-input-row {
@@ -3051,10 +2960,6 @@
3051
2960
 
3052
2961
  ensureStyle();
3053
2962
 
3054
- // =========================================================
3055
- // 2. 저장소
3056
- // =========================================================
3057
-
3058
2963
  const escapeHtml = value =>
3059
2964
  String(value ?? '')
3060
2965
  .replace(/&/g, '&amp;')
@@ -3414,10 +3319,6 @@
3414
3319
 
3415
3320
  migrateStorage();
3416
3321
 
3417
- // =========================================================
3418
- // 2-1. 요청 조절 (디시 접속 차단 방지)
3419
- // =========================================================
3420
-
3421
3322
  const NET_GAP_SCALE = Number.isFinite(window.__dcEnhancerNetScale) ? window.__dcEnhancerNetScale : 1;
3422
3323
  const NET_BG_GAP = 1500 * NET_GAP_SCALE;
3423
3324
  const NET_AUTO_GAP = 1000 * NET_GAP_SCALE;
@@ -3757,10 +3658,6 @@
3757
3658
  return task;
3758
3659
  };
3759
3660
 
3760
- // =========================================================
3761
- // 3. 테마 연동
3762
- // =========================================================
3763
-
3764
3661
  const darkQuery =
3765
3662
  typeof window.matchMedia === 'function'
3766
3663
  ? window.matchMedia('(prefers-color-scheme: dark)')
@@ -4242,9 +4139,6 @@
4242
4139
  rootWatch.observe(document, { childList: true });
4243
4140
  }
4244
4141
  coordinateOtherDarkScripts();
4245
- // =========================================================
4246
- // 4. 미디어 식별
4247
- // =========================================================
4248
4142
 
4249
4143
  const MEDIA_ATTRS = [
4250
4144
  'data-original', 'data-src', 'data-lazy-src', 'data-url', 'data-rel',
@@ -4955,10 +4849,6 @@
4955
4849
  (element.classList.contains('written_dccon') ||
4956
4850
  !!element.closest(`${CONTENT_SCOPE_SELECTOR}, .comment, .comment-add, .txt`));
4957
4851
 
4958
- // =========================================================
4959
- // 5. 네트워크 선차단
4960
- // =========================================================
4961
-
4962
4852
  const nativeSetAttribute = Element.prototype.setAttribute;
4963
4853
  const rawSetAttribute = (element, name, value) => nativeSetAttribute.call(element, name, value);
4964
4854
 
@@ -5241,10 +5131,6 @@
5241
5131
 
5242
5132
  installMediaNetworkGuard();
5243
5133
 
5244
- // =========================================================
5245
- // 6. 작성자·텍스트
5246
- // =========================================================
5247
-
5248
5134
  const IP_PAREN_RE = /\(\s*([0-9]{1,3}\.[0-9]{1,3})\s*\)/;
5249
5135
  const IP_PLAIN_RE = /\b([0-9]{1,3}\.[0-9]{1,3})\b/;
5250
5136
 
@@ -5413,10 +5299,6 @@
5413
5299
 
5414
5300
  const matchBlockedKeyword = el => (blockedKeywords.length ? findWord(blockedKeywords, getKeywordText(el)) : '');
5415
5301
 
5416
- // =========================================================
5417
- // 7. 말머리
5418
- // =========================================================
5419
-
5420
5302
  const GALL_TAG_RE = /^\[[^[\]]{1,10}\]$/;
5421
5303
 
5422
5304
  const isHomePage = () =>
@@ -5706,10 +5588,6 @@
5706
5588
  refreshAfterBlockChange();
5707
5589
  };
5708
5590
 
5709
- // =========================================================
5710
- // 8. 미디어 UI
5711
- // =========================================================
5712
-
5713
5591
  const mediaTools = new WeakMap();
5714
5592
  const mediaHosts = new WeakMap();
5715
5593
  const mediaSignature = new WeakMap();
@@ -6151,10 +6029,6 @@
6151
6029
  refreshMedia();
6152
6030
  };
6153
6031
 
6154
- // =========================================================
6155
- // 9. 닉네임 팝오버 · 알림
6156
- // =========================================================
6157
-
6158
6032
  let toastTimer = null;
6159
6033
  const toastListeners = [];
6160
6034
 
@@ -6678,9 +6552,6 @@
6678
6552
  }
6679
6553
  }, { passive: true });
6680
6554
  };
6681
- // =========================================================
6682
- // 10. 항목 처리
6683
- // =========================================================
6684
6555
 
6685
6556
  const SCRIPT_LI_SELECTOR = '.dc-collapsed-stub, .dc-stream-page-sep';
6686
6557
 
@@ -7526,10 +7397,6 @@
7526
7397
  processElements();
7527
7398
  };
7528
7399
 
7529
- // =========================================================
7530
- // 11. 차단 기록
7531
- // =========================================================
7532
-
7533
7400
  const DAY_MS = 24 * 60 * 60 * 1000;
7534
7401
 
7535
7402
  let blockedPostLog = readArray(STORAGE.postLog).filter(entry => entry && typeof entry.key === 'string' && entry.key);
@@ -7651,10 +7518,6 @@
7651
7518
 
7652
7519
  const clearBlockedPostLog = () => setBlockedPostLog([], { immediate: true });
7653
7520
 
7654
- // =========================================================
7655
- // 11-1. 본문 미리 검사
7656
- // =========================================================
7657
-
7658
7521
  const BODY_SCAN_LIMIT = 1500;
7659
7522
  const POST_TITLE_SELECTOR = '.gallview-tit-box .tit, .gallview_head .title_subject';
7660
7523
  const BODY_SCAN_CONCURRENCY = 1;
@@ -7903,10 +7766,6 @@
7903
7766
  writeJson(STORAGE.bodyScan, bodyScanCache);
7904
7767
  };
7905
7768
 
7906
- // =========================================================
7907
- // 12. 목록 스트림
7908
- // =========================================================
7909
-
7910
7769
  const STREAM_PREFETCH_GAP = 1400;
7911
7770
  const STREAM_PULL_RATIO = 0.28;
7912
7771
  const STREAM_PULL_MIN = 150;
@@ -9576,9 +9435,6 @@
9576
9435
  }
9577
9436
  });
9578
9437
  };
9579
- // =========================================================
9580
- // 13. 모달
9581
- // =========================================================
9582
9438
 
9583
9439
  const h = (tag, className, text) => {
9584
9440
  const el = document.createElement(tag);
@@ -10052,6 +9908,17 @@
10052
9908
  area.querySelectorAll('.dc-row').forEach(row => {
10053
9909
  row.hidden = !matchesFilter(row.textContent);
10054
9910
  });
9911
+
9912
+ area.querySelectorAll('.dc-setting-row').forEach(row => {
9913
+ row.hidden = !matchesFilter(row.textContent);
9914
+ });
9915
+ area.querySelectorAll('.dc-settings-group[data-dc-group]').forEach(box => {
9916
+ const empty = !!blockFilter.trim() && ![...box.querySelectorAll('.dc-setting-row')].some(row => !row.hidden);
9917
+
9918
+ area.querySelectorAll(`[data-dc-group="${box.dataset.dcGroup}"]`).forEach(el => {
9919
+ el.hidden = empty;
9920
+ });
9921
+ });
10055
9922
  };
10056
9923
 
10057
9924
  const matchesFilter = text => !blockFilter || String(text).toLowerCase().includes(blockFilter.trim().toLowerCase());
@@ -10400,6 +10267,7 @@
10400
10267
  { key: 'alarm', title: '🔔 알림', intro: '디시 알림(댓글·답글·힛갤 등)을 보기 쉽게 바꿉니다. 알림 내용은 사이트가 받은 것을 그대로 씁니다.' },
10401
10268
  { key: 'dccon', title: '😶 디시콘', intro: '디시 자체 이모티콘을 다룹니다.' },
10402
10269
  { key: 'list', title: '📜 목록 보기', intro: '게시판 목록을 넘겨 보는 방식을 정합니다.' },
10270
+ { key: 'handy', title: '✨ 편의 기능', intro: '최근 방문 · 글 미리보기 · 단축키 · 스크랩처럼 사이트를 더 편하게 쓰는 기능입니다.' },
10403
10271
  { key: 'media', title: '🖼 이미지·영상', intro: '본문 이미지 차단과 확대 보기를 다룹니다.' },
10404
10272
  { key: 'data', title: '📶 데이터 절약', intro: '모바일 데이터를 아끼는 기능입니다.' },
10405
10273
  { key: 'theme', title: '🌓 화면 테마', intro: '주간/야간 모드를 기기 설정에 맞춥니다.' },
@@ -10546,21 +10414,13 @@
10546
10414
  refresh: 'root'
10547
10415
  },
10548
10416
  {
10549
- group: 'clean',
10417
+ group: 'handy',
10550
10418
  key: 'mobileRecentBar',
10551
10419
  name: '메뉴 위에 최근 방문 갤러리 늘 보이기 (모바일)',
10552
10420
  on: '검색창과 [갤러리 · 마이너갤 · …] 메뉴 사이에 최근 방문 갤러리를 한 줄로 보여 줍니다. 옆으로 밀어 보고, 누르면 바로 이동합니다. 지금 갤러리는 노란색입니다.',
10553
10421
  off: '[최근 방문]을 눌러야 보입니다.',
10554
10422
  refresh: 'root'
10555
10423
  },
10556
- {
10557
- group: 'clean',
10558
- key: 'mobileRecentStrip',
10559
- name: "'최근 방문'을 한 줄로 밀어 보기 (모바일)",
10560
- on: '위쪽 [최근 방문]을 누르면 넓은 표 대신 갤러리가 순서대로 한 줄에 나오고, 옆으로 밀어 봅니다. 고정한 순서를 그대로 따릅니다.',
10561
- off: '사이트 기본 표(2줄 × 4칸, 넘겨 보기)로 보여 줍니다.',
10562
- refresh: 'root'
10563
- },
10564
10424
  {
10565
10425
  group: 'clean',
10566
10426
  key: 'hideAdSlots',
@@ -10636,7 +10496,7 @@
10636
10496
  refresh: 'all'
10637
10497
  },
10638
10498
  {
10639
- group: 'list',
10499
+ group: 'handy',
10640
10500
  key: 'keyboardShortcuts',
10641
10501
  name: '키보드 단축키 (PC)',
10642
10502
  on: '목록에서 J/K 로 글을 고르고 Enter 로 엽니다. 글에서는 J/K 로 다음·이전 글, S 스크랩, / 검색창, B 차단 관리, ? 안내.',
@@ -10644,7 +10504,7 @@
10644
10504
  refresh: 'none'
10645
10505
  },
10646
10506
  {
10647
- group: 'list',
10507
+ group: 'handy',
10648
10508
  key: 'hoverPreview',
10649
10509
  name: '제목을 길게 누르면 글 미리보기 (PC)',
10650
10510
  on: '아이폰처럼 목록 제목을 길게 누르면 화면이 흐려지며 글 전체가 가운데에 떠오릅니다. 짧게 누르면 평소처럼 글로 갑니다. 창에서 본문을 누르면 글로 이동, 바깥을 누르거나 Esc 로 닫습니다. 스크랩·작성자 차단도 바로 할 수 있고, 차단한 이미지·단어는 미리보기에서도 가립니다. 키보드로 고른 글은 P 로 엽니다.',
@@ -10652,7 +10512,7 @@
10652
10512
  refresh: 'root'
10653
10513
  },
10654
10514
  {
10655
- group: 'list',
10515
+ group: 'handy',
10656
10516
  key: 'previewHover',
10657
10517
  parent: 'hoverPreview',
10658
10518
  name: '마우스를 올려 멈춰도 미리보기 (PC)',
@@ -10697,7 +10557,7 @@
10697
10557
  refresh: 'root'
10698
10558
  },
10699
10559
  {
10700
- group: 'list',
10560
+ group: 'handy',
10701
10561
  key: 'autoHideScrollbar',
10702
10562
  name: '스크롤바 자동 숨기기',
10703
10563
  on: '화면 스크롤바를 숨기고, 스크롤하는 동안만 얇은 표시가 잠깐 나타납니다 (스크롤바가 자리를 차지하는 PC).',
@@ -10705,7 +10565,7 @@
10705
10565
  refresh: 'root'
10706
10566
  },
10707
10567
  {
10708
- group: 'list',
10568
+ group: 'handy',
10709
10569
  key: 'scrapIntercept',
10710
10570
  name: '무제한 스크랩',
10711
10571
  on: '글의 스크랩 버튼을 누르면 개수 제한 없이 이 기기에 저장합니다. 플로팅 메뉴의 📌 스크랩 탭에서 봅니다.',
@@ -10713,7 +10573,7 @@
10713
10573
  refresh: 'none'
10714
10574
  },
10715
10575
  {
10716
- group: 'list',
10576
+ group: 'handy',
10717
10577
  key: 'showScrollTop',
10718
10578
  name: '맨 위로 버튼',
10719
10579
  on: '목록을 많이 내려가면 플로팅 버튼 위에 ↑ 버튼이 나타납니다.',
@@ -10857,10 +10717,6 @@
10857
10717
  renderRecentBar();
10858
10718
  }
10859
10719
 
10860
- if (item.key === 'mobileRecentStrip') {
10861
- renderRecentStrip();
10862
- }
10863
-
10864
10720
  if (item.key === 'alarmBubble') {
10865
10721
  paintAlarmBadge();
10866
10722
  }
@@ -11241,7 +11097,7 @@
11241
11097
  const seg = h('div', 'dc-choice-seg');
11242
11098
 
11243
11099
  head.append(
11244
- h('span', 'dc-setting-name', item.name),
11100
+ h('span', 'dc-setting-name', settingLabel(item)),
11245
11101
  h('span', 'dc-state-badge on', chosen ? chosen.label : String(current))
11246
11102
  );
11247
11103
  text.append(head, h('span', 'dc-setting-desc', item.on));
@@ -11277,17 +11133,43 @@
11277
11133
  return row;
11278
11134
  };
11279
11135
 
11136
+ const settingPlatform = item => (/\(PC\)$/.test(item.name) ? 'pc' : /\(모바일\)$/.test(item.name) ? 'mobile' : 'all');
11137
+ const settingShownHere = item => {
11138
+ const platform = settingPlatform(item);
11139
+
11140
+ return platform === 'all' || (platform === 'pc') === IS_PC_SITE;
11141
+ };
11142
+ const settingLabel = item => item.name.replace(/\s*\((PC|모바일)\)$/, '');
11143
+
11280
11144
  const renderSettings = area => {
11281
11145
  area.appendChild(
11282
- makeNote('스위치가 초록색이면 켜짐입니다. 바꾸면 바로 적용되고 자동으로 저장됩니다.')
11146
+ makeNote(`스위치가 초록색이면 켜짐입니다. 바꾸면 바로 적용되고 자동으로 저장됩니다. ${IS_PC_SITE ? 'PC' : '모바일'}에서 쓰는 설정만 보입니다.`)
11283
11147
  );
11284
11148
 
11149
+ const search = makeFilterRow(99);
11150
+
11151
+ if (search) {
11152
+ search.querySelector('input').placeholder = '🔍 설정에서 찾기';
11153
+ area.appendChild(search);
11154
+ }
11155
+
11285
11156
  SETTING_GROUPS.forEach(group => {
11157
+ const items = SETTING_ITEMS.filter(item => item.group === group.key && settingShownHere(item));
11158
+
11159
+ if (!items.length) {
11160
+ return;
11161
+ }
11162
+
11286
11163
  const box = h('div', 'dc-settings-group');
11164
+ const title = h('div', 'dc-group-title', group.title);
11165
+ const intro = h('div', 'dc-group-intro', group.intro);
11287
11166
 
11288
- area.append(h('div', 'dc-group-title', group.title), h('div', 'dc-group-intro', group.intro), box);
11167
+ title.dataset.dcGroup = group.key;
11168
+ intro.dataset.dcGroup = group.key;
11169
+ box.dataset.dcGroup = group.key;
11170
+ area.append(title, intro, box);
11289
11171
 
11290
- SETTING_ITEMS.filter(item => item.group === group.key).forEach(item => {
11172
+ items.forEach(item => {
11291
11173
  if (item.choices) {
11292
11174
  box.appendChild(renderChoiceSetting(item));
11293
11175
  return;
@@ -11302,7 +11184,7 @@
11302
11184
  const toggle = h('button', `dc-switch${on ? ' on' : ''}`);
11303
11185
 
11304
11186
  head.append(
11305
- h('span', 'dc-setting-name', item.name),
11187
+ h('span', 'dc-setting-name', settingLabel(item)),
11306
11188
  h('span', `dc-state-badge${on ? ' on' : ''}`, on ? '켜짐' : '꺼짐')
11307
11189
  );
11308
11190
  text.append(head, h('span', 'dc-setting-desc', on || !item.off ? item.on : item.off));
@@ -11312,7 +11194,7 @@
11312
11194
  }
11313
11195
 
11314
11196
  const status = !effective
11315
- ? `위의 '${parent.name}' 설정을 먼저 켜 주세요.`
11197
+ ? `위의 '${settingLabel(parent)}' 설정을 먼저 켜 주세요.`
11316
11198
  : item.status
11317
11199
  ? item.status(on)
11318
11200
  : null;
@@ -11324,7 +11206,7 @@
11324
11206
  toggle.type = 'button';
11325
11207
  toggle.disabled = !effective;
11326
11208
  toggle.setAttribute('role', 'switch');
11327
- toggle.setAttribute('aria-label', item.name);
11209
+ toggle.setAttribute('aria-label', settingLabel(item));
11328
11210
  toggle.setAttribute('aria-checked', String(on));
11329
11211
 
11330
11212
  toggle.addEventListener('click', () => {
@@ -11502,10 +11384,6 @@
11502
11384
  scrollLocked = false;
11503
11385
  };
11504
11386
 
11505
- // =========================================================
11506
-
11507
- // =========================================================
11508
-
11509
11387
  const SCRAP_LIMIT = 20000;
11510
11388
  const SCRAP_KINDS = ['G', 'M', 'N', 'P'];
11511
11389
 
@@ -11780,7 +11658,13 @@
11780
11658
  };
11781
11659
 
11782
11660
  const setModalView = view => {
11783
- currentView = MODAL_VIEWS[view] ? view : 'overview';
11661
+ const next = MODAL_VIEWS[view] ? view : 'overview';
11662
+
11663
+ if (next !== currentView) {
11664
+ blockFilter = '';
11665
+ }
11666
+
11667
+ currentView = next;
11784
11668
 
11785
11669
  document.getElementById('dc-modal-title').textContent = MODAL_VIEWS[currentView].title;
11786
11670
  document.querySelectorAll('[data-dc-view]').forEach(btn => {
@@ -11906,10 +11790,6 @@
11906
11790
  }
11907
11791
  });
11908
11792
 
11909
- // =========================================================
11910
- // 13-1. 기기 간 동기화
11911
- // =========================================================
11912
-
11913
11793
  const SYNC_SETTINGS_SKIP = ['settingsRev'];
11914
11794
  const SYNC_DEBOUNCE = 2500;
11915
11795
  const SYNC_MIN_GAP = 20000;
@@ -13491,10 +13371,6 @@
13491
13371
  }
13492
13372
  };
13493
13373
 
13494
- // =========================================================
13495
- // 13-2. 정보 · 업데이트 알림 · 후원
13496
- // =========================================================
13497
-
13498
13374
  const noteScriptVersion = () => {
13499
13375
  let seen = '';
13500
13376
 
@@ -13548,16 +13424,12 @@
13548
13424
  return a;
13549
13425
  };
13550
13426
 
13551
- links.append(link('☕ 후원하기', DONATE_URL, ''), link('변경 내역 · 문의', PROJECT_URL, 'neutral'));
13427
+ links.append(link('💖 Fairy 후원', DONATE_URL, ''), link('☕ Buy Me a Coffee', DONATE_URL_BMC, ''), link('변경 내역 · 문의', PROJECT_URL, 'neutral'));
13552
13428
  box.appendChild(links);
13553
13429
 
13554
13430
  return box;
13555
13431
  };
13556
13432
 
13557
- // =========================================================
13558
- // 13-3. 최근 방문 갤러리 · 사이트 알림
13559
- // =========================================================
13560
-
13561
13433
  const RECENT_LIMIT = 50;
13562
13434
  const RECENT_NATIVE_CAP = IS_MOBILE_SITE ? 24 : 50;
13563
13435
  const RECENT_KINDS = ['G', 'M', 'N', 'P'];
@@ -13994,82 +13866,6 @@
13994
13866
  }
13995
13867
  }
13996
13868
 
13997
- const renderRecentStrip = () => {
13998
- const pop = document.getElementById('lately_pop');
13999
-
14000
- if (!IS_MOBILE_SITE || !pop || settings.mobileRecentStrip === false) {
14001
- document.documentElement.classList.remove('dc-recent-strip-on');
14002
- pop?.querySelector('.dc-recent-strip')?.remove();
14003
- return;
14004
- }
14005
-
14006
- const latelyTab = document.getElementById('lately_gall');
14007
- const showing = !latelyTab || latelyTab.classList.contains('on');
14008
- let strip = pop.querySelector('.dc-recent-strip');
14009
-
14010
- if (!strip) {
14011
- strip = h('div', 'dc-ui dc-recent-strip');
14012
- strip.setAttribute('role', 'list');
14013
- const slider = pop.querySelector('#swiper-lately') || pop.querySelector('.vst-slider');
14014
-
14015
- (slider ? slider.parentNode : pop).insertBefore(strip, slider || null);
14016
- }
14017
-
14018
- document.documentElement.classList.add('dc-recent-strip-on');
14019
- strip.hidden = !showing;
14020
- pop.classList.toggle('dc-strip-lately', showing);
14021
-
14022
- if (!showing) {
14023
- return;
14024
- }
14025
-
14026
- const keepScroll = strip.scrollLeft;
14027
-
14028
- strip.textContent = '';
14029
-
14030
- if (!recentGalls.length) {
14031
- strip.appendChild(h('span', 'dc-rs-empty', '최근 방문한 갤러리가 없습니다'));
14032
- return;
14033
- }
14034
-
14035
- const here = (currentGalleryVisit() || {}).id;
14036
-
14037
- recentGalls.forEach(item => {
14038
- const chip = h('a', `dc-rs-chip${item.id === here ? ' here' : ''}`);
14039
-
14040
- chip.href = recentUrl(item);
14041
- chip.setAttribute('role', 'listitem');
14042
- chip.appendChild(h('span', 'dc-rs-name', item.n || item.id));
14043
-
14044
- if (RECENT_KIND_LABEL[item.k]) {
14045
- chip.appendChild(h('span', 'dc-rs-kind', item.k === 'M' ? 'ⓜ' : item.k === 'N' ? 'ⓝ' : 'ⓟ'));
14046
- }
14047
-
14048
- const del = h('button', 'dc-rs-del', '×');
14049
-
14050
- del.type = 'button';
14051
- del.setAttribute('aria-label', `${item.n || item.id} 지우기`);
14052
- del.addEventListener('click', event => {
14053
- event.preventDefault();
14054
- event.stopPropagation();
14055
- recentGalls = recentGalls.filter(other => other !== item);
14056
- saveRecent();
14057
- exportNativeRecent();
14058
- renderRecentStrip();
14059
- });
14060
- chip.appendChild(del);
14061
- strip.appendChild(chip);
14062
- });
14063
-
14064
- if (recentOrder.fixed) {
14065
- strip.appendChild(h('span', 'dc-rs-pin', '📌 순서 고정'));
14066
- }
14067
-
14068
- strip.scrollLeft = keepScroll;
14069
-
14070
- strip.querySelector('.dc-rs-chip.here')?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });
14071
- };
14072
-
14073
13869
  const renderRecentBar = () => {
14074
13870
  const nav = IS_MOBILE_SITE ? document.querySelector('nav.nav') : null;
14075
13871
  let bar = document.getElementById('dc-recent-bar');
@@ -14089,9 +13885,21 @@
14089
13885
  try {
14090
13886
  const cs = getComputedStyle(nav);
14091
13887
  const active = nav.querySelector('li.on a') || nav.querySelector('a');
14092
-
14093
- bar.style.setProperty('--dc-rb-bg', cs.backgroundColor);
14094
- bar.style.setProperty('--dc-rb-on', active ? getComputedStyle(active).color : '#ffe10a');
13888
+ const plain = nav.querySelector('li:not(.on) a') || active;
13889
+ const items = [...nav.querySelectorAll('li')].filter(li => li.getBoundingClientRect().width);
13890
+ const gap = items.length > 1 ? Math.round(items[1].getBoundingClientRect().left - items[0].getBoundingClientRect().right) : 30;
13891
+ const ps = plain ? getComputedStyle(plain) : null;
13892
+ const set = (name, value) => value && bar.style.setProperty(name, value);
13893
+
13894
+ set('--dc-rb-bg', cs.backgroundColor);
13895
+ set('--dc-rb-on', active ? getComputedStyle(active).color : '');
13896
+ set('--dc-rb-color', ps ? ps.color : '');
13897
+ set('--dc-rb-size', ps ? ps.fontSize : '');
13898
+ set('--dc-rb-weight', ps ? ps.fontWeight : '');
13899
+ set('--dc-rb-family', ps ? ps.fontFamily : '');
13900
+ set('--dc-rb-spacing', ps ? ps.letterSpacing : '');
13901
+ set('--dc-rb-gap', `${Math.max(16, Math.min(40, gap))}px`);
13902
+ set('--dc-rb-pad', items[0] ? `${Math.round(items[0].getBoundingClientRect().left - nav.getBoundingClientRect().left)}px` : '');
14095
13903
  } catch {
14096
13904
  }
14097
13905
 
@@ -14126,41 +13934,11 @@
14126
13934
  }
14127
13935
  };
14128
13936
 
14129
- const watchRecentStrip = () => {
14130
- const pop = document.getElementById('lately_pop');
14131
-
14132
- if (!IS_MOBILE_SITE || !pop) {
14133
- return;
14134
- }
14135
-
14136
- let timer = null;
14137
- const refresh = () => {
14138
- clearTimeout(timer);
14139
- timer = setTimeout(() => {
14140
- if (pop.style.display !== 'none') {
14141
- importNativeRecent();
14142
- renderRecentStrip();
14143
- }
14144
- }, 30);
14145
- };
14146
-
14147
- new MutationObserver(refresh).observe(pop, { attributes: true, attributeFilter: ['style'] });
14148
-
14149
- const tabs = pop.querySelector('.tab-lst');
14150
-
14151
- if (tabs) {
14152
- new MutationObserver(refresh).observe(tabs, { attributes: true, subtree: true, attributeFilter: ['class'] });
14153
- }
14154
-
14155
- renderRecentStrip();
14156
- };
14157
-
14158
13937
  const initRecent = () => {
14159
13938
  importNativeRecent();
14160
13939
  recordGalleryVisit();
14161
13940
  exportNativeRecent();
14162
13941
  watchNativeRecentDom();
14163
- watchRecentStrip();
14164
13942
  renderRecentBar();
14165
13943
 
14166
13944
  const follow = () => {
@@ -14246,10 +14024,6 @@
14246
14024
  return true;
14247
14025
  };
14248
14026
 
14249
- // =========================================================
14250
-
14251
- // =========================================================
14252
-
14253
14027
  const ALARM_TAGS = { R: '댓글', RR: '답글', P: '펌', hit: '힛갤', B: '실베', EC: '동영상', G: '방명록' };
14254
14028
  const ALARM_POLL_GAP = 3 * 60 * 1000;
14255
14029
  const ALARM_BUBBLE_MAX = 3;
@@ -14730,10 +14504,6 @@
14730
14504
  window.addEventListener('resize', placeBubbleBox, { passive: true });
14731
14505
  };
14732
14506
 
14733
- // =========================================================
14734
-
14735
- // =========================================================
14736
-
14737
14507
  const renderRecentView = area => {
14738
14508
  const alarms = siteUserId() || alarmStorageKeys().length ? readSiteAlarms() : null;
14739
14509
 
@@ -14861,10 +14631,6 @@
14861
14631
 
14862
14632
  initRecentEarly();
14863
14633
 
14864
- // =========================================================
14865
-
14866
- // =========================================================
14867
-
14868
14634
  const KEY_HELP = 'J/K 다음·이전 글 · Enter 열기 · P 미리보기 · S 스크랩 · / 검색 · B 차단 관리';
14869
14635
 
14870
14636
  const typingTarget = el =>
@@ -14983,10 +14749,6 @@
14983
14749
  });
14984
14750
  };
14985
14751
 
14986
- // =========================================================
14987
-
14988
- // =========================================================
14989
-
14990
14752
  const SEARCH_HISTORY_MAX = 30;
14991
14753
 
14992
14754
  const readSiteSearchHistory = () => {
@@ -15041,10 +14803,6 @@
15041
14803
  return true;
15042
14804
  };
15043
14805
 
15044
- // =========================================================
15045
- // 13-4. 차단 목록 정리 도우미 · 기기 알림 · PC 글 미리보기
15046
- // =========================================================
15047
-
15048
14806
  const collectHitsForSync = () => {
15049
14807
  flushBlockHits();
15050
14808
 
@@ -15083,10 +14841,6 @@
15083
14841
  return true;
15084
14842
  };
15085
14843
 
15086
- // =========================================================
15087
-
15088
- // =========================================================
15089
-
15090
14844
  const CLEANUP_IDLE_DAYS = 7;
15091
14845
 
15092
14846
  const cleanupSuggestions = () => {
@@ -15222,10 +14976,6 @@
15222
14976
  }));
15223
14977
  };
15224
14978
 
15225
- // =========================================================
15226
-
15227
- // =========================================================
15228
-
15229
14979
  const systemNotifySupported = () => typeof window.Notification === 'function';
15230
14980
 
15231
14981
  const canSystemNotify = () =>
@@ -15282,10 +15032,6 @@
15282
15032
  return true;
15283
15033
  };
15284
15034
 
15285
- // =========================================================
15286
-
15287
- // =========================================================
15288
-
15289
15035
  const PREVIEW_DELAY = 650;
15290
15036
  const PREVIEW_SWITCH_DELAY = 320;
15291
15037
  const PREVIEW_CLOSE_DELAY = 380;
@@ -16038,9 +15784,6 @@
16038
15784
  openPreview(anchor, 'peek');
16039
15785
  return true;
16040
15786
  };
16041
- // =========================================================
16042
- // 14. 플로팅 버튼
16043
- // =========================================================
16044
15787
 
16045
15788
  const FAB_DRAG_THRESHOLD = 8;
16046
15789
  const FAB_EDGE_MARGIN = 6;
@@ -16363,10 +16106,6 @@
16363
16106
  updateScrollTopButton();
16364
16107
  };
16365
16108
 
16366
- // =========================================================
16367
- // 15. 이미지 확대뷰
16368
- // =========================================================
16369
-
16370
16109
  const isPopupVisible = el =>
16371
16110
  el.isConnected && el.style.display !== 'none' && window.getComputedStyle(el).display !== 'none';
16372
16111
 
@@ -16709,10 +16448,6 @@
16709
16448
  });
16710
16449
  };
16711
16450
 
16712
- // =========================================================
16713
- // 16. 초기화
16714
- // =========================================================
16715
-
16716
16451
  let processTimer = null;
16717
16452
 
16718
16453
  const scheduleProcess = () => {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@kangsicj/dcinsideenhancer",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
4
4
  "description": "DCInside filter & enhancer userscript for mobile and PC (디시인사이드 차단·편의 유저스크립트)",
5
- "license": "MIT",
5
+ "license": "GPL-3.0-only",
6
6
  "author": "kangsicj",
7
7
  "homepage": "https://github.com/kangsicj/DCInsideEnhancer#readme",
8
8
  "repository": {