{"id":19474610,"url":"https://github.com/tomasc/hashtags","last_synced_at":"2025-04-25T12:31:53.441Z","repository":{"id":56876004,"uuid":"66301037","full_name":"tomasc/hashtags","owner":"tomasc","description":"Rails engine to facilitate inline text hashtags.","archived":false,"fork":false,"pushed_at":"2019-03-04T16:44:47.000Z","size":255,"stargazers_count":0,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T17:18:16.228Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomasc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-08-22T19:15:15.000Z","updated_at":"2020-04-26T03:05:59.000Z","dependencies_parsed_at":"2022-08-20T22:00:50.188Z","dependency_job_id":null,"html_url":"https://github.com/tomasc/hashtags","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasc%2Fhashtags","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasc%2Fhashtags/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasc%2Fhashtags/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasc%2Fhashtags/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomasc","download_url":"https://codeload.github.com/tomasc/hashtags/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250817804,"owners_count":21492226,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T19:25:51.770Z","updated_at":"2025-04-25T12:31:52.739Z","avatar_url":"https://github.com/tomasc.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hashtags\n\n[![Build Status](https://travis-ci.org/tomasc/hashtags.svg)](https://travis-ci.org/tomasc/hashtags) [![Gem Version](https://badge.fury.io/rb/hashtags.svg)](http://badge.fury.io/rb/hashtags) [![Coverage Status](https://img.shields.io/coveralls/tomasc/hashtags.svg)](https://coveralls.io/r/tomasc/hashtags)\n\nRails engine to facilitate inline text hashtags.\n\n- hashtags are entered inline in text, for example as `@tomasc`, `#location:Home(12345)` or `$my_variable`\n- when rendered, they are replaced by actual values, for example HTML tags, images, links etc.\n\nAdditionally:\n\n- the user can be assisted with a dropdown triggered by a special character (`#`, `@`, `$`, ...)\n- a Mongoid field option add support for `.to_markup` and `.to_hashtag` methods and more\n- hashtags typically have `cache_key` defined on class so corresponding fragment cache can be easily expired\n\nTODOs:\n\n- There's an implicit support for Mongoid, but it should be very easy to make that conditional ev. add support for other ORMs or libs such as Virtus etc.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'hashtags'\n```\n\nAnd then execute:\n\n```\n$ bundle\n```\n\nOr install it yourself as:\n\n```\n$ gem install hashtags\n```\n\n## Usage\n\nThe three following types are included in this gem, however the gem's design allows for definition of new types and their subclassing.\n\n### Hash tag types\n\n#### User hash tag\n\n```\n@tomasc\n```\n\n#### Resource hash tag\n\nThese typically include human-readable version of the resource (in the example below it would be `Home`).\n\n```\n#location:Home(12345)\n```\n\n#### Variable hash tag\n\n```\n$number_of_users\n```\n\n### Adding new hash tags in your application\n\nThe following are quick examples. It is advised to read the source code of `Hashtags::User`, `Hashtags::Resource` and `Hashtags::Variable` and their superclass `Hashtags::Builder` in order to fully understand the possibilities and flexibility of this gem.\n\n#### User\n\nSee `Hashtags::User` and override its methods on your subclass as necessary. Typically it would be at least the following:\n\n```ruby\nclass UserTag \u003c Hashtags::User\n  def self.resource_class\n    # User\n  end\n\n  def self.tag_attribute\n    # name of attribute to be used in the tag\n    # @\u003ctag_attribute\u003e\n    # for example :username\n  end\n\n  def self.result_attribute\n    # the tags will be replaced by this attribute\n    # for example :full_name\n  end\n\n  def self.resources_for_query(query)\n    # return resources matching query\n    # this will be called from the controller as user types\n  end\n\n  def resource(tag_attribute_value)\n    # this should find and return resource object\n    # self.class.resource_class.find(value)\n  end\nend\n```\n\nImplement the `values` class method instead of the `resources_for_query` to preload values.\n\n#### Resource\n\nSee `Hashtags::Resource` and override its methods on your subclass as necessary. Typically it would be at least the following:\n\n```ruby\nclass LocationTag \u003c Hashtags::Resource\n  def self.resource_class\n    # Location\n  end\n\n  def self.tag_attribute\n    # name of attribute to be used in the tag\n    # #\u003ctag_attribute\u003e(id)\n    # for example :to_s\n  end\n\n  def self.result_attribute\n    # the tags will be replaced by this attribute\n    # for example :to_s\n  end\n\n  def self.resources_for_query(query)\n    # return resources matching query\n    # this will be called from the controller as user types\n  end\n\n  def resource(value)\n    # this should find and return resource object\n    # self.class.resource_class.find(value)\n  end\nend\n```\n\nImplement the `values` class method instead of the `resources_for_query` to preload values.\n\n#### Variable\n\nSee `Hashtags::Variable` and override its methods on your subclass as necessary. Typically it would be at least the following:\n\n```ruby\nclass VariableTag \u003c Hashtags::Variable\n  def self.values(hashtag_classes = Hashtags::Variable.descendants)\n    # %w(\n    #   variable_1\n    #   variable_2\n    # )\n  end\n\n  def markup(match)\n    # case name(match)\n    # when 'variable_1' then 'foo'\n    # when 'variable_2' then 'bar'\n    # end\n  end\nend\n```\n\n### Usage in an app\n\n#### Core\n\n```ruby\nstr = 'Current document: #doc:Foo(123).'\nHashtags::Builder.to_markup(str) # =\u003e 'Current document: Foo.'\n```\n\nSince the hashtags might contain human-readable values (as in the `Resource` tags), it is often helpful to update them:\n\n```ruby\ndoc.title = 'Bar'\nHashtags::Builder.to_hashtag(str) # =\u003e 'Current document: #doc:Bar(123).'\n```\n\nOptionally, a list of only/except classes can be specified, useful for example for limiting available hashtags in certain situations.\n\n```ruby\nHashtags::Builder.to_markup(str, only: [LocationTag])\nHashtags::Builder.to_hashtag(str, except: [UserTag])\n```\n\n#### With Mongoid Extension\n\nIn case you are using Mongoid, you can use the `hashtags` options to enable hashtags processing and additional helpers. The hashtags will be also automatically processed whenever you save your data to the database (using the above-mentioned `to_hashtag` method).\n\n```ruby\nclass MyDoc\n  include Mongoid::Document\n  field :text, type: String, hashtags: true # or { only: … } or # { except: … }\nend\n\nmy_doc.text.to_markup # =\u003e field value with hashtags converted to markup\nmy_doc.text.to_hashtag # =\u003e field value with hashtags updated\n```\n\nNext to that the following helper class methods will be defined:\n\n```ruby\nMyDoc.hashtags['text'].dom_data # =\u003e outcome of builder's dom_data method\nMyDoc.hashtags['text'].help # =\u003e outcome of builder's help method\nMyDoc.hashtags['text'].options # =\u003e hashtags builder options { only: … } or { except: … }\n```\n\n#### With JS textcomplete plugin\n\nFinally, it is fairly straightforward to add support for JS textcomplete that assists the user when inserting tags.\n\nRequire the `hashtags` javascript.\n\n```javascript\n// application.js\n//= require hashtags\n```\n\nIn routes:\n\n```ruby\nmount Hashtags::Engine =\u003e '/'\n```\n\nOptionally add default CSS.\n\n```css\n/* application.css */\n/*\n *= require hashtags\n*/\n```\n\nIn a form:\n\n```slim\nfieldset\n  = form.text_area :text, data: form.object.class.hashtags['text'].dom_data\n  = render_hashtags_help_for(form.object.class, :text)\n```\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at \u003chttps://github.com/tomasc/hashtags\u003e.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomasc%2Fhashtags","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomasc%2Fhashtags","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomasc%2Fhashtags/lists"}