Module: Rinku

Extended by:
FFI::Library, Rinku
Included in:
Rinku
Defined in:
lib/rinku.rb,
lib/rinku-ffi.rb,
ext/rinku/rinku.c

Defined Under Namespace

Classes: Buf

Constant Summary collapse

VERSION =
"1.7.2"
INT2FIX(SD_AUTOLINK_SHORT_DOMAINS)
Proc.new do |link_text, link, block_cb|
  link_ruby = Rinku::Buf.new(link)
  block_cb.call(link_ruby[:data], link_ruby[:size], link_text)
end

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.skip_tagsObject

Returns the value of attribute skip_tags.



37
38
39
# File 'lib/rinku-ffi.rb', line 37

def skip_tags
  @skip_tags
end

Instance Attribute Details

#skip_tagsObject

Returns the value of attribute skip_tags.



3
4
5
# File 'lib/rinku.rb', line 3

def skip_tags
  @skip_tags
end

Class Method Details



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rinku-ffi.rb', line 39

def auto_link(text, mode=:all, link_attr=nil, skip_tags=nil, flags=0, &block)
  ob_c = ffi_create_buf()
  ob_ruby = Buf.new(ob_c)
  skip_tags_ruby = skip_tags || self.skip_tags || %w(a pre code kbd script)
  skip_tags_c = FFI::MemoryPointer.new(:pointer, skip_tags_ruby.size+1)
  skip_tags_ruby.each_with_index do |tag, i|
    skip_tags_c[i].put_pointer(0, FFI::MemoryPointer.from_string(tag))
  end
  skip_tags_c[skip_tags_ruby.size].put_pointer(0, nil)

  block_cb = Proc.new do |_in, _in_size, _out_bf|
    out = block.call(_in.read_string(_in_size))
    ffi_bufput(_out_bf, out)
  end

  count = ffi_autolink(ob_c, text, mode.nil? ? :all : mode, flags, link_attr, skip_tags_c, block.nil? ? nil : LINK_TEXT_CB, block_cb)
  if count == 0
    result = text
  else
    str_ptr = ob_ruby[:data]
    result = str_ptr.null? ? nil : str_ptr.read_string(ob_ruby[:size]).force_encoding(text.encoding)
  end
  ffi_release_buf(ob_c)
  result
end

Instance Method Details

call-seq:

auto_link(text, mode=:all, link_attr=nil, skip_tags=nil, flags=0)
auto_link(text, mode=:all, link_attr=nil, skip_tags=nil, flags=0) { |link_text| ... }

Parses a block of text looking for “safe” urls or email addresses, and turns them into HTML links with the given attributes.

NOTE: The block of text may or may not be HTML; if the text is HTML, Rinku will skip the relevant tags to prevent double-linking and linking inside ‘pre` blocks by default.

NOTE: If the input text is HTML, it’s expected to be already escaped. Rinku will perform no escaping.

NOTE: Currently the follow protocols are considered safe and are the only ones that will be autolinked.

http:// https:// ftp:// mailto://

Email addresses are also autolinked by default. URLs without a protocol specifier but starting with ‘www.’ will also be autolinked, defaulting to the ‘http://’ protocol.

  • ‘text` is a string in plain text or HTML markup. If the string is formatted in

HTML, Rinku is smart enough to skip the links that are already enclosed in ‘<a>` tags.`

  • ‘mode` is a symbol, either `:all`, `:urls` or `:email_addresses`,

which specifies which kind of links will be auto-linked.

  • ‘link_attr` is a string containing the link attributes for each link that

will be generated. These attributes are not sanitized and will be include as-is in each generated link, e.g.

 ~~~~~ruby
 auto_link('http://www.pokemon.com', :all, 'target="_blank"')
 # => '<a href="http://www.pokemon.com" target="_blank">http://www.pokemon.com</a>'
 ~~~~~

This string can be autogenerated from a hash using the Rails `tag_options` helper.
  • ‘skip_tags` is a list of strings with the names of HTML tags that will be skipped

when autolinking. If ‘nil`, this defaults to the value of the global `Rinku.skip_tags`, which is initially `[“a”, “pre”, “code”, “kbd”, “script”]`.

  • ‘flag` is an optional boolean value specifying whether to recognize

foo’ as a valid domain, or require at least one ‘.’. It defaults to false.

  • ‘&block` is an optional block argument. If a block is passed, it will

be yielded for each found link in the text, and its return value will be used instead of the name of the link. E.g.

~~~~~ruby
auto_link('Check it out at http://www.pokemon.com') do |url|
  "THE POKEMAN WEBSITEZ"
end
# => 'Check it out at <a href="http://www.pokemon.com">THE POKEMAN WEBSITEZ</a>'
~~~~~~


383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# File 'ext/rinku/rinku.c', line 383

static VALUE
rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
{
	static const char *SKIP_TAGS[] = {"a", "pre", "code", "kbd", "script", NULL};

	VALUE result, rb_text, rb_mode, rb_html, rb_skip, rb_flags, rb_block;
	struct buf *output_buf;
	int link_mode, count;
	unsigned int link_flags = 0;
	const char *link_attr = NULL;
	const char **skip_tags = NULL;
	ID mode_sym;

	rb_scan_args(argc, argv, "14&", &rb_text, &rb_mode,
		&rb_html, &rb_skip, &rb_flags, &rb_block); 

	Check_Type(rb_text, T_STRING);

	if (!NIL_P(rb_mode)) {
		Check_Type(rb_mode, T_SYMBOL);
		mode_sym = SYM2ID(rb_mode);
	} else {
		mode_sym = rb_intern("all");
	}

	if (!NIL_P(rb_html)) {
		Check_Type(rb_html, T_STRING);
		link_attr = RSTRING_PTR(rb_html);
	}

	if (NIL_P(rb_skip))
		rb_skip = rb_iv_get(self, "@skip_tags");

	if (NIL_P(rb_skip)) {
		skip_tags = SKIP_TAGS;
	} else {
		skip_tags = rinku_load_tags(rb_skip);
	}

	if (!NIL_P(rb_flags)) {
		Check_Type(rb_flags, T_FIXNUM);
		link_flags = FIX2INT(rb_flags);
	}

	output_buf = bufnew(32);

	if (mode_sym == rb_intern("all"))
		link_mode = AUTOLINK_ALL;
	else if (mode_sym == rb_intern("email_addresses"))
		link_mode = AUTOLINK_EMAILS;
	else if (mode_sym == rb_intern("urls"))
		link_mode = AUTOLINK_URLS;
	else
		rb_raise(rb_eTypeError,
			"Invalid linking mode (possible values are :all, :urls, :email_addresses)");

	count = rinku_autolink(
		output_buf,
		RSTRING_PTR(rb_text),
		RSTRING_LEN(rb_text),
		link_mode,
		link_flags,
		link_attr,
		skip_tags,
		RTEST(rb_block) ? &autolink_callback : NULL,
		(void*)rb_block);

	if (count == 0)
		result = rb_text;
	else {
		result = rb_str_new(output_buf->data, output_buf->size);
		rb_enc_copy(result, rb_text);
	}

	if (skip_tags != SKIP_TAGS)
		xfree(skip_tags);

	bufrelease(output_buf);
	return result;
}