Drupal Markup Engine ==================== The Drupal Markup Engine (or DME as I'll refer to it from now on) allows you to define tags for use inside of node content that do almost anything you could wish for - allowing users to do such things as to specify where images should be placed in the text, specify that certain text is a spoiler and shouldn't be easily hidden, or to safely allow users to reference video or other resources from other sites. Tags can either enclose text (like text) or not (like ). The dme works by being a filter that can be set up with other input filters. It checks other modules looking for hook_dme_tags() hooks and asking them for tags that the module supports. Once it runs into a tag when filtering, it then calls the hook a second time with parameters from the tag, expecting the hook to return text that it replaces the original tag with. The tag processing is in the context of the node being processed, so the processing of tags can include referencing related nodes or imagefields inside of the node itself. The dme_test_module that is included with this module contains a number of example tags that you can inspect in addition to reading this documentation. hook_dme_tags($op, $tag = '', $nid = 0, $params = array()) $op is a string, either 'list' or 'call'. If list, the dme wants the list of tags the function supports. If call, the dme wants the hook to process a tag. $tag is a string, and is the 'name' from the tag definition of the tag being processed. $nid is the node id of the text being processed. $params is an array of parameters in the tag - restricted by the parameters that the tag definition allows. ------------------- Tag definitions When hook_dme_tags is called with the $op = 'list', it wants a list of the various tags that are supported by your module, as an array of arrays. Each tag definition array should contain the following items, all of which are required except for description: tag - string - This is the tag that the user inserts into their module. If it says something like 'tag' => 'spoiler', then the user would have entered as the tag. module - string - the name of this module. type - string - One of 'hook', 'function', or 'node' - indicating what type of tag handler to call. If the value is 'hook', then when the dme encounters the tag, it will call hook_dme_tags with an $op of 'call'. If the value is 'function', then it will call the function in 'name' with the text enclosed by the tag as the first parameter. If the value is 'node', then the hook will insert the value returned by calling the theme function in 'name' on the node declared by the nid attribute of the tag. (For example, if you had the tag named 'bar' set up as a 'node' type that had a 'name' attribute of 'test_theme', then if you had in the text, it would insert the result of calling theme("test_theme", node_load(27)). ) name - string - The name of the tag handler. If the tag is of type 'hook', then this is the string that is passed in on the hook_dme_tags('call') function call. If it's type 'function', then this is the name of the function it will call, and if it's type 'node' then this is the name of the theme function it will call. It's suggested that if the type is 'hook', that you leave the name the same as the tag for clarity. allowed_attributes - string or array - This item indicates which attributes or parameters that are entered into the tag are passed on to the hook, function, or theme function. If the value is 'none' than none are - they're all ignored. If the value is 'all' than every attribute is passed along. Otherwise, the value should be an array of attribute names that you want to have passed to the tag handler. For instance, if you had an image tag that displayed an image field in the node body, you might set the allowed_attributes to array('index', 'size', 'align') so that the user could specify something like . However, if the user tried to set something like or other sort of shennanigans, the test attribute and it's value would never reach the tag handler, just the index and size values. Numeric values don't require quotes as part of a tag, but string values do - although numeric values in quotes work just fine. So, index=0 and index="0" both mean the same thing, but name="Albert" is correct where name=Albert is not. description - string - This is a description of your tag for the users, printed out as the filter help underneath the node body (or whichever). ------------------ Tag handlers Hook - If the hook_dme_tags is being called with the node information, then the $tag parameter will hold the name attribute from the tag definition of the tag that was used, the $nid will hold the node id of the text they're processing, and $params will be an array of any attributes written into the tag body, minus anything not allowed in the tag's allowed_attributes. Additionally if the tag encloses other text, the $params array will contain that text under the index 'dme_inner_text'. (And if that text contains any dme tags of it's own, it will already have been handled.) In the DME Test Module example module, the 'bold', 'caps', and 'testhook' tags are good examples to look at for this sort of handler. Function - For function tags, the dme uses call_user_func_array() to call a given function. Although call_user_func_array takes an array of the arguments to the function it's calling, it doesn't use numeric order or alphabetical order, but seems to use the order that items were added to the array to decide which arguments to use in which order. The code is set up to have the enclosed text of the tag as the first parameter, but beyond that what order things will be passed into the function is undetermined. I suggest setting allowed_attributes to 'none' or to only allow one attribute, as you may need. If you need more than one attribute, then what you probably want to do is to write a hook instead, and pass the values in the correct order that way. In the DME Test Module example module, the 'rot13' tag is a good example to look at for this sort of handler. Theme - The same restrictions on array order apply for Theme as Function, except that the code will guarentee that the first attribute is the name of the tag from the tag definition's name field, followed by the loaded node, and followed by anything else. Generally you'll want to severely restrict the attributes as well, and if the situation requires a more complex set of attributes, use a hook and your own code to set the arguments to the theme function in the right order. In the DME Test Module example module, the 'node_theme' tag is a good example to look at for this sort of handler.