010101 the favicon wasn't always showing inline

I noticed that and the styling disturbs me as well, I'll get this fixed 😇

Thanks for the other suggestions!

10 days later

Version 1.1.0 - June 1st, 2022

  • Added Rich image embeds feature. Disabled by default.
  • Changed Rich link previews now show the domain name of the destination website if the URL was a redirect instead of the domain name from the posted link.
  • Changed Any link longer than 2048 characters is now automatically blacklisted and cannot be previewed.
  • Fixed errors when inserting links longer than 255 characters.
  • Fixed blacklist/whitelist not being applied to HTTP redirect destination.
  • Fixed favicon not aligned properly with text.
  • Fixed post preview now debounced to avoid many requests and crawls being performed if a URL is typed by hand.
  • Fixed inline preview not switching to page title label when entering a link without ending slash.

This update also started collecting image Exif data, but this information is currently not displayed. It might be made visible in a future update.

You must run php flarum migrate immediately after performing the update. Trying to create discussions or posts before the migrations have run will lead to errors.


The new image embed feature is still experimental, any suggestion is welcome!

The reason I added this feature was primarily because it solves the usually unavoidable issue of page content jumping during image loading. When an image has rich preview available, it not only shows that data when hovering the image with the mouse, but it actually also sets the width/height into the page DOM, and with this the image will take the correct space into the page even before it's fully loaded.

A future update will bring link and image embeds even closer by allowing preview of links that point to images and other content types.

I also want to show some of the image Exif data when available, but I'm not entirely sure how realistic or useful this will be. Most image hosting services will strip that data from images, and the images that still have the Exif data could actually contain compromising information that you'd prefer not be easily available (like showing the geolocation of the picture on a map directly in the meta overlay). If anyone has some feedback on where Exif could be useful, all suggestions are welcome!

This is how the image embed overlay looks like in the current 1.1 version. On mouseover the image darkens and the text/buttons appear:

5 days later

If I install this, would it work for existing images that were uploaded through the FoF Upload and are not posted as a plain URL?

Do I have to uninstall/reconfigure FoF formatting which does similar stuff? For instance it formats YouTube videos, image and video URL-s, popular website URL-s (Amazon, etc.)?

How about the Inline Audio extension that shows a small audio play button that we like a lot on our forum?

OK, I purchased it and installed it. Seems nice and I hope it will fix the problems we have with the images and auto-scroll. However to me it seems it would do that only for newly added images after the extension was installed? Existing images don't get the overlay with the EXIF which makes me think it won't parse them and store their size?

I will add a way to generate embeds for existing posts in a future update. Right now only new posts or posts that have been edited will have their embeds updated. I have not entirely decided how to build the command because it will have to perform a lot of external requests and this could take a long time to complete, in particular if the website doesn't have a queue setup.

Embeds only affect the TextFormatter tags for URL (in practice, this means Autolink [not MediaEmbed, Autovideo or Autoaudio], Markdown links and bbcode URL tag) and IMG (Markdown image tag, bbcode image tag, and Autoimage).

The extension should correctly ignore everything inserted by MediaEmbed, Autovideo and Autoaudio, even if it has images inside of it. It will also not modify images inserted by FoF Upload with Full image or Image preview templates, but it will modify images inserted by FoF Upload with Markdown or bbcode image tags.

Ideally FoF Upload should do this itself for its own images inserted via the custom bbcode tags. My extension is designed for external images, but as long as the image URLs are absolute URLs and can be resolved from the Flarum server it should work fine with images that are hosted on the same server as Flarum as well.

    clarkwinkelmann I will add a way to generate embeds for existing posts in a future update.

    That would be awesome!

    clarkwinkelmann It will also not modify images inserted by FoF Upload with Full image or Image preview templates, but it will modify images inserted by FoF Upload with Markdown or bbcode image tags.

    Yeah I noticed that but luckily I switched to Markdown at some point since it seemed the most useful way, so I’m good with that.

    I’m wondering if you can somehow implement a YouTube box with inline player too? Because I think the MediaEmbed videos are the other thing besides images that is causing auto-scroll issues. I tested the RichEmbed YouTube and it’s OK but it opens the video in a new window. If it played in the box, I would gladly disable the MediaEmbed.

    Ultimately, it’s a nice extension, even if just for the image dimension cache, thank you! 👏🏻

      CyberGene I think the MediaEmbed videos are the other thing besides images that is causing auto-scroll issues

      That's what I also noticed. I could have a special embed that overrides MediaEmbed for some of my link embeds. YouTube is an obvious candidate. I'll see if that's feasible. This could also be an opportunity to not load the actual YouTube player at page load, but only if clicking the play button inside of my embed element.

        Teddan did you run php flarum migrate after updating my extension prior to the Flarum 1.3.1 update?

        For the error you see to happen, a different error probably happened the first time php flarum migrate was run after the extension update.

        You can safely delete the url_hash column in the kilowhat_rich_embeds table to try again.

        If a different error happens (like duplicate value insertion, or error creating index), can you share the error message and if possible a structure+data dump of the kilowhat_rich_embeds table?

        There's a very tiny tiny tiny risk of generating conflicting hashes if you have a large number of entries in the table already. But this is incredibly unlikely.

        If you have a lot of entries, the migration could also have failed due to timeout because it can take a lot of time to complete. Running the migrations via the command line should work around that issue.

          clarkwinkelmann
          I run php flarum migrate already. though it says nothing to migrate.

          So I just simply remove the extension temporarily to allow the update. But now when I tried to reinstall and enable in the admin panel, it reported error in the console which prevent it to be enabled:

          {
          "status": 500,
          "options": {
          "background": true,
          "url": "https://www.xn--fmrv2rkpbv8uymm.com/api/extensions/kilowhat-rich-embeds",
          "method": "POST",
          "body": {
          "enabled": true
          }
          },
          "xhr": {},
          "responseText": "<br />\n<b>Fatal error</b>: Uncaught UnexpectedValueException: The stream or file &quot;/www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/storage/logs/flarum-2022-06-07.log&quot; could not be opened in append mode: Failed to open stream: Permission denied in /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php:110\nStack trace:\n#0 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php(120): Monolog\Handler\StreamHandler-&gt;write()\n#1 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php(39): Monolog\Handler\RotatingFileHandler-&gt;write()\n#2 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/monolog/monolog/src/Monolog/Logger.php(344): Monolog\Handler\AbstractProcessingHandler-&gt;handle()\n#3 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/monolog/monolog/src/Monolog/Logger.php(712): Monolog\Logger-&gt;addRecord()\n#4 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/flarum/core/src/Foundation/ErrorHandling/LogReporter.php(32): Monolog\Logger-&gt;error()\n#5 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/flarum/core/src/Http/Middleware/HandleErrors.php(63): Flarum\Foundation\ErrorHandling\LogReporter-&gt;report()\n#6 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Next.php(51): Flarum\Http\Middleware\HandleErrors-&gt;process()\n#7 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/flarum/core/src/Http/Middleware/InjectActorReference.php(25): Laminas\Stratigility\Next-&gt;handle()\n#8 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Next.php(51): Flarum\Http\Middleware\InjectActorReference-&gt;process()\n#9 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/MiddlewarePipe.php(76): Laminas\Stratigility\Next-&gt;handle()\n#10 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/middlewares/request-handler/src/RequestHandler.php(84): Laminas\Stratigility\MiddlewarePipe-&gt;process()\n#11 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Next.php(51): Middlewares\RequestHandler-&gt;process()\n#12 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/middlewares/base-path-router/src/BasePathRouter.php(101): Laminas\Stratigility\Next-&gt;handle()\n#13 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Next.php(51): Middlewares\BasePathRouter-&gt;process()\n#14 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Middleware/OriginalMessages.php(36): Laminas\Stratigility\Next-&gt;handle()\n#15 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Next.php(51): Laminas\Stratigility\Middleware\OriginalMessages-&gt;process()\n#16 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/middlewares/base-path/src/BasePath.php(73): Laminas\Stratigility\Next-&gt;handle()\n#17 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Next.php(51): Middlewares\BasePath-&gt;process()\n#18 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/flarum/core/src/Http/Middleware/ProcessIp.php(24): Laminas\Stratigility\Next-&gt;handle()\n#19 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/Next.php(51): Flarum\Http\Middleware\ProcessIp-&gt;process()\n#20 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/MiddlewarePipe.php(76): Laminas\Stratigility\Next-&gt;handle()\n#21 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-stratigility/src/MiddlewarePipe.php(65): Laminas\Stratigility\MiddlewarePipe-&gt;process()\n#22 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/laminas/laminas-httphandlerrunner/src/RequestHandlerRunner.php(96): Laminas\Stratigility\MiddlewarePipe-&gt;handle()\n#23 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/flarum/core/src/Http/Server.php(44): Laminas\HttpHandlerRunner\RequestHandlerRunner-&gt;run()\n#24 /www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/public/index.php(26): Flarum\Http\Server-&gt;listen()\n#25 {main}\n thrown in <b>/www/wwwroot/www.xn--fmrv2rkpbv8uymm.com/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php</b> on line <b>110</b><br />\n",
          "response": null,
          "alert": {
          "type": "error",
          "content": [
          "糟糕,出错啦!请刷新页面重试。"
          ],
          "controls": false
          }
          }

          I am sorry I dont know how to reach to the data dump of an extension 😢

            Teddan this new error message says it can't write the actual error message to the log file, so we don't know what the real error is.

            Make sure Flarum can write to the <flarum>/storage/logs folder.

              clarkwinkelmann
              Now I think I get the real error here😂:

              request.js:173 POST https://www.xn--fmrv2rkpbv8uymm.com/api/extensions/kilowhat-rich-embeds 500
              (匿名) @ request.js:173
              (匿名) @ request.js:23
              (匿名) @ request.js:22
              e.request @ Application.tsx:503
              n.toggle @ ExtensionPage.tsx:234
              n.onchange @ Checkbox.js:61
              (匿名) @ withAttr.ts:14
              L.handleEvent @ render.js:888
              admin#/extension/kilowhat-rich-embeds:1 Uncaught (in promise) Hn {status: 500, options: {…}, xhr: XMLHttpRequest, responseText: '{"errors":[{"status":"500","code":"unknown"}]}', response: {…}, …}alert: content: Array(1)0: "糟糕,出错啦!请刷新页面重试。"length: 1[[Prototype]]: Array(0)at: ƒ at()concat: ƒ concat()constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()findLast: ƒ findLast()findLastIndex: ƒ findLastIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ includes()indexOf: ƒ indexOf()join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ lastIndexOf()length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {copyWithin: true, entries: true, fill: true, find: true, findIndex: true, …}[[Prototype]]: Objectcontrols: falsetype: "error"[[Prototype]]: Objectoptions: {background: true, url: 'https://www.xn--fmrv2rkpbv8uymm.com/api/extensions/kilowhat-rich-embeds', method: 'POST', body: {…}, deserialize: ƒ, …}response: {errors: Array(1)}responseText: "{\"errors\":[{\"status\":\"500\",\"code\":\"unknown\"}]}"status: 500xhr: XMLHttpRequest {readyState: 4, timeout: 0, withCredentials: false, abort: ƒ, onreadystatechange: ƒ, …}[[Prototype]]: Object
              Promise.then(异步)
              n.toggle @ ExtensionPage.tsx:241
              n.onchange @ Checkbox.js:61
              (匿名) @ withAttr.ts:14
              L.handleEvent @ render.js:888

                Teddan that's still not the real error 😅 That's what the client-side says when debug mode is disabled, it just says an error occurred and that more details are available in the log file on the server. If debug mode is enabled in config.php more details might appear in that error. But in any case if Flarum can write to the log file, everything needed should be in the log file (<flarum>/storage/logs).

                  Teddan yes "Rich Embeds for Images" is the setting that will cover it. It'll only work for new/edited posts though. I will try to get the import tool for existing posts ready soon.

                    Teddan it applies to new pictures only. And only those that are inserted as BBcode or Markdown.

                      Teddan do you have a link to a page where I could see one of your posts with markdown? Maybe a post that contains both one in markdown and one in bbcode format? Both should have the exact same output with the extension.

                      If you edited older posts, you need at least one character change to force Flarum to re-parse the post. So changing from Markdown to bbcode in an older post might have done the trick but only because it changed the (raw) content of the post and not actually because it's bbcode. You could try reverting to Markdown after using bbcode to see if it still works or stops working again.

                      a month later

                      Version 1.2.0 - July 24, 2022

                      • Added Scan command for import and update after permission changes
                      • Added Refresh command to mass-refresh embeds
                      • Added API-powered Flarum embeds (discussions+users)
                      • Added API-powered GitHub embeds (repos+issues+pulls)
                      • Added API-powered YouTube embeds (videos)
                      • Added API-powered Google Drive embeds (files)
                      • Added Embedded player on YouTube links
                      • Added Popover on links that failed rendering to give access to refresh controls
                      • Added MySQL version check during extension activation
                      • Changed Tweaked colors and margins
                      • Changed No longer proxying images to the same domain as Flarum
                      • Fixed Links containing ampersands wouldn't render as blocks

                      You must run php flarum migrate immediately after performing the update. Trying to create discussions or posts before the migrations have run will lead to errors.

                      If you get an error saying your MySQL version is unsupported, see workaround in MySQL requirements and please report your select version() as version SQL command output and I'll get it fixed ASAP.

                      Most of the new features are disabled by default. Visit the extension page in the admin panel to configure.

                      Check the documentation to find the requirements and instructions for each new feature https://kilowhat.net/flarum/extensions/rich-embeds As you might guess from their name, you need to configure access to the GitHub and/or Google APIs to enable the new features.

                      Just like in previous versions, the MediaEmbed feature from FoF Formatting has priority over regular links.
                      This means the new YouTube and Google Drive rich embeds can only be used when MediaEmbed is disabled.

                      A screenshot showing what it looks like with all of the new options enabled (in "separated" layout mode):

                      4 websites with API-powered embeds