├── .gitignore
├── README.md
├── images
└── icon.png
├── jsconfig.json
├── promos
├── screenshots
│ ├── main.png
│ ├── organize.png
│ └── sync.png
└── tiles
│ ├── large-tile.png
│ ├── promo-440.svg
│ ├── promo-920.svg
│ └── small-tile.png
├── src
├── _locales
│ ├── de
│ │ └── messages.json
│ ├── en
│ │ └── messages.json
│ └── pl
│ │ └── messages.json
├── analytics.js
├── background.js
├── constants.js
├── contentscript.js
├── css
│ ├── material-icons.css
│ ├── materialize.min.css
│ ├── options.css
│ ├── popup.css
│ └── translators.css
├── fonts
│ ├── Material-Icons.woff2
│ └── roboto
│ │ ├── Roboto-Bold.eot
│ │ ├── Roboto-Bold.ttf
│ │ ├── Roboto-Bold.woff
│ │ ├── Roboto-Bold.woff2
│ │ ├── Roboto-Light.eot
│ │ ├── Roboto-Light.ttf
│ │ ├── Roboto-Light.woff
│ │ ├── Roboto-Light.woff2
│ │ ├── Roboto-Medium.eot
│ │ ├── Roboto-Medium.ttf
│ │ ├── Roboto-Medium.woff
│ │ ├── Roboto-Medium.woff2
│ │ ├── Roboto-Regular.eot
│ │ ├── Roboto-Regular.ttf
│ │ ├── Roboto-Regular.woff
│ │ ├── Roboto-Regular.woff2
│ │ ├── Roboto-Thin.eot
│ │ ├── Roboto-Thin.ttf
│ │ ├── Roboto-Thin.woff
│ │ └── Roboto-Thin.woff2
├── img
│ ├── icon-128.png
│ ├── icon-16.png
│ ├── icon-19.png
│ ├── icon-38.png
│ ├── icon.svg
│ └── icons
│ │ ├── ic_folder_1x.png
│ │ ├── ic_folder_2x.png
│ │ ├── ic_help_1x.png
│ │ ├── ic_help_2x.png
│ │ ├── ic_navigate_before_1x.png
│ │ └── ic_navigate_before_2x.png
├── jquery-ui
│ ├── AUTHORS.txt
│ ├── LICENSE.txt
│ ├── external
│ │ └── jquery
│ │ │ └── jquery.js
│ ├── images
│ │ ├── ui-icons_444444_256x240.png
│ │ ├── ui-icons_555555_256x240.png
│ │ ├── ui-icons_777620_256x240.png
│ │ ├── ui-icons_777777_256x240.png
│ │ ├── ui-icons_cc0000_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ ├── index.html
│ ├── jquery-ui.css
│ ├── jquery-ui.js
│ ├── jquery-ui.min.css
│ ├── jquery-ui.min.js
│ ├── jquery-ui.structure.css
│ ├── jquery-ui.structure.min.css
│ ├── jquery-ui.theme.css
│ ├── jquery-ui.theme.min.css
│ └── package.json
├── js
│ ├── analytics.js
│ ├── i18n.js
│ ├── materialize.min.js
│ └── translators.js
├── manifest.json
├── options.html
├── options.js
├── permissions.html
├── permissions.js
├── popup.html
├── popup.js
├── storage.js
└── translators.html
└── tests
└── storage.test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | node_modules
4 | tests/localStorage
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 | # Permanent Clipboard
4 |
5 | Permanent Clipboard is Google Chrome™ browser extension that improves the clipboard by allowing users to store multiple entries just a click away.
6 |
7 | Do you want quick access your response templates? Or maybe you often fill forms that aren't standard and the browser doesn't support it? Then Permanent Clipboard is the extension for you.
8 |
9 | ### Main features
10 |
11 | ##### Directories
12 |
13 | For convenience, entries can be categorized in directories for logical structure, so you won't mix business with pleasure.
14 | Directories can also be nested so the structure you create can reflect any complicated work flow you face each day.
15 |
16 | ##### Cross computers synchronization
17 |
18 | Permanent Clipboard can synchronize between your Google Chrome™ instances, as long as you are logged in into your Google Account.
19 | But this feature is not obligatory, and you can easy opt out from it if you store confidential information in your clipboard.
20 |
21 | ##### Backups
22 |
23 | When you are not using synchronized storage it is important not to lose your work, this is why Permanent Clipboard lets you create a backup of all your entries and restore then at any point, so you are safe from any data loss.
24 |
25 | ### Help
26 |
27 | Permanent Clipboard is free and open source software and I would like to keep it that way. So if you enjoy the
28 | extension I would appreciate if you help me reach wider audience by rating the extension on [Chrome Web Store](https://chrome.google.com/webstore/detail/permanent-clipboard/hilkjcfodmbdgpadbpehimibheopoccb) or telling your friends about it.
29 |
30 | You can also support the growth of Permanent Clipboard by donating via PayPal. Donations allows me to spend more time developing the extension, fixing bugs, adding features and improving the extension overall.
31 |
32 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=X4LEC9EWL4V24)
33 |
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/images/icon.png
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonJS",
4 | "target": "es2019"
5 | },
6 | "typeAcquisition": {"include": ["chrome"]},
7 | "exclude": [
8 | "node_modules"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/promos/screenshots/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/promos/screenshots/main.png
--------------------------------------------------------------------------------
/promos/screenshots/organize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/promos/screenshots/organize.png
--------------------------------------------------------------------------------
/promos/screenshots/sync.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/promos/screenshots/sync.png
--------------------------------------------------------------------------------
/promos/tiles/large-tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/promos/tiles/large-tile.png
--------------------------------------------------------------------------------
/promos/tiles/promo-440.svg:
--------------------------------------------------------------------------------
1 |
2 |
261 |
--------------------------------------------------------------------------------
/promos/tiles/promo-920.svg:
--------------------------------------------------------------------------------
1 |
2 |
224 |
--------------------------------------------------------------------------------
/promos/tiles/small-tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/promos/tiles/small-tile.png
--------------------------------------------------------------------------------
/src/_locales/de/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "optionsSave" : {
3 | "message" : "Speichern"
4 | },
5 | "optionSwapText" : {
6 | "message" : "Plätze wechseln"
7 | },
8 | "optionsSavedToastText" : {
9 | "message" : "Einstellungen wurden gespeichert"
10 | },
11 | "insertFromExtension" : {
12 | "message" : "Aus Permanent Clipboard einfügen"
13 | },
14 | "optionsStorageSizeHelp" : {
15 | "message" : "Speicherplatz synchronisierter Permanent Clipboard ist von Google begrenzt und kann nicht vergrößert werden. Wenn der Speicherplatz voll wird, empfiehlt man, synchronisierte Permanent Clipboard zu nutzen. Denk jedoch daran, den Inhalt zu übertragen."
16 | },
17 | "optionsText" : {
18 | "message" : "Einstellungen"
19 | },
20 | "showAddFormText" : {
21 | "message" : "Neuen Eintrag anlegen"
22 | },
23 | "addBtnText" : {
24 | "message" : "Hinzufügen"
25 | },
26 | "popupHintText_2" : {
27 | "message" : "Gefällt dir Permanent Clipboard? Bewerte sie!<\/a>"
28 | },
29 | "extensionDescription" : {
30 | "message" : "Es lässt die Elemente in der Zwischenablage aufbewahren und macht sie zugänglich."
31 | },
32 | "popupBack" : {
33 | "message" : "Zurück"
34 | },
35 | "optionsSwapStoragesHelp" : {
36 | "message" : "Speicherplatz synchronisierter Zwischenablage ist von Google begrenzt und kann nicht vergrößert werden. Wenn der Speicherplatz voll wird, empfiehlt man, synchronisierte Zwischenablage zu nutzen. Denk jedoch daran, den Inhalt zu übertragen."
37 | },
38 | "optionStorageCardTitle" : {
39 | "message" : "Speicher"
40 | },
41 | "commonCancel" : {
42 | "message" : "Abbrechen"
43 | },
44 | "localStorageUsed" : {
45 | "message" : "Lokaler Speicher wird genutzt"
46 | },
47 | "popupNewElement" : {
48 | "message" : "Aus Systemzwischenablage einfügen"
49 | },
50 | "deleteEntryIconTitle" : {
51 | "message" : "Löschen"
52 | },
53 | "storageSwappingFailedMessage" : {
54 | "message" : "Der Inhalt wurde nicht geändert: "
55 | },
56 | "donateWithPaypal" : {
57 | "message" : "Via PayPal dotieren"
58 | },
59 | "addToExtensionDB" : {
60 | "message" : "In die Permanent Clipboard einfügen"
61 | },
62 | "optionsSuccess" : {
63 | "message" : "Geändert"
64 | },
65 | "popupHintText_1" : {
66 | "message" : "Klicke auf den Link in Optionen um Permanent Clipboard zu dotieren"
67 | },
68 | "optionStorageUsage" : {
69 | "message" : "Synchronisierter Speicherplatzverbrauch "
70 | },
71 | "editEntryIconTitle" : {
72 | "message" : "Bearbeiten"
73 | },
74 | "optionSwapStorageText" : {
75 | "message" : "Inhalt übertragen"
76 | },
77 | "optionLocalText" : {
78 | "message" : "Lokal"
79 | },
80 | "optionSyncTip" : {
81 | "message" : "Lokalspeicher ist nur auf diesem Rechner sichtbar. Synchronisierter Speicher ist im Google Chrome Browser sichtbar, wenn man angemeldet ist (es kann langsamer als Lokalspeicher funktionieren)"
82 | },
83 | "descriptionPlaceholder" : {
84 | "message" : "Beschreibung"
85 | },
86 | "popupHintNoElements" : {
87 | "message" : "Keine Einträge"
88 | },
89 | "translatorsTitle" : {
90 | "message" : "Übersetzung"
91 | },
92 | "extensionName" : {
93 | "message" : "Permanent Clipboard"
94 | },
95 | "newDirectoryName" : {
96 | "message" : "Neuer Katalog"
97 | },
98 | "contentPlaceholder" : {
99 | "message" : "Inhalt"
100 | },
101 | "optionSyncText" : {
102 | "message" : "Synchronisiert"
103 | },
104 | "optionStorageTypeText" : {
105 | "message" : "Speicherart"
106 | },
107 | "popupHintTitle" : {
108 | "message" : "Weißt du, dass…?"
109 | },
110 | "popupHint" : {
111 | "message" : "Klicke auf den Eintrag, um ihn in synchronisierte Zwischenablage zu kopieren"
112 | },
113 | "popupHintsCount" : {
114 | "message" : "2"
115 | },
116 | "errorFailedToSaveEntry" : {
117 | "message" : "Der Eintrag wurde nicht angelegt:"
118 | },
119 | "syncedStorageUsed" : {
120 | "message" : "Synchronisierter Speicher wird genutzt"
121 | }
122 | }
--------------------------------------------------------------------------------
/src/_locales/en/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "popup_unsavedChanges" : {
3 | "message" : "Unsaved changes"
4 | },
5 | "optionsBackupInvalidFile" : {
6 | "message" : "Invalid backup file"
7 | },
8 | "optionBackupTitle" : {
9 | "message" : "Backup"
10 | },
11 | "popup_copiedToClipboard" : {
12 | "message" : "Copied to system clipboard"
13 | },
14 | "donateWithPaypal" : {
15 | "message" : "Donate with PayPal"
16 | },
17 | "optionsSwapStoragesHelp" : {
18 | "message" : "Swapping storages will replace the content of synchronized storage with the content of local storage and the other way around. This operation will fail if not enough space is available in synchronized storage."
19 | },
20 | "optionsSavedToastText" : {
21 | "message" : "Options saved"
22 | },
23 | "optionsStorageSizeHelp" : {
24 | "message" : "Currently synchronized storage size is limited by Google and cannot be increased. If you fill your space you should consider switching to local storage, which is unlimited. Don't forget to swap your storages."
25 | },
26 | "optionsSave" : {
27 | "message" : "Save"
28 | },
29 | "popupHintTitle" : {
30 | "message" : "Did you know?"
31 | },
32 | "optionStorageUsage" : {
33 | "message" : "Synchronized storage usage "
34 | },
35 | "optionSyncText" : {
36 | "message" : "Synchornized"
37 | },
38 | "editEntryIconTitle" : {
39 | "message" : "Edit",
40 | "description" : "Hover text on edit icon"
41 | },
42 | "extensionName" : {
43 | "message" : "Permanent clipboard",
44 | "description" : "Extension name."
45 | },
46 | "localStorageUsed" : {
47 | "message" : "Using local storage"
48 | },
49 | "optionBackupNewerFile" : {
50 | "message" : "Backup created with newer version of software. Please update your software."
51 | },
52 | "optionsBackupRestoreFailed" : {
53 | "message" : "Backup restore failed"
54 | },
55 | "deleteEntryIconTitle" : {
56 | "message" : "Delete"
57 | },
58 | "storageSwappingFailedMessage" : {
59 | "message" : "Swapping storage failed, aborting: "
60 | },
61 | "noMoreSpace" : {
62 | "message" : "No more space left"
63 | },
64 | "optionBackupCreateButton" : {
65 | "message" : "Create"
66 | },
67 | "optionBackupTip" : {
68 | "message" : "The backup will only be made from, and be restored to local storage. Sychronized storage is automatically backed up by Google when you sign in to your Google Account in Chrome."
69 | },
70 | "optionsText" : {
71 | "message" : "Settings",
72 | "description" : "Text displayed on top of options page"
73 | },
74 | "optionSwapStorageText" : {
75 | "message" : "Swap storages contents",
76 | "description" : ""
77 | },
78 | "popupHint" : {
79 | "message" : "Click on the element to store it in system clipboard",
80 | "description" : "Hint text showed in popup"
81 | },
82 | "optionsBackupRestored" : {
83 | "message" : "Backup restored"
84 | },
85 | "optionStorageTypeText" : {
86 | "message" : "Storage type",
87 | "description" : "Field description before combo on options screen"
88 | },
89 | "optionStorageCardTitle" : {
90 | "message" : "Storage"
91 | },
92 | "translatorsTitle" : {
93 | "message" : "Translation"
94 | },
95 | "optionBackupRestoreButton" : {
96 | "message" : "Read"
97 | },
98 | "optionSwapText" : {
99 | "message" : "Swap"
100 | },
101 | "addToExtensionDB" : {
102 | "message" : "Copy",
103 | "description" : "Context menu text on selected text."
104 | },
105 | "popupBack" : {
106 | "message" : "Back"
107 | },
108 | "insertFromExtension" : {
109 | "message" : "Paste",
110 | "description" : "Context menu text on editable elements."
111 | },
112 | "optionsBackupCorrupted" : {
113 | "message" : "Backup file corrupted, can't restore"
114 | },
115 | "popupHintNoElements" : {
116 | "message" : "No entries yet",
117 | "description" : "Hint visible when no elements are available"
118 | },
119 | "dropOverlayPromptText" : {
120 | "message" : "Drop backup file to restore"
121 | },
122 | "showAddFormText" : {
123 | "message" : "Add new entry",
124 | "description" : "Link text for new entry div trigger"
125 | },
126 | "unknownError" : {
127 | "message" : "Unknown error"
128 | },
129 | "contentPlaceholder" : {
130 | "message" : "Content",
131 | "description" : "Placeholder hint for content input box"
132 | },
133 | "errorFailedToSaveEntry" : {
134 | "message" : "Failed to save selection: "
135 | },
136 | "errorFailedToCreateDirectory": {
137 | "message" : "Failed to create directory: "
138 | },
139 | "addBtnText" : {
140 | "message" : "Add",
141 | "description" : "Text on add button in popup"
142 | },
143 | "extensionDescription" : {
144 | "message" : "Allows you to store and access multiple elements in clipboard",
145 | "description" : "Extension description."
146 | },
147 | "manageText" : {
148 | "message" : "Manage"
149 | },
150 | "commonCancel" : {
151 | "message" : "Cancel"
152 | },
153 | "popupHintText_1" : {
154 | "message" : "You can support Permanent Clipboard with donation using link in options screen."
155 | },
156 | "popupHintsCount" : {
157 | "message" : "2"
158 | },
159 | "descriptionPlaceholder" : {
160 | "message" : "Description",
161 | "description" : "Placeholder on input field in popup"
162 | },
163 | "popupHintText_2" : {
164 | "message" : "Enjoying PermanentClipboard? Rate it!<\/a>"
165 | },
166 | "optionSyncTip" : {
167 | "message" : "Local storage is kept only on this chrome instance.\nSynchronized storage is shared across all your chrome instances (it might working a bit slower then local storage)."
168 | },
169 | "popupNewElement" : {
170 | "message" : "Add from system clipboard",
171 | "description" : "New element title in popup"
172 | },
173 | "syncedStorageUsed" : {
174 | "message" : "Using synchronized storage",
175 | "description" : ""
176 | },
177 | "newDirectoryName" : {
178 | "message" : "New directory"
179 | },
180 | "optionsSuccess" : {
181 | "message" : "Success"
182 | },
183 | "optionLocalText" : {
184 | "message" : "Local"
185 | },
186 | "popup_ButtonDiscard" : {
187 | "message" : "Discard"
188 | },
189 | "menuRunningOutOfSpace" : {
190 | "message" : "Running out of space? Click here!"
191 | },
192 | "popup_missingPermissionsWarning": {
193 | "message" : "Some permissions are missing. Click to fix"
194 | },
195 | "permissions_clipboardRead": {
196 | "message" : "Reading clipboard"
197 | },
198 | "permissions_clipboardRead_rationale": {
199 | "message": "Required to read data from the system clipboard to simplify the process of adding new entries."
200 | },
201 | "permissions_clipboardWrite": {
202 | "message": "Writing to clipboard"
203 | },
204 | "permissions_clipboardWrite_rationale": {
205 | "message": "Required to put a selected snippet into the system clipboard for easier access to your data."
206 | },
207 | "permissions_grantPermission": {
208 | "message": "Grant"
209 | },
210 | "permissions_title": {
211 | "message": "Permanent Clipboard needs the following permissions to function properly."
212 | },
213 | "permissions_thankYou": {
214 | "message": "All permissions granted. Thank you!"
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/src/_locales/pl/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "popup_unsavedChanges" : {
3 | "message" : "Niezapisane zmiany"
4 | },
5 | "optionsBackupInvalidFile" : {
6 | "message" : "Niepoprawny plik kopii zapasowej"
7 | },
8 | "optionBackupTitle" : {
9 | "message" : "Kopia zapasowa"
10 | },
11 | "popup_copiedToClipboard" : {
12 | "message" : "Skopiowano do schowka"
13 | },
14 | "donateWithPaypal" : {
15 | "message" : "Dotuj przez PayPal"
16 | },
17 | "optionsSwapStoragesHelp" : {
18 | "message" : "Zamiana miejscami sprawia, że zawartość synchronizowanego schowka, znajdzie się na miejscu schowka lokalnego, i odwrotnie.\nZamiana nie powiedzie się jeśli nie ma wystarczająco dużo miejsca w schowku synchronizowanym."
19 | },
20 | "optionsSavedToastText" : {
21 | "message" : "Zapisano ustawienia"
22 | },
23 | "optionsStorageSizeHelp" : {
24 | "message" : "Pojemność schowka synchronizowanego jest ograniczona przez Google i nie można jej zwiększyć. Jeśli zapełnisz tą przestrzeń, rozważ użycie schowka synchronizowanego. Tylko pamiętaj, żeby przenieść zawartość."
25 | },
26 | "optionsSave" : {
27 | "message" : "Zapisz"
28 | },
29 | "popupHintTitle" : {
30 | "message" : "Czy wiesz, \u0010\u0010\u0010że?"
31 | },
32 | "optionStorageUsage" : {
33 | "message" : "Zużycie pamięci synchronizowanej "
34 | },
35 | "optionSyncText" : {
36 | "message" : "Synchronizowana"
37 | },
38 | "editEntryIconTitle" : {
39 | "message" : "Edytuj"
40 | },
41 | "extensionName" : {
42 | "message" : "Stały schowek"
43 | },
44 | "localStorageUsed" : {
45 | "message" : "Używasz pamięci lokalnej"
46 | },
47 | "optionBackupNewerFile" : {
48 | "message" : "Kopia utworzona nowszą wersją schowka. Zaktualizuj swoje oprogramowanie."
49 | },
50 | "optionsBackupRestoreFailed" : {
51 | "message" : "Nie udało się odtworzyć kopii zapasowej"
52 | },
53 | "deleteEntryIconTitle" : {
54 | "message" : "Usuń"
55 | },
56 | "storageSwappingFailedMessage" : {
57 | "message" : "Nie udało się podmienić zawartości: "
58 | },
59 | "noMoreSpace" : {
60 | "message" : "brak miejsca"
61 | },
62 | "optionBackupCreateButton" : {
63 | "message" : "Utwórz"
64 | },
65 | "optionBackupTip" : {
66 | "message" : "Kopia zapasowa wykonuje, i odtwarza, tylko zawartość schowka lokalnego. Schowek synchronizowany jest automatycznie kopiowany przez Google po zalogowaniu się na koncie Google w przeglądarce Chrome."
67 | },
68 | "optionsText" : {
69 | "message" : "Ustawienia"
70 | },
71 | "optionSwapStorageText" : {
72 | "message" : "Przenieś zawartość"
73 | },
74 | "popupHint" : {
75 | "message" : "Kliknij we wpis żeby zapisać go do schowka systemowego"
76 | },
77 | "optionsBackupRestored" : {
78 | "message" : "Odtworzono"
79 | },
80 | "optionStorageTypeText" : {
81 | "message" : "Typ pamięci"
82 | },
83 | "optionStorageCardTitle" : {
84 | "message" : "Pamięć"
85 | },
86 | "translatorsTitle" : {
87 | "message" : "Tłumaczenie"
88 | },
89 | "optionBackupRestoreButton" : {
90 | "message" : "Wczytaj"
91 | },
92 | "optionSwapText" : {
93 | "message" : "Zamień miejscami"
94 | },
95 | "addToExtensionDB" : {
96 | "message" : "Kopiuj"
97 | },
98 | "popupBack" : {
99 | "message" : "Wstecz"
100 | },
101 | "insertFromExtension" : {
102 | "message" : "Wklej"
103 | },
104 | "optionsBackupCorrupted" : {
105 | "message" : "Plik z kopią uszkodzony. Odzyskiwanie wstrzymane"
106 | },
107 | "popupHintNoElements" : {
108 | "message" : "Brak wpisów"
109 | },
110 | "dropOverlayPromptText" : {
111 | "message" : "Upuść plik kopii zapasowej żeby odtworzyć zawartość"
112 | },
113 | "showAddFormText" : {
114 | "message" : "Dodaj nowy wpis"
115 | },
116 | "unknownError" : {
117 | "message" : "Nieznany błąd"
118 | },
119 | "contentPlaceholder" : {
120 | "message" : "Zawartość"
121 | },
122 | "addBtnText" : {
123 | "message" : "Dodaj"
124 | },
125 | "errorFailedToSaveEntry" : {
126 | "message" : "Nie udało się dodać wpisu: "
127 | },
128 | "errorFailedToCreateDirectory": {
129 | "message" : "Nie udało się utworzyć katalogu: "
130 | },
131 | "extensionDescription" : {
132 | "message" : "Pozwala na zachownie i dostęp do wielu elementów w schowku"
133 | },
134 | "manageText" : {
135 | "message" : ""
136 | },
137 | "commonCancel" : {
138 | "message" : "Anuluj"
139 | },
140 | "popupHintText_1" : {
141 | "message" : "Możesz wesprzeć Stały schowek dotacją, klikając link w opcjach."
142 | },
143 | "descriptionPlaceholder" : {
144 | "message" : "Opis"
145 | },
146 | "popupHintsCount" : {
147 | "message" : "2"
148 | },
149 | "popupHintText_2" : {
150 | "message" : "Podoba Ci się Stały schowek? Wystaw ocenę!<\/a>"
151 | },
152 | "optionSyncTip" : {
153 | "message" : "Pamięć lokalna jest widoczna tylko na tym komputerze.\nPamięć synchronizowana jest widoczna na wszystkich przeglądarkach Google Chrome, na których jesteś zalgowany (może działać wolniej niż pamięć lokalna)."
154 | },
155 | "popupNewElement" : {
156 | "message" : "Dodaj ze schowka systemowego"
157 | },
158 | "newDirectoryName" : {
159 | "message" : "Nowy katalog"
160 | },
161 | "syncedStorageUsed" : {
162 | "message" : "Używasz pamięci synchronizowanej"
163 | },
164 | "optionsSuccess" : {
165 | "message" : "Zamieniono"
166 | },
167 | "optionLocalText" : {
168 | "message" : "Lokalna"
169 | },
170 | "popup_ButtonDiscard" : {
171 | "message" : "Odrzuć"
172 | },
173 | "menuRunningOutOfSpace" : {
174 | "message" : "Kończy Ci się miejsce? Kliknij tutaj!"
175 | }
176 | }
--------------------------------------------------------------------------------
/src/analytics.js:
--------------------------------------------------------------------------------
1 | function Analytics() {}
2 |
3 | Analytics.prototype = {
4 | userCode: function() { return 'UA-64085295-1'; },
5 | initialize: function() {
6 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
7 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
8 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
9 | })(window,document,'script','https://ssl.google-analytics.com/analytics.js','ga');
10 |
11 | ga('create', this.userCode(), 'auto');
12 | ga('set', 'checkProtocolTask', null);
13 | },
14 | trackEvent: function(category, action, label, value) {
15 | ga('send', 'event', category, action, label, value);
16 | }
17 | }
18 |
19 | var analytics = new Analytics();
20 | analytics.initialize();
21 |
--------------------------------------------------------------------------------
/src/background.js:
--------------------------------------------------------------------------------
1 | var storage = new Storage();
2 |
3 | let storagePercentageThreshold = 70;
4 |
5 | function IndexPath(string) {
6 | var separated = string.split('_');
7 | this._elements = [];
8 | for (var e in separated) {
9 | this._elements.push(parseInt(separated[e]));
10 | }
11 | }
12 |
13 | IndexPath.prototype = {
14 | constructor: IndexPath,
15 | length: function() { return this._elements.length; },
16 | get: function(part) { return this._elements[part]; },
17 | getLast: function() { return this._elements[this.length()-1]; }
18 | }
19 |
20 | function traverseWithIndexPath(indexPath, data) {
21 | var e = data;
22 | for (var i = 0; i < indexPath.length()-1; ++i)
23 | e = e[indexPath.get(i)].e;
24 | return e[indexPath.getLast()].value;
25 | }
26 |
27 | function onMenuClicked(info, tab) {
28 | if (info.menuItemId == "selmenu") {
29 | analytics.trackEvent('Menu', 'Selection added');
30 | chrome.tabs.sendMessage(tab.id, {event: ACTION__ADD_SELECTION});
31 | } else if (info.menuItemId == "runningOutOfSpace") {
32 | chrome.tabs.create({ url: CONTACT_PAGE_URL });
33 | } else {
34 | storage.getData('clipboard').then((data) => {
35 | var indexPath = new IndexPath(info.menuItemId);
36 | var val = traverseWithIndexPath(indexPath, data.clipboard);
37 |
38 | analytics.trackEvent('Menu', 'Inserting text');
39 | chrome.tabs.sendMessage(tab.id, {event:ACTION__INSERT_TEXT, value: val});
40 | }, (error) => console.error(error));
41 | }
42 | }
43 |
44 | function buildMenuLevel(menu, parentId) {
45 | var cnt = 0;
46 | for (var e in menu) {
47 | var elem = menu[e];
48 | if (!elem)
49 | continue;
50 | if (elem.e != null) {
51 | var newId = parentId + cnt + '_';
52 | chrome.contextMenus.create({"title": elem.desc, "parentId": parentId, "contexts": ["editable"], "id": newId});
53 | buildMenuLevel(elem.e, newId);
54 | } else {
55 | var newId = parentId + cnt;
56 | chrome.contextMenus.create({"title": elem.desc, "parentId": parentId, "contexts": ["editable"], "id": newId});
57 | }
58 | cnt++;
59 | }
60 | }
61 |
62 | function rebuildMenus() {
63 | chrome.contextMenus.removeAll(function() {
64 | storage.getData({'clipboard':[]}).then(items => {
65 | if (items.clipboard.length == 0) return;
66 | var title = chrome.i18n.getMessage("insertFromExtension");
67 | chrome.contextMenus.create({"title":title, "contexts":["editable"], "id": ""});
68 | buildMenuLevel(items.clipboard, "");
69 | }, error => {
70 | console.error("Failed to get data for menu filling: " + error.message);
71 | });
72 |
73 | var title = chrome.i18n.getMessage("addToExtensionDB");
74 | chrome.contextMenus.create({"title": title, "contexts":["selection"], "id": "selmenu"});
75 |
76 | storage.getStorageUsagePercentage().then((usage) => {
77 | if (usage > storagePercentageThreshold) {
78 | chrome.contextMenus.create({
79 | "id": "sep",
80 | "type": "separator",
81 | "parentId": ""
82 | });
83 | chrome.contextMenus.create({
84 | "title": chrome.i18n.getMessage("menuRunningOutOfSpace"),
85 | "contexts": ["selection", "editable"],
86 | "id": "runningOutOfSpace",
87 | "parentId": ""
88 | });
89 | }
90 | });
91 | });
92 | }
93 |
94 | chrome.runtime.onMessage.addListener(
95 | function(message, sender, sendResponse) {
96 | if (message.event == "rebuildMenus") {
97 | rebuildMenus();
98 | sendResponse({});
99 | return;
100 | } else if (message.event == 'saveRecentItem') {
101 | storage.setData({'recent': message.value}).then(() => {
102 | sendResponse({});
103 | }, (error) => sendResponse({'error': error}));
104 | } else if (message.event == 'addNewEntry') {
105 | storage.getData('clipboard').then((data) => {
106 | var clipboard = data.clipboard || [];
107 | clipboard.push({value: message.value, desc: message.value});
108 | storage.setData({'clipboard': clipboard}).then(() => {
109 | sendResponse({});
110 | rebuildMenus();
111 | }, (error) => {
112 | sendResponse({'error': error});
113 | rebuildMenus();
114 | });
115 | }, (error) => sendResponse({'error': error}));
116 | }
117 | return true;
118 | });
119 |
120 | function installContentScriptInTabs() {
121 | chrome.tabs.query({}, function(tabs) {
122 | for(var i in tabs) {
123 | if (tabs[i].url.startsWith("http://") || tabs[i].url.startsWith("https://")) {
124 | chrome.tabs.executeScript(tabs[i].id, {file: "contentscript.js"});
125 | }
126 | }
127 | });
128 | }
129 |
130 | chrome.contextMenus.onClicked.addListener(onMenuClicked);
131 |
132 | chrome.runtime.onInstalled.addListener(function() {
133 | rebuildMenus();
134 | installContentScriptInTabs();
135 | });
--------------------------------------------------------------------------------
/src/constants.js:
--------------------------------------------------------------------------------
1 | const ACTION__INSERT_TEXT = 'insertText';
2 | const ACTION__ADD_SELECTION = 'addSelection';
3 |
4 | const CONTACT_PAGE_URL = 'https://bartosz.im/permanent-clipboard/contact/index.html';
--------------------------------------------------------------------------------
/src/contentscript.js:
--------------------------------------------------------------------------------
1 | chrome.runtime.onMessage.addListener(
2 | function(message, sender, sendResponse) {
3 | switch (message.event) {
4 | case ACTION__INSERT_TEXT:
5 | document.execCommand("insertText", true, message.value);
6 | break;
7 | case ACTION__ADD_SELECTION:
8 | var selection = document.getSelection().toString();
9 | if (selection.length > 0)
10 | chrome.runtime.sendMessage({event: 'addNewEntry', value: selection}, function(response) {
11 | if (response.error != null)
12 | alert(chrome.i18n.getMessage("errorFailedToSaveEntry") + response.error.message);
13 | });
14 | break;
15 | default:
16 | console.warn('Unknown message event sent to content script' + message.event);
17 | }
18 | sendResponse({});
19 | });
20 |
21 | document.addEventListener('copy', function(e) {
22 | var selection = document.getSelection().toString();
23 | if (selection.length > 0)
24 | chrome.runtime.sendMessage({event:"saveRecentItem", value: selection}, function(response) {
25 | if (response.error != null)
26 | console.error("Failed to save recent item: " + response.error.message);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/css/material-icons.css:
--------------------------------------------------------------------------------
1 | /* fallback */
2 | @font-face {
3 | font-family: 'Material Icons';
4 | font-style: normal;
5 | font-weight: 400;
6 | src: url(../fonts/Material-Icons.woff2) format('woff2');
7 | }
8 |
9 | .material-icons {
10 | font-family: 'Material Icons';
11 | font-weight: normal;
12 | font-style: normal;
13 | font-size: 24px;
14 | line-height: 1;
15 | letter-spacing: normal;
16 | text-transform: none;
17 | display: inline-block;
18 | white-space: nowrap;
19 | word-wrap: normal;
20 | direction: ltr;
21 | -webkit-font-feature-settings: 'liga';
22 | -webkit-font-smoothing: antialiased;
23 | }
24 |
--------------------------------------------------------------------------------
/src/css/options.css:
--------------------------------------------------------------------------------
1 | body {
2 | display: flex;
3 | flex-direction: column;
4 | }
5 |
6 | main {
7 | flex: 1 0 auto;
8 | }
9 |
10 | #title {
11 | margin-left: 66px;
12 | font-size: 1.5rem;
13 | }
14 |
15 | .option-card-title {
16 | width: 680px;
17 | margin-left: auto;
18 | margin-right: auto;
19 | margin-top: 20pt;
20 | font-weight: 500;
21 | padding-left: 10pt;
22 | }
23 |
24 | .option-card {
25 | width: 680px;
26 | margin-left: auto;
27 | margin-right: auto;
28 | margin-top: 20pt;
29 | }
30 |
31 | .option-entry {
32 | margin-bottom: 0;
33 | display: flex;
34 | flex-direction: row;
35 | flex-wrap: nowrap;
36 | align-items: center;
37 | min-height: 46px;
38 | }
39 |
40 | .option-entry__name {
41 | flex-grow: 2;
42 | font-size: 1rem;
43 | align-items: flex-start;
44 | margin: auto 0;
45 | }
46 |
47 | .title-container {
48 | flex-grow: 2;
49 | align-items: flex-start;
50 | margin: auto 0;
51 | }
52 |
53 | .option-entry__title {
54 | flex-grow: 2;
55 | font-size: 1rem;
56 | align-items: flex-start;
57 | margin: auto 0;
58 | font-weight: bold;
59 | }
60 |
61 | .option-entry__subtitle {
62 | flex-grow: 2;
63 | font-size: 0.7rem;
64 | }
65 |
66 | .option-entry__action {
67 | display: flex;
68 | justify-content: flex-end;
69 | flex-grow: 2;
70 | align-self: flex-end;
71 | margin: auto 9pt;
72 | }
73 |
74 | /* Materialize css hack to remove bottom margin of select input */
75 | .option-entry__action > div.select-wrapper > input.select-dropdown {
76 | margin-bottom: 0;
77 | }
78 |
79 | .option-entry__decorator {
80 | flex-shrink: 0;
81 | align-self: flex-end;
82 | margin: auto 0;
83 | }
84 |
85 | .select-dropdown {
86 | margin-bottom: 0;
87 | }
88 |
89 | .drop-overlay {
90 | width: 60%;
91 | height: 60%;
92 | margin-left: 20%;
93 | margin-top: 10%;
94 | position: absolute;
95 | background-color: #505050aa;
96 | z-index: -1;
97 | border-radius: 10pt;
98 | align-items: center;
99 | display: flex;
100 | justify-content: center;
101 | pointer-events:none;
102 | }
103 |
104 | .drop-overlay_content {
105 | color: white;
106 | font-size: 25pt;
107 | pointer-events:none;
108 | margin: 10pt;
109 | text-align:center;
110 | }
111 |
112 | .hidden {
113 | display: none;
114 | }
115 |
116 | .dropzone {
117 | box-sizing: border-box;
118 | position: fixed;
119 | width: 100%;
120 | height: 100%;
121 | left: 0;
122 | top: 0;
123 | z-index: 99999;
124 | }
125 |
--------------------------------------------------------------------------------
/src/css/popup.css:
--------------------------------------------------------------------------------
1 | body {
2 | min-width: 357px;
3 | min-height: 357px;
4 | font-size: 10pt;
5 | display: flex;
6 | flex-direction: column;
7 | }
8 |
9 | main {
10 | flex: 1 0 auto;
11 | }
12 |
13 | a {
14 | cursor: pointer;
15 | }
16 |
17 | .default-cursor {
18 | cursor: default;
19 | }
20 |
21 | .ml1 {
22 | margin-left: 1pt;
23 | }
24 |
25 | .actionbtn {
26 | cursor: pointer;
27 | float: right;
28 | }
29 |
30 | div.rowrow {
31 | min-height: 40px;
32 | margin-bottom: 0;
33 | }
34 | .material-tooltip {
35 | white-space: pre;
36 | }
37 |
38 | td {
39 | padding: 10px 10px;
40 | }
41 |
42 | td.actioncell {
43 | width: 18pt;
44 | }
45 |
46 | div.cinvisible {
47 | display: none;
48 | }
49 | #current_div {
50 | padding-bottom: 0px;
51 | }
52 | div.top-padded {
53 | padding-top: 20px;
54 | padding-bottom: 1em;
55 | }
56 |
57 | .list-placeholder {
58 | background-color: #f5f5f5;
59 | }
60 |
61 | .topbar-button {
62 | margin-top: -20px;
63 | margin-left: 5pt;
64 | margin-right: 5pt;
65 | }
66 |
67 | .btn-action {
68 | padding: 0 .5em;
69 | }
70 |
--------------------------------------------------------------------------------
/src/css/translators.css:
--------------------------------------------------------------------------------
1 | .option-entry__language {
2 | flex-grow: 2;
3 | font-size: 1rem;
4 | align-items: flex-start;
5 | margin: auto 0;
6 | }
7 |
8 | .option-entry__translator {
9 | display: flex;
10 | justify-content: flex-end;
11 | flex-grow: 2;
12 | align-self: flex-end;
13 | margin: auto 9pt;
14 | font-size: 1rem;
15 | }
16 |
--------------------------------------------------------------------------------
/src/fonts/Material-Icons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/Material-Icons.woff2
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Bold.eot
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Bold.woff
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Bold.woff2
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Light.eot
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Light.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Light.woff
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Light.woff2
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Medium.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Medium.eot
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Medium.woff
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Medium.woff2
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Regular.eot
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Regular.woff
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Regular.woff2
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Thin.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Thin.eot
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Thin.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Thin.woff
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Thin.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/fonts/roboto/Roboto-Thin.woff2
--------------------------------------------------------------------------------
/src/img/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icon-128.png
--------------------------------------------------------------------------------
/src/img/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icon-16.png
--------------------------------------------------------------------------------
/src/img/icon-19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icon-19.png
--------------------------------------------------------------------------------
/src/img/icon-38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icon-38.png
--------------------------------------------------------------------------------
/src/img/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/img/icons/ic_folder_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icons/ic_folder_1x.png
--------------------------------------------------------------------------------
/src/img/icons/ic_folder_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icons/ic_folder_2x.png
--------------------------------------------------------------------------------
/src/img/icons/ic_help_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icons/ic_help_1x.png
--------------------------------------------------------------------------------
/src/img/icons/ic_help_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icons/ic_help_2x.png
--------------------------------------------------------------------------------
/src/img/icons/ic_navigate_before_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icons/ic_navigate_before_1x.png
--------------------------------------------------------------------------------
/src/img/icons/ic_navigate_before_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/przybylski/permanent-clipboard/75bf107c7bf4d7720d57ec996f35b4e73416925a/src/img/icons/ic_navigate_before_2x.png
--------------------------------------------------------------------------------
/src/jquery-ui/AUTHORS.txt:
--------------------------------------------------------------------------------
1 | Authors ordered by first contribution
2 | A list of current team members is available at http://jqueryui.com/about
3 |
4 | Paul Bakaus
5 | Richard Worth
6 | Yehuda Katz
7 | Sean Catchpole
8 | John Resig
9 | Tane Piper
10 | Dmitri Gaskin
11 | Klaus Hartl
12 | Stefan Petre
13 | Gilles van den Hoven
14 | Micheil Bryan Smith
15 | Jörn Zaefferer
16 | Marc Grabanski
17 | Keith Wood
18 | Brandon Aaron
19 | Scott González
20 | Eduardo Lundgren
21 | Aaron Eisenberger
22 | Joan Piedra
23 | Bruno Basto
24 | Remy Sharp
25 | Bohdan Ganicky
26 | David Bolter
27 | Chi Cheng
28 | Ca-Phun Ung
29 | Ariel Flesler
30 | Maggie Wachs
31 | Scott Jehl
32 | Todd Parker
33 | Andrew Powell
34 | Brant Burnett
35 | Douglas Neiner
36 | Paul Irish
37 | Ralph Whitbeck
38 | Thibault Duplessis
39 | Dominique Vincent
40 | Jack Hsu
41 | Adam Sontag
42 | Carl Fürstenberg
43 | Kevin Dalman
44 | Alberto Fernández Capel
45 | Jacek Jędrzejewski (http://jacek.jedrzejewski.name)
46 | Ting Kuei
47 | Samuel Cormier-Iijima
48 | Jon Palmer
49 | Ben Hollis
50 | Justin MacCarthy
51 | Eyal Kobrigo
52 | Tiago Freire
53 | Diego Tres
54 | Holger Rüprich
55 | Ziling Zhao
56 | Mike Alsup
57 | Robson Braga Araujo
58 | Pierre-Henri Ausseil
59 | Christopher McCulloh
60 | Andrew Newcomb
61 | Lim Chee Aun
62 | Jorge Barreiro
63 | Daniel Steigerwald
64 | John Firebaugh
65 | John Enters
66 | Andrey Kapitcyn
67 | Dmitry Petrov
68 | Eric Hynds
69 | Chairat Sunthornwiphat
70 | Josh Varner
71 | Stéphane Raimbault
72 | Jay Merrifield
73 | J. Ryan Stinnett
74 | Peter Heiberg
75 | Alex Dovenmuehle
76 | Jamie Gegerson
77 | Raymond Schwartz
78 | Phillip Barnes
79 | Kyle Wilkinson
80 | Khaled AlHourani
81 | Marian Rudzynski
82 | Jean-Francois Remy
83 | Doug Blood
84 | Filippo Cavallarin
85 | Heiko Henning
86 | Aliaksandr Rahalevich
87 | Mario Visic
88 | Xavi Ramirez
89 | Max Schnur
90 | Saji Nediyanchath
91 | Corey Frang
92 | Aaron Peterson
93 | Ivan Peters
94 | Mohamed Cherif Bouchelaghem
95 | Marcos Sousa
96 | Michael DellaNoce
97 | George Marshall
98 | Tobias Brunner
99 | Martin Solli
100 | David Petersen
101 | Dan Heberden
102 | William Kevin Manire
103 | Gilmore Davidson
104 | Michael Wu
105 | Adam Parod
106 | Guillaume Gautreau
107 | Marcel Toele
108 | Dan Streetman
109 | Matt Hoskins
110 | Giovanni Giacobbi
111 | Kyle Florence
112 | Pavol Hluchý
113 | Hans Hillen
114 | Mark Johnson
115 | Trey Hunner
116 | Shane Whittet
117 | Edward A Faulkner
118 | Adam Baratz
119 | Kato Kazuyoshi
120 | Eike Send
121 | Kris Borchers
122 | Eddie Monge
123 | Israel Tsadok
124 | Carson McDonald
125 | Jason Davies
126 | Garrison Locke
127 | David Murdoch
128 | Benjamin Scott Boyle
129 | Jesse Baird
130 | Jonathan Vingiano
131 | Dylan Just
132 | Hiroshi Tomita
133 | Glenn Goodrich
134 | Tarafder Ashek-E-Elahi
135 | Ryan Neufeld
136 | Marc Neuwirth
137 | Philip Graham
138 | Benjamin Sterling
139 | Wesley Walser
140 | Kouhei Sutou
141 | Karl Kirch
142 | Chris Kelly
143 | Jason Oster
144 | Felix Nagel
145 | Alexander Polomoshnov
146 | David Leal
147 | Igor Milla
148 | Dave Methvin
149 | Florian Gutmann
150 | Marwan Al Jubeh
151 | Milan Broum
152 | Sebastian Sauer
153 | Gaëtan Muller
154 | Michel Weimerskirch
155 | William Griffiths
156 | Stojce Slavkovski
157 | David Soms
158 | David De Sloovere
159 | Michael P. Jung
160 | Shannon Pekary
161 | Dan Wellman
162 | Matthew Edward Hutton
163 | James Khoury
164 | Rob Loach
165 | Alberto Monteiro
166 | Alex Rhea
167 | Krzysztof Rosiński
168 | Ryan Olton
169 | Genie <386@mail.com>
170 | Rick Waldron
171 | Ian Simpson
172 | Lev Kitsis
173 | TJ VanToll
174 | Justin Domnitz
175 | Douglas Cerna
176 | Bert ter Heide
177 | Jasvir Nagra
178 | Yuriy Khabarov <13real008@gmail.com>
179 | Harri Kilpiö
180 | Lado Lomidze
181 | Amir E. Aharoni
182 | Simon Sattes
183 | Jo Liss
184 | Guntupalli Karunakar
185 | Shahyar Ghobadpour
186 | Lukasz Lipinski
187 | Timo Tijhof
188 | Jason Moon
189 | Martin Frost
190 | Eneko Illarramendi
191 | EungJun Yi
192 | Courtland Allen
193 | Viktar Varvanovich
194 | Danny Trunk
195 | Pavel Stetina
196 | Michael Stay
197 | Steven Roussey
198 | Michael Hollis
199 | Lee Rowlands
200 | Timmy Willison
201 | Karl Swedberg
202 | Baoju Yuan
203 | Maciej Mroziński
204 | Luis Dalmolin
205 | Mark Aaron Shirley
206 | Martin Hoch
207 | Jiayi Yang
208 | Philipp Benjamin Köppchen
209 | Sindre Sorhus
210 | Bernhard Sirlinger
211 | Jared A. Scheel
212 | Rafael Xavier de Souza
213 | John Chen
214 | Robert Beuligmann
215 | Dale Kocian
216 | Mike Sherov
217 | Andrew Couch
218 | Marc-Andre Lafortune
219 | Nate Eagle
220 | David Souther
221 | Mathias Stenbom
222 | Sergey Kartashov
223 | Avinash R
224 | Ethan Romba
225 | Cory Gackenheimer
226 | Juan Pablo Kaniefsky
227 | Roman Salnikov
228 | Anika Henke
229 | Samuel Bovée
230 | Fabrício Matté
231 | Viktor Kojouharov
232 | Pawel Maruszczyk (http://hrabstwo.net)
233 | Pavel Selitskas
234 | Bjørn Johansen
235 | Matthieu Penant
236 | Dominic Barnes
237 | David Sullivan
238 | Thomas Jaggi
239 | Vahid Sohrabloo
240 | Travis Carden
241 | Bruno M. Custódio
242 | Nathanael Silverman
243 | Christian Wenz
244 | Steve Urmston
245 | Zaven Muradyan
246 | Woody Gilk
247 | Zbigniew Motyka
248 | Suhail Alkowaileet
249 | Toshi MARUYAMA
250 | David Hansen
251 | Brian Grinstead
252 | Christian Klammer
253 | Steven Luscher
254 | Gan Eng Chin
255 | Gabriel Schulhof
256 | Alexander Schmitz
257 | Vilhjálmur Skúlason
258 | Siebrand Mazeland
259 | Mohsen Ekhtiari
260 | Pere Orga