Vue TipTap Editor - Can't add Link - tiptap

I'm using Vue3 & TypeScript to build a TipTap Wysiwyg editor.
Having issues when trying to use the Link Extension (other extensions such as StarterKit, Highlight and TaskList work fine).
Following the docs here: https://tiptap.dev/api/marks/link/
I installed the correct Link extension yarn add #tiptap/extension-link
imported import Link from '#tiptap/extension-link'
Added the Link extension using default options to the editor as such:
setup() {
const editor = useEditor({
extensions: [..., Link],
...
return {
editor,
}
}
Getting the following error:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'target') tiptap-extension-link.esm.js?2dbe:148
Any help will be greatly appriciated.

the extension-link is currently beta as you can see in the npm package site, so I believe there are currently bugs or missing parameters inside the package itself so to overcome that error you can pass the parameter yourself by configuring the Link like this:
Link.configure({
HTMLAttributes: { target: '_blank' },
linkOnPaste: false,
openOnClick: true,
}),
and by doing that, the package might not work as intended which as happened to me so you can make use of the fact that now your editor understands the tag but the logic to transformed to links automatically might not work so you should write the logic urself and pass the new text to the editor like this:
replaceUrls(string) {
const urlRegex = /(?<!href=")(?<!>)(((https?:\/\/)|(www\.))[^\s|<]+)/g
return string.replace(urlRegex, (url) => {
let hyperLink = url
if (!hyperLink.match('^https?://')) {
hyperLink = 'http://' + hyperLink
}
return (
'<a href="' + hyperLink + '" target="_blank" >' + url + '</a> '
)
})
}
and so you can update your Editor content with this command so you can transform the links into a tags that the editor understands
editor.commands.setContent(replaceUrls(editor.getHTML()), false)

Related

How to allow filtering of plain-text into HTML tags in NodeJS and PUG?

I have a web application in NodeJS and PUG/Jade. I want to separate the logic of the application, controlled by a developer, from the textual content, controlled by a marketing person and translators, while keeping all the source code integrated. (I asked about ways for this separation here and got no answers as of this writing).
For English, I use a JSON object en.json with:
{
"404": {
"notFound": "Page not found"
}
}
the controller loads it with:
let localText = require('./en.json');
res.status(404).render('404', {
text: localText
});
and the view renders it with:
h1 #{text['404'].notFound}
I would like to include links in the JSON object, such as:
{
"404": {
"notFound": "Page not found. Go to Twitter, maybe?"
}
}
NodeJS renders the page with the source code and not the link. I've fixed it temporarily by splitting into three:
{
"404": {
"notFound1": "Page not found. Go to",
"notFound2": "Twitter",
"notFound3": ", maybe?"
}
}
and the view:
h1 #{text['404'].notFound1} #[a(href="www.twitter.com") #{text['404'].notFound2}] #{text['404'.notFound3}
And it has now become a pain to maintain.
I understand from this page that I could create a filter to pre-process all links, e.g.:
options.filters = {
'my-own-filter': function (text) {
text = text.replace("Twitter", "Twitter")
/* all other replacements */
return text;
}
};
I couldn't find how to pass such filter options to the web application, whose only PUG line is app.set('view engine', 'pug');.
How can I pre-process a plain-text with NodeJS and Jade to populate links and display them nicely to the browser user?
You should be able to use unescaped string interpolation syntax (!{variable}) instead of the regular string interpolation syntax (#{variable}) to get the HTML to render correctly.
In your case:
h1 !{text['404'].notFound}
But keep in mind this word of warning from the Pug documentation:
Caution
Keep in mind that buffering unescaped content into your templates can be mighty risky if that content comes fresh from your users. Never trust user input!

How to set the default directory in Komodo from an an extension?

I'm working on a KomodoIDE/KomodoEdit extension that creates a new file and then opens it in a new editing tab using
...
var obsvc = Components.classes["#mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
...
Display.initWithPath(Target.path);
Display.append(what);
try {
obsvc.notifyObservers(null, 'open-url', "file://" + Display.path);
} catch (e) {
alert(e);
}
which works, but I would also like it to set Komodo's default directory to the same directory where this file lives, but I don't see a way to do that automatically.
I found the doCommand...
ko.commands.doCommand('cmd_openDirectory')
but this just launches a file dialog that asks the user to pick a directory. I'd like to do something to set it programatically using something like...
obsvc.notifyObservers(null, 'open-directory', "file://" + Display.path);
(which I know doesn't work but is sort of the idea).
I just discovered that the ko.places.manager object has a function to set the default Places window-pane directory. Below is an example of how I used it. The uri should be set to the full directory path and, in the case of Windows, backslashes should get escaped...
function SetPlace(ko, uri) {
try {
ko.places.manager.openDirURI("file:///" + uri.replace(/\\/g, "\\\\") );
} catch(e) {
alert("Could not set place to: " + uri.replace(/\\/g, "\\\\") + "\n" + e);
}
}
The nsIFile interface provides this:
// Get current working directory
var file = Components.classes["#mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("CurProcD", Components.interfaces.nsIFile);
The Komodo preferences service would also be an option:
var gprefs = Components.classes["#activestate.com/koPrefService;1"].
getService(Components.interfaces.koIPrefService).prefs;
gprefs.setStringPref("mruDirectory", "Display.path);
References
How do I get the path of the project folder
Getting Special Files
Komodo JS Macro - insert a relative path from the current editor file
mruDirectory
XPCOM API Reference
Komodo Profile Structure
Where does Komodo Store File Preferences
Getting/Setting a Komodo Preference

jquery.exif not load exif data from displayed photo

I cant get exif data from displayed image address
by click on photo You should see the exif data.
var someCallback = function(e) {
$('#cameraModel').val(e.Model);
$('#aperture').val(e.FNumber);
$('#created').val(e.DateTime);
$('#taken').val(e.DateTimeOriginal);
$('#copyright').val(e.Copyright);
$('#description').val(e.ImageDescription);
$('#artist').val(e.Artist);
$('#latitude').val(e.GPSLatitude[2]);
$('#longitude').val(e.GPSLongitude[2]);
//Uncomment the line below to examine the
//EXIF object in console to read other values
//console.log(e);
}
$('#fdd').on('click', function (e) {
alert($(this).attr("src"));
$(this).fileExif(someCallback);
});
please help... jsfiddle
From the fiddle, you're trying to use the fileExif method from https://github.com/sanisoft/jQuery-fileExif. You have several problems here:
You did not load the library in your fiddle (hence I had to guess which library you tried to use. Hint: read the console log, a message like Uncaught TypeError: Object [object Object] has no method 'fileExif' means you're missing code or trying the call on the wrong object)
That library cannot be loaded into a fiddle because it uses document.write. You can remove this code from the plugin to get it to work in a fiddle; it's only needed for IE:
document.write(
"<script type='text/vbscript'>\r\n"
+ "Function IEBinary_getByteAt(strBinary, iOffset)\r\n"
+ " IEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\n"
+ "End Function\r\n"
+ "Function IEBinary_getLength(strBinary)\r\n"
+ " IEBinary_getLength = LenB(strBinary)\r\n"
+ "End Function\r\n"
+ "</script>\r\n"
);
You are using the wrong library. That one is for file uploads, not image elements. You should try using the original jquery exif plugin, here: http://www.nihilogic.dk/labs/exifjquery/

How to Inject strings into tinyMCE from a Chrome Extension?

My background_script.js sends a message such as this:
function genericOnClick(info, tab) {
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendMessage(tab.id, {message: 'insert_string'}, function(){} );
});
};
The receiver.js catches this as:
function insert_string() {
var field = document.activeElement;
if(field.tagName == "IFRAME") {
field = field.contentDocument.activeElement;
}
field.value += 'This is my string';
}
Now, the extension works perfectly well on regular editable fields and textareas (it even works properly in tinyMCE on the textarea-tab!) but in the case of Visual-tab of tinyMCE I can't get this to work. I have noticed that the Visual-tab, as it's a WYSIWYG editor, is special and the only way I so far have figured out on how to solve this issue would be to mimic tinyMCE's behaviour for updating the Visual-tab. However, I would like to know if there's something simple and obvious I've missed. If not, how would I go about editing the Visual-tab contents?
All you need to issue to fill the editor is
tinymce.get('your_editor_id').setContent('This is my string');

Add a MediaPicker to the General Site Settings

The current project I'm on is utilizing tenant sites. With each site, we want the ability to change the logo through out the tenant site by modifying the its settings (on the admin page, settings > general).
I've added two text fields to the site settings by following this well documented tutorial. However, I'd like the user to be able to pick the logos using the media picker instead of typing in the path.
Currently I have a LogoBarSettings part with its record, driver and handler. I'm not sure how to add the media picker to the my LogoBarSettings and even if I did, must I also create another handler, driver, and record for it? I can't imagine I would but I'm pretty stuck at this point.
Can someone provide some direction on this?
Here is my LogoBarSettings
public class LogoBarSettings : ContentPart<LogoBarSettingsPartRecord>
{
public string ImageUrl
{
get { return Record.ImageUrl; }
set { Record.ImageUrl = value; }
}
public string ImageAltText
{
get { return Record.ImageAltText; }
set { Record.ImageAltText = value; }
}
}
The MediaPicker is invoked through Javascript, so you shouldn't need to change any of your model classes. When the MediaPicker is loaded for a page, it sets up a jQuery event handler for all form elements on the page. Triggering the event orchard-admin-pickimage-open will open the MediaPicker. Supply a callback function to capture the picked media.
Here is a quick example that you can run in Firebug or Chrome Developer Tools from a page which has the MediaPicker loaded, such as a Page editor:
$('form').trigger("orchard-admin-pickimage-open", {
callback: function(data) {
console.log(data);
}})
This should print something similar to this:
Object {img: Object}
img: Object
align: ""
alt: ""
class: ""
height: "64"
html: "<img src="/Media/Default/images/test.jpg" alt="" width="64" height="64"/>"
src: "/Media/Default/images/test.jpg"
style: ""
width: "64"
__proto__: Object
__proto__: Object
The BodyPart editor integrates Orchard's MediaPicker with TinyMce, so you can start looking at that module for a more complete example, specifically Modules\TinyMce\Scripts\plugins\mediapicker\editor_plugin_src.js.

Resources