Static output of presentation as presented
This commit is contained in:
parent
57e4c16287
commit
1f8bb1f30c
88 changed files with 10453 additions and 0 deletions
772
_static/index.html
Normal file
772
_static/index.html
Normal file
|
@ -0,0 +1,772 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
|
||||
<title>reveal-md</title>
|
||||
<link rel="shortcut icon" href="./favicon.ico" />
|
||||
<link rel="stylesheet" href="./dist/reset.css" />
|
||||
<link rel="stylesheet" href="./dist/reveal.css" />
|
||||
<link rel="stylesheet" href="./dist/theme/black.css" id="theme" />
|
||||
<link rel="stylesheet" href="./css/highlight/base16/zenburn.css" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="reveal">
|
||||
<div class="slides">
|
||||
<section data-markdown data-separator="\r?\n---\r?\n" data-separator-vertical="\r?\n----\r?\n">
|
||||
<textarea data-template>
|
||||
|
||||
|
||||
#### When There's Not a Module for That— How to Make (and Maintain) a New Module
|
||||
|
||||
New England Drupal Camp @ Rhode Island College
|
||||
Providence, RI
|
||||
November 16, 2024
|
||||
#NEDCamp2024
|
||||
9am, Gaige Hall 206
|
||||
|
||||
benjamin "mlncn" melançon
|
||||
ben@agaric.coop
|
||||
|
||||
---
|
||||
|
||||
### Agaric Technology Collective
|
||||
|
||||

|
||||
|
||||
presents
|
||||
|
||||
Note: my name's ben, i have been a worker and owner at the worker-owned Agaric cooperative since 2006.
|
||||
|
||||
---
|
||||
|
||||
## When There's *Not*
|
||||
## a Module for That
|
||||
### How to Make (and Maintain)
|
||||
### a New Drupal Module
|
||||
|
||||
---
|
||||
|
||||
###### Presented by
|
||||
|
||||
**Benjamin Melançon**
|
||||
**[mlncn](https://agaric.coop/mlncn)**
|
||||
|
||||
|
||||
with behind-the-scenes help from
|
||||
|
||||
Mauricio Dinarte
|
||||
**[dinarcon](https://agaric.coop/dinarcon)**
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
TOGETHER, we are **⅓** of
|
||||
|
||||
<img alt="Agaric" src="content/images/agaric-logo-stacked.png" class="plain" />
|
||||
|
||||
a web technology collective
|
||||
|
||||
**ask@agaric.coop**
|
||||
|
||||
---
|
||||
|
||||
Send complaints to ben@agaric.coop
|
||||
|
||||
and heckling posts to social.coop/@mlncn
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
Note: So what do you do when there's not a module for that? You make your own. It's easy.
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
|
||||
Note: Say you're creating a site where people can relive great literature that may have been inspired by a famine. You've already created an excellent content type under Structure » Content. But somehow the usual "Save" doesn't communicate what you want when creating Frankenstein content.
|
||||
|
||||
---
|
||||
|
||||
|
||||
`frankenstein.info.yml`
|
||||
|
||||
```yaml
|
||||
name: Frankenstein
|
||||
description: "Rename save button for Frankenstein's content."
|
||||
type: module
|
||||
core_version_requirement: ^8 || ^9 || ^10 || ^11 || ^12
|
||||
```
|
||||
|
||||
Note: This file tells Drupal about your module, and it is technically all you need to enable your module.
|
||||
|
||||
---
|
||||
|
||||
|
||||
`frankenstein.module`
|
||||
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* Implements hook_form_FORM_NAME_alter() for "Frankenstein" node (add) form.
|
||||
*/
|
||||
function frankenstein_form_node_frankenstein_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
|
||||
$form['actions']['submit']['#value'] = t('Re-animate!');
|
||||
}
|
||||
```
|
||||
|
||||
Note: There we go, there's a module! I think we're done here. Anyone have any ideas for the next 40 minutes? `.info.yml` files are not PHP. They cleverly indicate this by not starting with `<?php`. `.module` files are PHP...
|
||||
|
||||
---
|
||||
|
||||
### Where to put these files
|
||||
|
||||

|
||||
|
||||
Note: Our files are in place in our local site, now we go to our create 'Frankenstein' content form and…
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
# Enable your module
|
||||
|
||||
At **Extend** (`/admin/modules`) or with:
|
||||
|
||||
`drush -y en frankenstein`
|
||||
|
||||
|
||||
Note: That slide may be the most important you're going to be shown. Enable your module.
|
||||
|
||||
---
|
||||
|
||||
|
||||

|
||||
|
||||
Note: Tadaaa! Now you know how to make a module!
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
Note: So you're all sitting* there thinking ... sure, that's easy if you know the exact words and symbols to *put* in that file. And you're absolutely right. And we're going to tell you how you can figure out all of that.
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
|
||||
Note: It has often been said, Drupal is a box of legos that you can build just about anything you want with. But sometimes those legos have been put together for you. And sometimes not.
|
||||
|
||||
---
|
||||
|
||||
A few basic approaches give a lot of power.
|
||||
|
||||
<img alt="Screwdriver with extensive collection of driver tips." src="content/images/screwdriver-tip-set.jpg" width="70%" />
|
||||
|
||||
Note: A few specific examples will give you a lot of tools. But first, two secrets. One's good news, second is bad news.
|
||||
|
||||
---
|
||||
|
||||
#### Good News
|
||||
|
||||
### Now you know where to paste
|
||||
|
||||

|
||||
|
||||
Note: And knowing where to paste unleashes the power of Stack Overflow / Stack Exchange sites. (yes, the same family of sites that has helped a couple million developers figure out how to quit vim.) Knowing where to put this code unleashes the power of Stack Overflow. You now know enough to be dangerous. And i hope i have definitively slayed (slewn?) the mythology that module-making is a mystic domain of Drupal druids.
|
||||
|
||||
---
|
||||
|
||||
#### Bad News
|
||||
### That simple form alter has hidden gotchas
|
||||
|
||||
|
||||
|
||||
* As written, it only applies to the create (node/add) form— not the edit form.
|
||||
* There's a dozen variations of the humble form alter hook, and all are valid.
|
||||
|
||||
Note: With our dirty secrets acknowledged, on with the show. We'll show the edit form hook later on!
|
||||
|
||||
---
|
||||
|
||||
## The Show
|
||||
|
||||
- Prelude: **How To Make a Module**
|
||||
- Act One: **How Not To Make a Module**
|
||||
- Act Two: **How Not To Have to Make a Whole Module**
|
||||
- Act Three: **How To Figure Out How To Make a Module**
|
||||
- Encore: **How To Contribute Your Module**
|
||||
|
||||
---
|
||||
|
||||
Act One
|
||||
|
||||
### How Not To Make a Module
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Hierarchy of Code Usage
|
||||
|
||||
Stop at the first layer configurable to your needs.
|
||||
|
||||
1. Drupal core code
|
||||
2. Broadly supported contributed module code
|
||||
3. Less-supported or patched contributed module code
|
||||
4. Code you have written and contributed
|
||||
5. Custom code you have written and hidden from the world
|
||||
|
||||
Note: Why not to make a module.
|
||||
|
||||
---
|
||||
|
||||
#### When not to make a module?
|
||||
|
||||
[](https://www.koreus.com/video/machine-rube-goldberg-lente.html)
|
||||
|
||||
Note: You can do anything with a module! Why wouldn't you make one every day?
|
||||
|
||||
---
|
||||
|
||||
|
||||
#### …when there's an easier way
|
||||
|
||||

|
||||
|
||||
Note: find a contrib module that does it. Should it be in a template? If it's very specific to the display on your site, you should probably do it in the theme layer. But if it's at all data and you might ever want to switch themes, or want to allow site builders or site managers to disable or change settings, get that in a module.
|
||||
|
||||
---
|
||||
|
||||
Alternatives to a module:
|
||||
|
||||
- Template override
|
||||
- String override
|
||||
- ECA (Event Condition Action, or now Rules is also stable, but i like ECA)
|
||||
|
||||
Note: There are a couple of modules for string overrides, or they can go in settings.php. ECA is not necessarily faster than making a module, especially once you know how to make a module, but it exposes the logic to non-developers better.
|
||||
|
||||
---
|
||||
|
||||
> When building a Drupal site, “there’s a module for that” can be the sweetest words you can hear.
|
||||
|
||||
Note: So let's start there.
|
||||
|
||||
---
|
||||
|
||||
### Is there already a module for that?
|
||||
|
||||
|
||||
[drupal.org/project/project_module](https://www.drupal.org/project/project_module)
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
Note: I definitely recommend changing core compatibility to something reasonable, Drupal 10, to start. And Status to "All projects", not just Full, non-sandbox projects, if you're ready to write a module. A sandbox may be a great start. And then allow any version. Then put in your key words and search. Remove the version— perhaps your best bet is porting an existing module. Use lots of different keywords.
|
||||
|
||||
---
|
||||
|
||||
* Do the same searches on an Internet-wide search with “Drupal” and “module” included as keywords.
|
||||
* Ask in IRC: #drupal-support, #drupal, and #drupal-contribute (in that order and over some time, even a few days)
|
||||
* Er, i meant the Slack equivalents #support, #general, #contribute, see https://www.drupal.org/slack
|
||||
|
||||
---
|
||||
|
||||
Take note of everything you use to search for a module.
|
||||
|
||||
Note: This is how people in the same situation will find your module. Currently we are pouring our notes into Logseq, and they'll be public soon.
|
||||
|
||||
---
|
||||
|
||||
##### There's a module that *almost* does exactly what you want
|
||||
|
||||
* Contribute a patch!
|
||||
* Port it to Drupal 8/9!
|
||||
|
||||
Note: Even if your patch is not accepted nor is there any way given to build on the module, you can fork the module— maintain your own copy. Indeed, this is the standard way of contributing now, with an Issue Fork.
|
||||
|
||||
---
|
||||
|
||||
](https://www.drupal.org/project/comment_notify/issues/2850935)
|
||||
|
||||
---
|
||||
|
||||
|
||||
](https://www.drupal.org/project/comment_notify/issues/2976478)
|
||||
|
||||
Note: This strategy is not without risks. David was made a maintainer of Comment Notify, and now routinely fixes issues there all himself. Still, that's generally better for *everyone* than to make your own module with duplicate functionality.
|
||||
|
||||
---
|
||||
|
||||
Act Two
|
||||
|
||||
### How Not To Have to Make a Whole Module
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Be a part of something bigger
|
||||
(but not as big as all of Drupal)
|
||||
|
||||
#### Commerce
|
||||
#### Extra Field
|
||||
#### ECA
|
||||
#### Search API (and friends)
|
||||
|
||||
Note: Build on or with some major —and with luck join a community of
|
||||
|
||||
----
|
||||
|
||||
##### Example: BEF Links Filter
|
||||
|
||||
[drupal.org/project/bef_links_filter](https://www.drupal.org/project/bef_links_filter)
|
||||
|
||||
Search API's friends include Facets and Better Exposed Filters
|
||||
|
||||
Note: By extending BEF Links module, we were able to get a lot of power— with a much better user experience, thanks to our ~250 lines of code altogether.
|
||||
|
||||
----
|
||||
|
||||
#### Look for plugin opportunities
|
||||
|
||||
Literally, look for plugins,
|
||||
|
||||
in `src/Plugin` of whatever modules you are operating in the vicinity of.
|
||||
|
||||
BEF Links Filter is a `better_exposed_filters` plugin in about 250 lines of code altogether.
|
||||
|
||||
|
||||
Note: Doing your own by extending an existing plugin or copying and modifying an existing plugin is probably the highest impact to effort ratio.
|
||||
|
||||
---
|
||||
|
||||
Act Three
|
||||
|
||||
### How To Figure Out How To Make a Module
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### When to make a module
|
||||
|
||||

|
||||
|
||||
Note: You've identified to the best of your ability that there's definitely not something out there that does what you want to do. I personally do not advocate introspection at this point: Why am i trying to do something that no one else is trying to do? Credit: lego heart is credited to Llama-Muffin-Kelly on DeviantArt but only see it on Pinterest
|
||||
|
||||
---
|
||||
|
||||
### Steal, and keep stealing
|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
Note: If you decide your module should have one of those button links you see at the top right of a bunch of pages in Drupal's administration, you *don't even need to know* that they are called "Action Links" and find a tutorial on making them. You can just go look in the code of a module you know has them, grep for the label, and steal the code around it.
|
||||
|
||||
----
|
||||
|
||||
|
||||

|
||||
|
||||
Note: Grep. Even when i am fully using an IDE for everything else, i grep in the regular command line when looking for text in a file. This habit is probably fueled more by failing to tell the IDE to index Drupal core and contrib modules more than anything else.
|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Building blocks
|
||||
|
||||
* Hooks
|
||||
* Form alter
|
||||
* Node insert
|
||||
* Plugins
|
||||
* Block
|
||||
* Formatter
|
||||
* Services
|
||||
* Route subscriber
|
||||
* Event subscriber
|
||||
|
||||
Note: The three main ways to mess with Drupal 8 and 9: hooks, plugins, and services, with a couple examples in each. Both examples of what technically to do and how to do general things. For example: Doing something with a form? You want hook_form_alter() or one of its variants.
|
||||
|
||||
---
|
||||
|
||||
How to figure out how to make a module
|
||||
|
||||
## Learning to learn
|
||||
|
||||
* Drupal documentation
|
||||
* Drupal contributed modules
|
||||
* Drupal core and *its* modules
|
||||
* Debugger
|
||||
* Drupal forums and issues
|
||||
* Drupal.StackExchange.com
|
||||
* The rest of the Internet
|
||||
* Code search / grep
|
||||
|
||||
Note: Where to start if i don't cover it in this session. And the debugger to more quickly find methods and functions, or even step through code, in contributed modules, core, and the module you're working on!
|
||||
|
||||
---
|
||||
|
||||
|
||||
### Building a Contrib-Worthy Modern Drupal (10, 11, 12…) Module
|
||||
|
||||
#### What module to make?
|
||||
|
||||
* One you need.
|
||||
* One not already made!
|
||||
|
||||
Note: To summarize: ^^
|
||||
|
||||
---
|
||||
|
||||
#### Write up what you plan to do
|
||||
|
||||
[groups.drupal.org/contributed-module-ideas](https://groups.drupal.org/contributed-module-ideas)
|
||||
|
||||
Note: Is one place
|
||||
|
||||
---
|
||||
|
||||
File issues for your own modules.
|
||||
|
||||
Note: It helps you think through what you are planning to do, it makes features and bugs more discoverable by other people, if you do not get to it right away there is a chance someone else will, and you (and anyone else who helps) get Drupal.org issue credit for that (you get no credit for contributing the actual module).
|
||||
|
||||
---
|
||||
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
```yaml
|
||||
name: "Project Copyright"
|
||||
type: module
|
||||
description: "Generate a block with the copyright leyend."
|
||||
core_version_requirement: ^8 || ^9 || ^10 || ^11 || ^12
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Drupal\copyright\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
|
||||
/**
|
||||
* Provides a block with the copyright legend.
|
||||
*
|
||||
* @Block(
|
||||
* id = "copyright_block",
|
||||
* admin_label = @Translation("Copyright"),
|
||||
* )
|
||||
*/
|
||||
class Copyright extends BlockBase {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function build() {
|
||||
return [
|
||||
'#markup' => $this->t('Copyright © @year All rights reserved', ['@year' => date('Y')]),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
|
||||
Note: Hooks are magic portals that let any module appear in another part of Drupal and do something. More technically, a hook is tied to some sort of Drupal event and is an opportunity for our module to take action. There were 251+ hooks in Drupal 7 core. After a concerted effort in the development of Drupal 8 to remove hooks and replace them with more modern and widespread (outside Drupal) programming practices such as plugins and services... There are now 288 hooks in Drupal 8.8. To be fair, we moved some big contributed modules like Views into Drupal core ... but even after that, we've added 25 hooks to core since Drupal 8.2 (and only deprecated 9, which are removed in Drupal 9). Hooks are still very much a part of Drupal. Every contributed module can provide hooks, too.
|
||||
|
||||
|
||||
---
|
||||
|
||||
Hooks work by naming convention.
|
||||
|
||||
To implement a hook, take the 'hook' part off the hook name and replace it with your module's (machine) name.
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
Most of these links go to a page on [Drupal's API reference which is also a great place to go for an overview](https://api.drupal.org/api/drupal/9.0.x) of what tools are available to you as you pick through the pieces Drupal offers and assemble your module.
|
||||
|
||||
https://api.drupal.org/api/drupal/core%21core.api.php/group/extending/
|
||||
|
||||
---
|
||||
|
||||
### Key hooks
|
||||
|
||||
* [hook form_alter](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21form.api.php/function/hook_form_alter/9.0.x )
|
||||
* [hook_entity_extra_field_info](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_extra_field_info/9.0.x ) + a 'field' site builders can use in entity view modes, such as to combine entity data and format it for display. Or you can replace those three hooks with one plugin by using the [Extra field module](https://www.drupal.org/project/extra_field )
|
||||
|
||||
### All the hooks
|
||||
|
||||
* [api.drupal.org/api/drupal/core!core.api.php/group/hooks](https://api.drupal.org/api/drupal/core!core.api.php/group/hooks/)
|
||||
|
||||
|
||||
Note: A note on all these links: I've linked to the Drupal 9.0 version. These hooks all work in Drupal 8.x also. Drupal.org [inadvertently for quite a while treated 8.2 as the end-all-and-be-all version of Drupal](https://www.drupal.org/project/apidrupalorg/issues/3085999 ); this has been mitigated and is being fixed but Google is still likely to take you to 8.2 when searching for documentation on a hook. Just switch to the version you're using, or the latest version of Drupal if
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### The Rest of the Internet
|
||||
|
||||
* Duck Duck Go (!g for Google results)
|
||||
* [ddg.co](https://duckduckgo.com/)
|
||||
* [agaric.coop/blog](https://agaric.coop/blog)
|
||||
* Your own notes
|
||||
|
||||
---
|
||||
|
||||
### Copy or have technology copy for you
|
||||
|
||||
* A module that was generated with Drupal Console https://www.drupal.org/project/ckeditor_youtube/ - simple and used by many, and slowly got more complex
|
||||
|
||||
Note: Shows how a lot of this is boilerplate.
|
||||
|
||||
|
||||
---
|
||||
|
||||
### Field Formatter
|
||||
|
||||
|
||||
* A module bringing in a PHP library and getting crazy (started with simple field formatter, can use this or another module to demo that) - https://drupal.org/project/inotherwords
|
||||
|
||||
Note: @TODO bring in, cleaned up and not confusing
|
||||
|
||||
---
|
||||
|
||||
### Services: Event Subscriber
|
||||
|
||||
https://gitlab.com/find-it-program-locator/findit_library_sync/-/blob/8.x-1.x/migrations/findit_library_sync_events.yml#L5
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Why contribute?
|
||||
|
||||
* Right thing to do
|
||||
* I asked you to
|
||||
* People may contribute to it
|
||||
* Someone may take it over and upgrade it or improve it greatly
|
||||
|
||||
|
||||
---
|
||||
|
||||
[](https://www.drupal.org/project/workflow_buttons/issues/3120524)
|
||||
|
||||
Note: Or someone may make a tiny improvement that makes everyone's lives better.
|
||||
|
||||
---
|
||||
|
||||
## Nice touches
|
||||
|
||||
`workflow_buttons.info.yml`
|
||||
|
||||
```diff
|
||||
type: module
|
||||
description: 'Provide workflow buttons for content moderation instead of a select dropdown of states.'
|
||||
core_version_requirement: ^8 || ^9
|
||||
core: 8.x
|
||||
+configure: workflow_buttons.settings
|
||||
|
||||
dependencies:
|
||||
- drupal:system (>=8.4)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### How to develop while sharing the same code you're using
|
||||
|
||||
Your module `composer.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "drupal/cyborgtranslate",
|
||||
"description": "Trigger Google translate and Drupal interface translation at the same time, allowing sections of your site's localization to be done by humans and the rest by machines.",
|
||||
"keywords": ["drupal", "translation", "multilingual", "localization", "google translate"],
|
||||
"type": "drupal-module",
|
||||
"license": "GPL-2.0+",
|
||||
"homepage": "https://www.drupal.org/project/cyborgtranslate",
|
||||
"minimum-stability": "dev",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/cyborgtranslate",
|
||||
"source": "https://gitlab.com/agaric/drupal/cyborgtranslate/tree/8.x-1.x"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: Composer makes a lot of stuff seem more complicated, but it makes it easier to contribute. Trust me... this will only be three screens of gibberish. It's also possible to read from other sources, not just Drupal.org. In this case, for example, we are getting the project from our GitLab mirror, which we have so people can submit merge requests if they would like.
|
||||
|
||||
---
|
||||
|
||||
Your project root `composer.json`:
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"drupal/core": "^8.8.0",
|
||||
"drupal/cyborgtranslate": "dev-8.x-1.x as 1.x-dev",
|
||||
"drush/drush": "^9.0"
|
||||
},
|
||||
"repositories": {
|
||||
"drupal": {
|
||||
"type": "composer",
|
||||
"url": "https://packages.drupal.org/8"
|
||||
},
|
||||
"drupal/cyborgtranslate": {
|
||||
"type": "git",
|
||||
"url": "git@gitlab.com:agaric/drupal/cyborgtranslate.git"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Examples for developers project
|
||||
|
||||
[drupal.org/project/examples](https://www.drupal.org/project/examples)
|
||||
|
||||
Note: It's like it was written just for you.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
Drupal.org/planet to keep up to date with what is going on in the Drupal world.
|
||||
Drupal.tv for recording of talks at different conferences.
|
||||
Drupical.com to find out about events happening in your city.
|
||||
The official Drupal API documentation.
|
||||
The Drupal Slack to get community support.
|
||||
A video series by OSTraining on YouTube.
|
||||
Drupalize.Me for high quality (paid) material.
|
||||
UnderstandDrupal.com shameless plug
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||

|
||||
agaric.coop/wtnamft · <a href="mailto:ask@agaric.coop">ASK@AGARIC.COOP</a>
|
||||
|
||||
Note: It's a big wild world out there. Bite off a piece you can chew. Links for all of this and more on the session page.
|
||||
|
||||
---
|
||||
|
||||
To be continued…
|
||||
|
||||
Note: Let me know what you build!
|
||||
|
||||
</textarea>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="./dist/reveal.js"></script>
|
||||
|
||||
<script src="./mermaid/dist/mermaid.min.js"></script>
|
||||
|
||||
<script src="./plugin/markdown/markdown.js"></script>
|
||||
<script src="./plugin/highlight/highlight.js"></script>
|
||||
<script src="./plugin/zoom/zoom.js"></script>
|
||||
<script src="./plugin/notes/notes.js"></script>
|
||||
<script src="./plugin/math/math.js"></script>
|
||||
<script>
|
||||
function extend() {
|
||||
var target = {};
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
for (var key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
// default options to init reveal.js
|
||||
var defaultOptions = {
|
||||
controls: true,
|
||||
progress: true,
|
||||
history: true,
|
||||
center: true,
|
||||
transition: 'default', // none/fade/slide/convex/concave/zoom
|
||||
slideNumber: true,
|
||||
highlight: {
|
||||
highlightOnLoad: false
|
||||
},
|
||||
plugins: [
|
||||
RevealMarkdown,
|
||||
RevealHighlight,
|
||||
RevealZoom,
|
||||
RevealNotes,
|
||||
RevealMath
|
||||
]
|
||||
};
|
||||
|
||||
// options from URL query string
|
||||
var queryOptions = Reveal().getQueryHash() || {};
|
||||
|
||||
var options = extend(defaultOptions, {"_":["2024-nedcamp-when-not-a-module-make-and-maintain.md"],"static":true}, queryOptions);
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
Reveal.initialize(options);
|
||||
Reveal.addEventListener('ready', function (event) {
|
||||
const blocks = Reveal.getRevealElement().querySelectorAll('pre code:not(.mermaid)');
|
||||
const hlp = Reveal.getPlugin('highlight');
|
||||
blocks.forEach(hlp.highlightBlock);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
const mermaidOptions = extend({ startOnLoad: false }, {"themeVariables":{"lineColor":"#fff"}});
|
||||
mermaid.startOnLoad = false;
|
||||
mermaid.initialize(mermaidOptions);
|
||||
const cb = function (event) {
|
||||
mermaid.init(mermaidOptions, '.stack.present > .present pre code.mermaid');
|
||||
mermaid.init(mermaidOptions, '.slides > .present:not(.stack) pre code.mermaid');
|
||||
}
|
||||
Reveal.addEventListener('ready', cb);
|
||||
Reveal.addEventListener('slidetransitionend', cb);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue