====== Zotero 8 for Developers ======
Zotero 8 includes an internal upgrade of the Mozilla platform on which Zotero is based, incorporating changes from Firefox 115 through Firefox 140.
Most of the guidance from [[Zotero 7 for Developers]] is still relevant.
===== Feedback =====
If you have questions about anything on this page or encounter other problems while updating your plugin, let us know on the [[https://groups.google.com/g/zotero-dev|dev list]]. Please don't post to the Zotero Forums about Zotero 8 at this time.
===== Dev Builds =====
The ''dev'' channel has been paused. Use [[:beta_builds|Zotero 8 beta builds]] for development.
===== Platform Changes =====
==== Mozilla Platform ====
The following list includes nearly all Mozilla changes that affected Zotero code. You may encounter other breaking changes if you use APIs not used in Zotero. [[https://searchfox.org/|Searchfox]] is the best resource for identifying current correct usage in Mozilla code and changes between Firefox 115 and Firefox 140.
Earlier Zotero 8.0 (formerly 7.1) beta releases were based on Firefox 128, so we've listed changes for Firefox 128 and 140 separately.
=== Firefox 115 → Firefox 128 ("Zotero 7.1" beta) ===
* Manual ''Services.jsm'' imports must be removed ([[https://github.com/zotero/zotero/commit/97329752a1839210d636b7b8d37deae854d42410|example]])
* ''nsIScriptableUnicodeConverter'' was removed; replace ''convertToByteArray()'' and ''convertToInputStream()'' ([[https://github.com/zotero/zotero/commit/24bf583b787d21117000336e4f67ddc9ac7b1deb|example]])
* ''nsIOSFileConstantsService'' was removed ([[https://github.com/zotero/zotero/commit/7f619e3fe3044ea968a9bd0fb31d98f45d5cb75b|example]])
* ''XPCOMUtils.defineLazyGetter'' → ''ChromeUtils.defineLazyGetter'' ([[https://github.com/zotero/zotero/commit/9606fca3ad39a52d29d0c74ae96fb680c14ad4e3|example]])
* ''nsIDOMChromeWindow'' was removed ([[https://github.com/zotero/zotero/commit/45e681431bfd6b77bfaf8f55ce87f04fedb4a475|example]])
* Login manager: ''addLogin'' → ''addLoginAsync'' ([[https://github.com/zotero/zotero/commit/fa2073335342f5f8f067b0e2cad12611012bcab5|example]])
* ''BrowsingContext'' should be passed to ''nsIFilePicker'' init ([[https://github.com/zotero/zotero/commit/72b56e7a592a6793817e2a7479b08b6f2e334252|example]], but we recommend using Zotero's ''FilePicker'' module instead)
* ''DataTransfer#types'': ''contains()'' → ''includes()'' —?now a standard array ([[https://github.com/zotero/zotero/commit/f28fa763ccfc5aac4575c1a2b28f532d84c89bf2|example]])
* ''-moz-nativehyperlinktext'' → ''LinkText'' ([[https://github.com/zotero/zotero/commit/b85864595754fe54ae841902df2e4f3276a7574f|example]])
=== Firefox 128 → Firefox 140 (Zotero 8) ===
* All JSMs (''.jsm'' files) in Firefox and Zotero were converted to ESMs (''.mjs'' files, or ''.sys.mjs'' files for Firefox code) ([[https://github.com/zotero/zotero/commit/6f96fa9da8368080001143898f6c3ece60939359|example]])
* Zotero now uses [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules|standard JavaScript modules]] and ''import'' statements ([[https://github.com/zotero/zotero/commit/09fc93f9772a267f581198d5ce6a768744ed9d9c|example]])
* See Mozilla's [[https://groups.google.com/a/mozilla.org/g/firefox-dev/c/od7Bd1QpCuU|primer on ESMification]] — in particular, the "Renamed New API" section
* **Zotero includes a script that can update most JSM-based code automatically.** Copy the ''[[https://github.com/zotero/zotero/tree/main/scripts/migrate-fx140|migrate-fx140]]'' directory into your plugin's Git repo and run ''migrate-fx140/migrate.py esmify path/to/Module.jsm''. To update the imports in a non-JSM file, run ''migrate-fx140/migrate.py esmify %%--%%imports path/to/file.js''. Both commands also accept a directory for batch conversion.
* Global imports are no longer supported. Imported modules need to be assigned to a variable. ([[https://github.com/zotero/zotero/commit/5e64365ce1ad07bd8f9308c76c4c39658883d0a7|example]])
* All ESMs run in [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode|strict mode]]
* Bluebird was removed — Zotero now uses standard JavaScript promises everywhere ([[https://github.com/zotero/zotero/commit/b090f5d4eb10108052f95b6afb7599301a81f125|example]])
* **Zotero provides a script that can update most Bluebird-based code automatically.** Copy the ''[[https://github.com/zotero/zotero/tree/fx140/scripts/migrate-fx140|migrate-fx140]]'' directory into your plugin's Git repo and run ''migrate-fx140/migrate.py asyncify path/to/file.js''. This command also accepts a directory for batch conversion.
* For compatibility, ''Zotero.Promise.delay()'' and ''Zotero.Promise.defer()'' are still supported. ''defer()'' can no longer be called as a constructor ([[https://github.com/zotero/zotero/commit/8d6a853a3fe11d4ad560dde8aa270f8aecee35ba|example]]).
* Bluebird Promise instance methods like ''map()'', ''filter()'', ''each()'', ''isResolved()'', ''isPending()'', and ''cancel()'' are no longer available. Collection methods can usually be replaced with iteration ([[https://github.com/zotero/zotero/commit/692312b419dfb7f0aaa8759230a9aafe62bbdc60|example]], [[https://github.com/zotero/zotero/commit/d734d78812c841f7adffdbb35b20b80606b67331|example]]) or awaits ([[https://github.com/zotero/zotero/commit/cf18fe69a9ffef4945841d62d4031c9137f2c5f2|example]]). Complicated ''isPending()'' logic will need to be rewritten ([[https://github.com/zotero/zotero/commit/8ffdb8bca2585408334c7dad7b1dce366fd6cd1a|example]]).
* ''ZoteroProtocolHandler'' extensions: ''new AsyncChannel()'' now takes an async function, not a generator ([[https://github.com/zotero/zotero/commit/ccc5dba03220b20722e94a1936a709ffc7a6c025|example]])
* ''Zotero.spawn()'' was removed.
* ''Services.appShell.hiddenDOMWindow'' was removed outside macOS — use only as a fallback ([[https://github.com/zotero/zotero/commit/cd813171e7d29b164d3760698274790e888c8fbb|example]])
* ''ZOTERO_CONFIG'' needs to be imported ([[https://github.com/zotero/zotero/commit/5e64365ce1ad07bd8f9308c76c4c39658883d0a7|example]])
* Preference panes now run in their own global scope, so a ''var'' defined in one preference pane's script won't automatically be accessible to other preference panes. Set variables on ''window'' explicitly if you need to share them between preference panes.
* Update button labels using the ''label'' property, not attribute ([[https://github.com/zotero/zotero/commit/b828cd5281e8a3ef5c86349b13d0796d8b08caf0|example]])
* The first segment of a zotero: URI is now parsed as its host, not as part of its path ([[https://github.com/zotero/zotero/commit/9cad92b817e56beb108a57b00929ce756dda4125|example]])
===== Plugin Changes =====
==== Custom Menu Items ====
A new API allows plugins to create custom menu items in Zotero's menu popups. Plugins should use this official API if possible rather than manually injecting content.
The example below shows registering a custom menu item and a submenu in Zotero's items list context menu.
let registeredID = Zotero.MenuManager.registerMenu({
menuID: "test",
pluginID: "example@example.com",
target: "main/library/item",
menus: [
{
menuType: "menuitem",
l10nID: "menu-print",
onShowing: (event, context) => {
Zotero.debug("onShowing");
Zotero.debug(Object.keys(context));
},
onCommand: (event, context) => {
Zotero.debug("onCommand");
Zotero.debug(Object.keys(context));
},
},
{
menuType: "submenu",
l10nID: "menu-print",
menus: [
{
menuType: "menuitem",
l10nID: "menu-print",
onShowing: (event, context) => {
Zotero.debug("onShowing submenu");
Zotero.debug(Object.keys(context));
// Only for regular items
context.setVisible(context.items?.every((item) => item.isRegularItem()));
},
onCommand: (event, context) => {
Zotero.debug("onCommand submenu");
Zotero.debug(Object.keys(context));
},
},
],
},
],
});
Available targets:
* **Main window menubar menus**
* main/menubar/file — File menu in the main window menubar
* main/menubar/edit — Edit menu in the main window menubar
* main/menubar/view — View menu in the main window menubar
* main/menubar/go — Go menu in the main window menubar
* main/menubar/tools — Tools menu in the main window menubar
* main/menubar/help — Help menu in the main window menubar
* **Main window library context menus**
* main/library/item — Context menu for library items
* main/library/collection — Context menu for library collections
* **Main window toolbar & file menu submenus**
* main/library/addAttachment — “Add attachment” button/menu
* main/library/addNote — “New note” button/menu
* **Main window tab context menus**
* main/tab — Context menu for main window tabs
* **Reader window menubar menus**
* reader/menubar/file — File menu in reader window
* reader/menubar/edit — Edit menu in reader window
* reader/menubar/view — View menu in reader window
* reader/menubar/go — Go menu in reader window
* reader/menubar/window — Window menu in reader window
* **Item pane context menus**
* itemPane/info/row — Context menu for item pane info rows
* **Notes pane add note buttons**
* notesPane/addItemNote — Add item note button
* notesPane/addStandaloneNote — Add standalone note button
* **Sidenav buttons**
* sidenav/locate — Locate button in side navigation
More advanced options are documented in the?[[https://github.com/zotero/zotero/blob/main/chrome/content/zotero/xpcom/pluginAPI/menuManager.js|source code]].
When the plugin is disabled or uninstalled, custom menus with the corresponding?''pluginID''?will be automatically removed. If you want to unregister a custom menu manually, you can use?''unregisterMenu()'':
Zotero.MenuManager.unregisterMenu(registeredID);
If you encounter any problem with this API, please let us know on the [[https://groups.google.com/g/zotero-dev|dev list]].
Among the most interesting of Plutarch’s religious writings is one entitled On the Delays in the Divine Vengeance. As might be expected from the name, it deals with a problem closely akin to that which ages before had been made the subject of such sublime imagery and such inconclusive reasoning by the author of the Book of Job. What troubled the Hebrew poet was the apparently undeserved suffering of the just. What the Greek moralist feels himself called on to explain is the apparent prosperity and impunity of the wicked. He will not for a moment admit that crime remains unavengeful; his object is to show why the retribution does not follow directly on the deed. And, in order to account for this, he adduces a number of very ingenious reasons. By acting deliberately rather than in blind anger, the gods wish to read us a useful lesson in patience and forbearance. Sometimes their object is to give the sinner an opportunity for repentance and amendment; or else they may be holding him in reserve for the performance of some beneficial work. At other times, their justice is delayed only that it may be manifested by some signal and striking form of retribution. In many cases, the final stroke has been preceded by long years of secret torment; and even where no suffering seems to be inflicted, the pangs of remorse may furnish a sufficient expiation. Or again, vengeance may be reserved for a future generation. Some persons hold that to267 visit the sins of the fathers on the children is unjust, but in this they are profoundly mistaken. Members of the same family and citizens of the same state are connected as parts of one organic whole; sharing in the benefits which accrue from the good deeds of their predecessors, it is right that they should also share in the responsibility for their crimes. Moreover, the posterity of the wicked inherit a sinful disposition which, as the gods can clearly foresee, would betray itself in overt acts were they not cut off in their youth. And it is equally an error to suppose that the original wrongdoers remain unaffected by the retribution which befalls their descendants. On the contrary, they witness it from the next world, where it adds poignancy to their remorse, and entails on them fresh penalties over and above those which they have already been doomed to suffer. This preference of pure abstract speculation to beneficent290 action may be traced to the influence of Aristotle. Some of the most enthusiastic expressions used by Plotinus in speaking of his supreme principle seem to have been suggested by the Metaphysics and the last book of the Nicomachean Ethics. The self-thinking thought of the Stagirite does not, indeed, take the highest rank with him. But it is retained in his system, and is only relegated to a secondary place because, for reasons which we shall explain hereafter, it does not fulfil equally well with Plato’s Idea of Good, the condition of absolute and indivisible unity, without which a first principle could not be conceived by any Greek philosopher. But this apparent return to the standpoint of the Republic really involves a still wider departure from its animating spirit. In other words, Plotinus differs from Aristotle as Aristotle himself had differed from Plato; he shares the same speculative tendency, and carries it to a greater extreme. "Yes?" she answered, and stroked the head of the fawn. She dropped beside him and tried to hold him down. "He did not know I was coming here," she pleaded. "It was a mistake, Jack! Will you wait until I tell you? Will you wait?" She was clinging around his neck and would not be shaken off. He dragged her in the dust, trying to get free himself. Feeling entirely at ease, he climbed into the car, with a copy of the Cincinnati Gazette, which he had bought of a newsboy, lighted his pipe, put on his spectacles, and settled down to a labored, but thorough perusal of the paper, beginning at the head-lines on the upper left-hand corner, and taking in every word, advertisements and all, as systematically as he would weed a garden-bed or milk a cow. The Deacon never did anything slip-shod, especially when he had to pay 10 cents for a copy of the Cincinnati Gazette. He was going to get his full money's worth, and if it was not in the news and editorials, he would take it out of the advertisements and patent medicine testimonials. He was just going through a convincing testimonial to the manifold virtues of Spalding's Prepared Glue, when there was a bump, the sound of coupling, and his car began to move off. Little Sammy Woggles came out presently to get some wood. Shorty called him to him. There was something fascinatingly mysterious in his tones and actions to that youth, who devoured dime novels on the sly. "GREAT Jehosephat, how hungry I am," suddenly ejaculated Shorty, stopping his cheering, as the thunder of the guns died away into an occasional shot after the rebels galloping back to the distant woods on the ridge from which they had emerged. "It isn't funny, Albin," Dodd said woodenly. "It isn't a game." "Who fill their pockets at Scott's Float, "No—I d?an't say it. I did write 'em. But it's all your fault that I did—so you've no right to miscall me." Alice Jury said nothing, and Reuben began to feel vaguely uncomfortable. What queer eyes she had!—they seemed to bore into him like nails. He suddenly rose to his feet. "Where's master?" "Now, lads, to your homes," cried Turner, as they hurried on, "every man of ye. Go by different roads, and you will not be suspected. There is not a man they can swear to but myself. Now, brave hearts, farewell! We may not meet together again: but all the harm I wish ye is, that Calverley and I may soon meet; and if ever he plagues free man or bond among ye after that, say Wat Turner is a coward—Away! Tom Merritt," said he, drawing the mason aside, "do you think of leaving Winchcombe?—you know there are always busy tongues." HoME美女护士性交不雅照
ENTER NUMBET 0017
www.minji3.net.cn
www.qianedai.com.cn
qcxgg.com.cn
danji4.net.cn
www.bacun4.net.cn
www.cqbgjj.com.cn
www.supin4.net.cn
laote9.net.cn
www.liche7.com.cn
8webfind.com.cn